快捷搜索:  汽车  科技

iic通信接收不到数据(IIC通信协议代码分享及调试过程中的一些小误区分享)

iic通信接收不到数据(IIC通信协议代码分享及调试过程中的一些小误区分享)发送数据://返回值为0表示应答成功,1表示非应答 uint8_t IIC_Ack(void) { uint8_t count; SDA_IN(); SCL=0; delay_us(3); SCL=1; delay_us(2); while(Read_SDA==1) { count ; if(count>250) { IIC_End(); return 1; } } SCL=0; //释放时钟线 return 0; } 小说明:这里定义了一个count,为的就是防止SDA接收不到低电平程序卡炸在这里。第三句SCL=0; delay_us(3);是先释放总线,等待SDA的低电平信号,但是亲测过,不加这两句也可以。停止信号://上升沿为停止信号 void IIC_End(void) {

1.前奏

很久没有更新博客了,hiahia,之前忙着考研,现在却忙着找工作,哎咦呦~,但也没事,研没考上也可以好好学学我感兴趣的东西,用这些来找工作也挺好,做自己喜欢的事情,研究生还是想考,等快到暑假再看吧。这段时间重新把以前学的东西又巩固了一遍,和我想的一样,以前的基础果然不牢。这次感觉花的时间挺久的就是IIC协议了,经过这次自己敲代码写,对协议的理解更加深了。所以想分享给大家,主要是代码,虽然网上有很多,但是就是想把自己的代码分享出来,当然,其中也有一些走过的小误区,可以给大家做一个参考,也可以让自己以后回写协议的时候有一个回忆参考。

2.IIC协议简单说明

开始信号:SCL为高电平时,SDA为下降沿;
停止信号:SCL为高电平时,SDA为上升沿;
应答信号:发送完一个字节后,当SCL为高电平时,读出的SDA为低电平;
发送数据:把SDA数据一位一位准备好,SCL为上升沿时一位一位地写入数据,方向为高位低位
接收数据:SCL为下降沿时一位一位地读出数据,读取数据的方向为高位低位

3.代码分享与说明及小误区分享

我这里的代码因为是我自己写的,有的地方想尽量写简单,所以才会犯了我调试过程中的一些错误,这里面大家当做参考就好,如有和大家一样的错误,那就真是英雄所见略同啦,这里用的主控芯片是STM32F103ZET6。
开始信号:

//下降沿为开始信号 void IIC_Start(void) { SDA_OUT(); SDA=1; SCL=1; delay_us(3); SDA=0; delay_us(3); SCL=0; }

小说明:这里的第二第三句SDA=1;SCL=1;最好不要变。
误区解读:若是SCL=1;SDA=1;我们不能确定在SCL=1之前SDA是高电平还是低电平,假如是低电平,那么这两条语句之后,SDA就会产生一个上升沿。

停止信号:

//上升沿为停止信号 void IIC_End(void) { SDA_OUT(); SDA=0; SCL=1; delay_us(3); SDA=1; delay_us(3); SCL=0; delay_us(1); }

小说明:同理,这里的第二第三句SDA=0;SCL=1;不能变。
误区解读:若是SCL=1;SDA=0;我们不能确定在SCL=1之前SDA是高电平还是低电平,假如是高电平,那么这两条语句之后,SDA就会产生一个下降沿。这里我就是因为把这两句调换了,所以才一直接受不到数据,调试了很久,不知道是哪的问题,后来还是走在路上买东西一直想才终于搞明白了,然后才有了想法写一篇博客,hiahia~,开心开心。

应答信号:

//返回值为0表示应答成功,1表示非应答 uint8_t IIC_Ack(void) { uint8_t count; SDA_IN(); SCL=0; delay_us(3); SCL=1; delay_us(2); while(Read_SDA==1) { count ; if(count>250) { IIC_End(); return 1; } } SCL=0; //释放时钟线 return 0; }

小说明:这里定义了一个count,为的就是防止SDA接收不到低电平程序卡炸在这里。第三句SCL=0; delay_us(3);是先释放总线,等待SDA的低电平信号,但是亲测过,不加这两句也可以。

发送数据:

//上升沿写入数据 从高位到低位写数据 void IIC_Send_One_Byte(uint8_t data) { uint8_t i; SCL=0; SDA_OUT(); for(i=0;i<8;i ) { if((data&0x80)>>7) SDA=1; else SDA=0; data<<=1; delay_us(3); SCL=1; delay_us(3); SCL=0; delay_us(2); } }

小说明:先把SDA上的数据准备好,然后利用SCL上升沿发送,注意是先高位再低位发送就可以,逐位数据代码发送的算法也可以自己再想想。

接收数据:

//下降沿读出数据 从高位到低位读数据 uint8_t IIC_Read_One_Byte(void) { uint8_t data=0; uint8_t i; SDA_IN(); for(i=0;i<7;i ) { SCL=1; delay_us(3); data|=Read_SDA; data<<=1; SCL=0; delay_us(3); } return data; }

误区解读:这里注意i<7 之前想当然地以为接收8位数据就是i<8了,后来在自己的脑海中模拟了一下这段程序才想明白。

向AT24C02指定地址写一个字节:

extern uint8_t num; void AT24C02_Write_One_Byte(uint8_t addr uint8_t data) { IIC_Start(); IIC_Send_One_Byte(0xA0); if(IIC_Ack()==0) { IIC_Send_One_Byte(addr); if(IIC_Ack()==0) { IIC_Send_One_Byte(data); if(IIC_Ack()==0) { IIC_End(); USART1_Send(num); } } } delay_ms(10); //可以注释掉 }

小说明:这里按照AT24C02的写字节操作来就好了

iic通信接收不到数据(IIC通信协议代码分享及调试过程中的一些小误区分享)(1)

向AT24C02指定地址读一个字节:

uint8_t AT24C02_Read_One_Byte(uint8_t addr) { uint8_t data; IIC_Start(); IIC_Send_One_Byte(0xA0); if(IIC_Ack()==0) { IIC_Send_One_Byte(addr); if(IIC_Ack()==0) { IIC_Start(); IIC_Send_One_Byte(0xA1); if(IIC_Ack()==0) { data=IIC_Read_One_Byte(); IIC_End(); } } } delay_ms(10); //可以注释掉 return data; }

小说明:这里按照AT24C02的读指定地址操作来就好了

iic通信接收不到数据(IIC通信协议代码分享及调试过程中的一些小误区分享)(2)

iic通信接收不到数据(IIC通信协议代码分享及调试过程中的一些小误区分享)(3)


其他函数:

#define SCL PBout(6) #define SDA PBout(7) #define Read_SDA PBin(7) //转变SDA的输入输出模式 #define SDA_IN() {GPIOB->CRL&=0x0fffffff;GPIOB->CRL|=0x80000000;} #define SDA_OUT() {GPIOB->CRL&=0x0fffffff;GPIOB->CRL|=0x30000000;} void AT24C02_Init(void) { GPIO_InitTypeDef GPIO_Struct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ENABLE); GPIO_Struct.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_Struct.GPIO_Pin=GPIO_Pin_6; //IIC SCL GPIO_Struct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB &GPIO_Struct); GPIO_Struct.GPIO_Pin=GPIO_Pin_7; //IIC SDA GPIO_Init(GPIOB &GPIO_Struct); GPIO_SetBits(GPIOB GPIO_Pin_6|GPIO_Pin_7); } int main(void) { AT24C02_Init(); delay_init(); key_init(); uart_init(115200); num=AT24C02_Read_One_Byte(0); USART1_Send(num); while(1) { if(key0==0) //°´¼ü°´Ï { delay_ms(10); if(key0==0) { num =2; AT24C02_Write_One_Byte(0 num); }while(!key0); } } } 4.实验现象:

iic通信接收不到数据(IIC通信协议代码分享及调试过程中的一些小误区分享)(4)


小说明:按一次key0,num的值加2,然后显示在串口上位机上,一直连续重复出现的AC、AE、B2、B6我按过复位键之后显示的,由此可以检验AT24C02可以断电之后存储原来的数据,代码磨问题啦~

5.写完收工!

若是有错误,欢迎大家指正!有想法,欢迎大家一起探讨!

iic通信接收不到数据(IIC通信协议代码分享及调试过程中的一些小误区分享)(5)

猜您喜欢: