<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> STM32 >> 瀏覽文章

        stm32與AT24C02的I2C通信總結(模擬時序)

        作者:明入如di   來源:明入如di的博客   點擊數:  更新時間:2014年05月18日   【字體:

        從51的時候就學習了I2C通信協議,但51的功能就那些,內部沒有集成I2C模塊,所以只能通過模擬I2C通信的時序來和EEPROM進行通信,stm32內部集成了I2C通信的片上外設,但由于內部I2C外設復雜和不穩定行,所以用的人不是很多,而基本上使用I2C的通信都是通過模擬時序的方式來實現的


        首先I2C是同步半雙工的通信方式,需要兩條線即可,SCL時鐘線,同步時鐘由主機產生,SDA數據線用來發送接收數據,任何時候只能一臺主機發送數據。
        在編程的時候碰到了很多問題,其中一項就是等待從機的應答程序
        開始的時候編寫如下
        void iic_wait_ack()   錯誤                                                   void iic_wait_ack()          正確的程序            
        {                                                                                  {
         SCL=1;                                                                        iic_sda_in();
        iic_sda_in();                                                                 SCL=1;
        delay_us(2);                                                                delay_us(2);
        SDA=1;                                                                       SDA=1;
        while(SDAIN);                                                            while(SDAIN);
        SCL=0;                                                                       SCL=0;
        }                                                                                   }
        程序運行的時候總是死在紅色部分的程序,后來用debug單步調試,慢慢的發現了規律,以下為個人觀點,不敢保證一定正確:
                            1.SDAIN只會在SCL為低電平的時候拉低
                            2.且在SCL保持高電平的時候,SDAIN比保持低電平
                            3.在SCL變為高電平之后,SDAIN才會拉高
         
        上圖為I2C通信的時序圖
         
        其中起始信號:在SCL為高電平時,SDA電平由高變低,且高電平SDA高電平持續時間要大于4.7us,在SCL由高電平變低時,SDA的低電平持續時間要大于4us
         
        終止信號:在SCL為高電平期間,SDA電平由低變高,且高電平持續時間大于4.7us,低電平持續時間大于4us
         
        起始信號和終止信號無論何時都是由主設備產生的
         
        數據幀:在SCL為高電平期間,SDA的電平保持穩定
         
        主向從寫數據

        期間地址為八位:其中高四位為固定位,bit3—bit1為可變位,最低位為操作位 為0時為寫操作,為1時是讀操作
        地址發送完成之后,等待從器件的應答信號,切記此時要將SDA配置為上拉輸入模式

        應答信號即為,SCL保持高電平時 SDA一直為低電平。
        然后再發送要寫入數據的地址,收到應答再寫入數據,最后是停止信號
         
        首先先配置IO口,PB10為SCL,PB.11為SDA
         
        #include
        void gpio_init()
        {
         RCC->APB2ENR|=1<<2;
         GPIOA->CRH&=0xfffff00f;
         GPIOA->CRH|=0x000008b0;
         GPIOA->ODR|=3<<9;
         
         RCC->APB2ENR|=1<<3;
         GPIOB->CRH&=0xfffff0ff;
         GPIOB->CRH|=0x00000300;
         GPIOB->ODR|=1<<10;
        }
         
        void iic_sda_out()//此時為主器件發送數據
        {
         RCC->APB2ENR|=1<<3;
         GPIOB->CRH&=0xffff0fff;
         GPIOB->CRH|=0x00003000;
         GPIOB->ODR|=1<<11;
        }
         
        void iic_sda_in()//此時為主器件接收數據或等待從器件發送應答信號
        {
         RCC->APB2ENR|=1<<3;
         GPIOB->CRH&=0xffff0fff;
         GPIOB->CRH|=0x00008000;
         GPIOB->ODR|=1<<11;
        }
         
        然后是為頭文件iic.h,如下
        #define iic_write 0xa0
        #define iic_read 0xa1
        void iic_start(void);//起始信號
        void iic_end(void);//終止信號
        void iic_senddata(u8 data);//主器件發送一個字節數據
        void iic_master_ack(void);//主機應答信號
        void iic_master_nack(void);//主機非應答信號
        void iic_wait_ack(void);//等待從機應答信號
        void iic_master_write(u8 type,u8 address,u8 data);
        u8 iic_master_read(u8 address);
        u8 iic_readdata(void);
         
        iic.c文件如下
        #include
        #include"gpio.h"
        #include"delay.h"
        #include"iic.h"
        #include"sys.h"
        void iic_start()
        {
         iic_sda_out();
         SDA=0;
         SCL=1;
         SDA=1;
         delay_us(5);
         SDA=0;
         delay_us(5);
        }
         
        void iic_end(void)
        {
         iic_sda_out();
         SCL=0;
         SDA=0;
         delay_us(2);
         SCL=1;
         delay_us(5);
         SDA=1;
         delay_us(5);
         SDA=0;
        }
         
        void iic_senddata(u8 data)
        {
         int i;
         iic_sda_out();
         for(i=7;i>=0;i--)
            {
             SCL=0;
        SDA=(data>>i);
        SCL=1;
        delay_us(5);
        SCL=0;
        }
        }
         
         
        void iic_master_ack()
        {
         iic_sda_out();
         SCL=0;
         SDA=0;
         SCL=1;
         delay_us(5);
         SCL=0;
         SDA=1;
        }
         
        void iic_master_nack()
        {
         iic_sda_out();
         SCL=0;
         SDA=1;
         SCL=1;
         delay_us(5);
         SCL=0;
        }
         
        void iic_wait_ack()
        {
         iic_sda_in();
         SDA=1;
         delay_us(1);
         SCL=1;
         delay_us(1);
         while(SDAIN);
         SCL=0;
         
        }
         
        void iic_master_write(u8 type,u8 address,u8 data)
        {
         iic_start();
         iic_senddata(type);
         iic_wait_ack();
         iic_senddata(address);
         iic_wait_ack();
         iic_senddata(data);
         iic_wait_ack();
         iic_end();
         delay_ms(10);
        }
         
        u8 iic_master_read(u8 address)
        {
         u8 dcb;
         iic_start();
         iic_senddata(0xa0);
         iic_wait_ack();
         iic_senddata(address);
         iic_wait_ack();
         iic_start();
         iic_senddata(0xa1);
         iic_wait_ack();
         dcb=iic_readdata();
         iic_master_nack();
         iic_end();
         return dcb;
        }
         
        u8 iic_readdata()
        {
          int k;
          u8 receive;
          iic_sda_in();
           for(k=7;k>=0;k--)
           {
            SCL=0;
        delay_us(2);
        SCL=1;
        receive<<=1;
        if(SDAIN==1)
        receive|=1<<0;
        else
        receive&=~(1<<0);
           }
           return receive;
        }
         
        主程序
         
        #include
        #include"delay.h"
        #include"usart1.h"
        #include"sys.h"
        #include"gpio.h"
        #include"iic.h"
        int main()
        {
         u8 temp;
         Stm32_Clock_Init(9);
         delay_init(72);
         gpio_init();
         usart1_init();
         iic_master_write(iic_write,0x00,0xdf);
         temp=iic_master_read(0x00);
         USART1->DR=temp;
         while(1);
        }
        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮