久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> STM32 >> 瀏覽文章

stm32與AT24C02的I2C通信總結(jié)(模擬時(shí)序)

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

從51的時(shí)候就學(xué)習(xí)了I2C通信協(xié)議,但51的功能就那些,內(nèi)部沒有集成I2C模塊,所以只能通過模擬I2C通信的時(shí)序來和EEPROM進(jìn)行通信,stm32內(nèi)部集成了I2C通信的片上外設(shè),但由于內(nèi)部I2C外設(shè)復(fù)雜和不穩(wěn)定行,所以用的人不是很多,而基本上使用I2C的通信都是通過模擬時(shí)序的方式來實(shí)現(xiàn)的


首先I2C是同步半雙工的通信方式,需要兩條線即可,SCL時(shí)鐘線,同步時(shí)鐘由主機(jī)產(chǎn)生,SDA數(shù)據(jù)線用來發(fā)送接收數(shù)據(jù),任何時(shí)候只能一臺(tái)主機(jī)發(fā)送數(shù)據(jù)。
在編程的時(shí)候碰到了很多問題,其中一項(xiàng)就是等待從機(jī)的應(yīng)答程序
開始的時(shí)候編寫如下
void iic_wait_ack()   錯(cuò)誤                                                   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;
}                                                                                   }
程序運(yùn)行的時(shí)候總是死在紅色部分的程序,后來用debug單步調(diào)試,慢慢的發(fā)現(xiàn)了規(guī)律,以下為個(gè)人觀點(diǎn),不敢保證一定正確:
                    1.SDAIN只會(huì)在SCL為低電平的時(shí)候拉低
                    2.且在SCL保持高電平的時(shí)候,SDAIN比保持低電平
                    3.在SCL變?yōu)楦唠娖街螅琒DAIN才會(huì)拉高
 
上圖為I2C通信的時(shí)序圖
 
其中起始信號(hào):在SCL為高電平時(shí),SDA電平由高變低,且高電平SDA高電平持續(xù)時(shí)間要大于4.7us,在SCL由高電平變低時(shí),SDA的低電平持續(xù)時(shí)間要大于4us
 
終止信號(hào):在SCL為高電平期間,SDA電平由低變高,且高電平持續(xù)時(shí)間大于4.7us,低電平持續(xù)時(shí)間大于4us
 
起始信號(hào)和終止信號(hào)無論何時(shí)都是由主設(shè)備產(chǎn)生的
 
數(shù)據(jù)幀:在SCL為高電平期間,SDA的電平保持穩(wěn)定
 
主向從寫數(shù)據(jù)

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

應(yīng)答信號(hào)即為,SCL保持高電平時(shí) SDA一直為低電平。
然后再發(fā)送要寫入數(shù)據(jù)的地址,收到應(yīng)答再寫入數(shù)據(jù),最后是停止信號(hào)
 
首先先配置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()//此時(shí)為主器件發(fā)送數(shù)據(jù)
{
 RCC->APB2ENR|=1<<3;
 GPIOB->CRH&=0xffff0fff;
 GPIOB->CRH|=0x00003000;
 GPIOB->ODR|=1<<11;
}
 
void iic_sda_in()//此時(shí)為主器件接收數(shù)據(jù)或等待從器件發(fā)送應(yīng)答信號(hào)
{
 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);//起始信號(hào)
void iic_end(void);//終止信號(hào)
void iic_senddata(u8 data);//主器件發(fā)送一個(gè)字節(jié)數(shù)據(jù)
void iic_master_ack(void);//主機(jī)應(yīng)答信號(hào)
void iic_master_nack(void);//主機(jī)非應(yīng)答信號(hào)
void iic_wait_ack(void);//等待從機(jī)應(yīng)答信號(hào)
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);
}
關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 免费在线视频一区二区 | 在线一级片 | 日韩欧美不卡 | 欧美日韩精品在线免费观看 | 国产精品视屏 | 91视频在线观看 | 久久精品1 | 久久小视频| 欧美日韩淫片 | 99精品久久久 | 中文字幕在线一区二区三区 | 欧美九九九 | 国产成人福利在线观看 | 91精品国产91久久久久久丝袜 | 欧美精品综合 | 精品一区二区在线视频 | 亚洲一区二区视频 | 欧美xxxⅹ性欧美大片 | 日本一区不卡 | 亚洲欧美在线一区 | 毛片一级片 | 一本大道久久a久久精二百 欧洲一区二区三区 | 懂色中文一区二区三区在线视频 | 国产精品一区二区日韩 | 欧美日韩中文字幕在线 | 99国产精品久久久久久久 | 欧美日韩国产在线 | 99精品网 | 欧美在线一区二区视频 | 国产一区二区三区四区 | 精品av | 不卡的av电影 | 中文字幕国产一区 | 国产福利二区 | 国产99久久久国产精品 | 久久久久网站 | 国产欧美精品区一区二区三区 | 一区二区三区在线免费看 | 久久亚洲一区二区 | jlzzjlzz欧美大全 | 在线欧美一区二区 |