IIC通信(STM32F4与AT24C02的通信)
来源:互联网 发布:java web开发需求 编辑:程序博客网 时间:2024/06/01 23:20
IIC通信
IIC的使用场合今天就不累赘了,直接入主题,使用IIC是关键在于他的时序图,以下为IIC时序图的解读:
时序图:
记得IIC通信是一种电平的跳变,在写代码时不必太纠结通信速率,延时合适就好,可以从上图得到什么信息呢,可不可以这么认为,时钟线SCL拉高的期间数据线SDA就不再变化了,是不是就可以得出这么一个结论:时钟线拉高的时候才能从外围设备读数据或是写数据给对方,而且时钟线呈等长时间的高或低电平,其实实际工程中不需要这么严格,比如可以这样,这个周期为10us,下个周期为15或7或8us都是可以的,所以我们在写代码的时候应该将注意力放在电平的跳变上,这里在举个例子:在写操作时,先将数据线设置为你想要的电平,延时一会,再将时钟线拉高使其电平数据保持有效,再延时一会,将时钟线拉低,到这里就算写完了一位数据;再比如读数据时,先将时钟线拉高,确保即将读的数据是有效的,然后延时一会就可以读了,读完后再将时钟先拉低延时为下一次读做准备。
虽然IIC通信对于不同的设备有点略微的不同,具体的根据硬件的时序图来,基本分为这几个步骤:1.启动 2. 对数据的操作 3. 停止 其中对数据的操作又分为读和写,对于这些步骤,我们看图说话。
启动与停止:
这是启动和停止的图示,可以看出什么呢,可不可以这样认为,启动这样子实现,将时钟线与数据线都拉高,然后先将数据线拉低,再将时钟线拉低,通讯就这样开始了;通讯停止的话则刚刚好反过来,将两者拉低,然后先将SCL拉高,再将SDA拉高,这样通讯就停止了。
写操作:
从图中看出,写入数据之前,需要做一些准备工作,寻设备地址和写设备内存地址,每发送一个字节(高位先发MSB)还有个应答信号ACK,设备地址(DEVICE ADDRESS)是以8为发送,但他并不是8为地址,最低为是R/W命令,意思是你想对这个设备进行读或写操作,1是读,0是写,这样的外设芯片手册里都可以找的到,其次就是写即将要对选定的设备的哪块内存进行读或写操作,即内存地址(WORD ADDRESS),然后才是真正的写数据data,需要再次提醒的是不管写地址还是数据,写一个字节后对方就会回应一个应答信号(有应答低电平,无应答高电平,无应答则认为数据传输出错了),更加具体的细节将再代码中备注。
读操作:
读操作相对写来说,感觉更复杂一点,因为它多了两个步骤,读操作是这样的,先和写操作一样,寻设备(本质还是写),再写地址,然后再启动一下,启动后再写一次
设备内存地址(特别注意这次写地址带有读操作命令),然后就可以开始读数据了,需要特别注意的是每读一个字节的给对方一个应答信号ACK(高电平),想要结束这次读操作,须在读到的最后一个字节不给应答信号,再给STOP信号结束这次读操作。
下面展现出IIC的功能代码,可自行移植:
void IIC_Start(void)//启动信号,将时钟线与数据线都拉高,然后先将数据线拉低,再将时钟线拉低,通讯就这样开始了{ SDA_OUT;//将作为数据线的那个IO引脚设置为输出模式 I2C_SDA_OUT = 1;//拉高数据线 I2C_CLK = 1;//拉高时钟线 delay_us(5);//适当延时,不能太低,高了也不好,低了芯片识别不了,久了通讯速率太慢。 I2C_SDA_OUT = 0; delay_us(5); I2C_CLK = 0;}void IIC_Stop(void){ SDA_OUT; I2C_SDA_OUT = 0; I2C_CLK = 0; delay_us(5); I2C_CLK = 1; delay_us(5); I2C_SDA_OUT = 1;}uint8_t Wait_Ack(void)//写数据时等待对方应答{ uint8_t ack = 0, i= 0; SDA_IN; I2C_CLK = 0; delay_us(5); I2C_CLK = 1; delay_us(2); while(I2C_SDA_IN) { i++; ack = 1; if(i > 100) printf("ack fail\r\n"); } ack = 0; I2C_CLK = 0; return ack; }void IIC_Ack(void)//读数据的时候给对方应答{ SDA_OUT; I2C_CLK = 0; delay_us(5); I2C_SDA_OUT = 0; delay_us(5); I2C_CLK = 1; delay_us(5);}void IIC_Nack(void)//读数据即将结束的时候不给对方应答{ SDA_OUT; I2C_CLK = 0; delay_us(5); I2C_SDA_OUT = 1; delay_us(5); I2C_CLK = 1; delay_us(5);}void IIC_Send_byte(uint8_t data)//发送一个字节{ uint8_t i; SDA_OUT; I2C_CLK = 0; delay_us(5); for(i = 0; i < 8; i++) { if(data & (1 << (7 - i))) I2C_SDA_OUT = 1; else I2C_SDA_OUT = 0; delay_us(2); I2C_CLK = 1; delay_us(5); I2C_CLK = 0; delay_us(5); }}uint8_t IIC_Read_byte(void)//读取一个字节{ uint8_t i; uint8_t data = 0; I2C_CLK = 0; delay_us(5); SDA_IN; for(i = 0; i < 8; i++) { I2C_CLK = 1; delay_us(2); if(I2C_SDA_IN) { data <<= 1; data |= 1; } else { data <<= 1; } delay_us(3); I2C_CLK = 0; delay_us(5); } return data;}void IIC_Write(uint8_t addr, uint8_t* buf, uint8_t len)//写数据,写的时候只能页写入,这里是基于AT24C02的(每页8个字节),不同的芯片可能不一样,{ uint8_t i, j; uint8_t page = 0; for(i = 0; i < (len/8); i++) { IIC_Start(); delay_us(5); IIC_Send_byte(0xA0); if(Wait_Ack()) { printf("start fail"); return; } IIC_Send_byte((addr/8*8)+ i*8);//写入的地址必须是8的整数倍,因为页写入 if(Wait_Ack())//无应答则结束,否则继续 { printf("write addr fail"); return; } for(j = 0; j < 8; j++) { IIC_Send_byte(buf[ i*8 + j ]); if(Wait_Ack()) { printf("write data fail"); return; } } IIC_Stop(); page = i; delay_ms(50);//´这个延时很关键,经多次测试,要足够长,不然会应答错误(通讯出错) }}uint8_t IIC_Read(uint8_t addr, uint8_t* buf, uint8_t len){ uint8_t i; uint8_t ack = 0; IIC_Start(); delay_us(2); IIC_Send_byte(0xA0);//寻设备,写命令 if(Wait_Ack()) { printf("find device fail"); ack = 1; } IIC_Send_byte(addr/8*8); if(Wait_Ack()) { printf("write addr fail"); ack = 1; } IIC_Start();//再次启动 IIC_Send_byte(0xA1)//读命令 if(Wait_Ack()) { printf("read device fail"); ack = 1; } for(i = 0; i < len; i++)//读操作不分页读取,一直读,地址会自动往后偏移 { buf[i] = IIC_Read_byte(); if(i == (len - 1)) IIC_Nack(); else IIC_Ack(); } if(!ack) printf("read succeed!\r\n"); IIC_Stop(); return ack;}
阅读全文
0 0
- IIC通信(STM32F4与AT24C02的通信)
- 单片机模拟 IIC 总线与 EEPROM(AT24C02)通信
- 基于51单片机IIC通信的AT24C02学习笔记
- msp430g2553的IIC通信
- STM32F105 与PCA6416 IIC通信(软件)
- stm8s开发(八) IIC的使用:IIC主机通信!
- IIC通信
- IIC通信
- IIC通信
- IIC的通信波形分析
- AT24C02的Stm32模拟读写IIC程序(续)
- Proteus中MSP430与SHT11的IIC通信问题
- STM32硬件IIC与51模拟IIC通信
- AT24C02的Stm32模拟读写IIC程序
- 以AT24C02为例的IIC通信协议
- IIC总线时序(结合AT24C02)
- IIC和SPI通信的异同
- tgcopter v3.x开发记录---stm32f4与arduino通过SPI的DMA通信
- NYOJ
- 联发科编程大赛_第六题小M的篮球梦
- Python数据分析相关库
- Java练习
- vue2.0 中#$emit,$on的使用详解
- IIC通信(STM32F4与AT24C02的通信)
- LeetCode编程练习
- SVM
- C++中的&和*
- 顺序表应用3:元素位置互换之移位算法
- modal--1.查看(子页面)
- 2017年9月21日训练日记
- C/C++时间相关操作 SYSTEMTIME time_t 字符串的相互转换
- 定时器实现60s点击重新发送验证码