历史上的今天
今天是:2025年04月23日(星期三)
2019年04月23日 | stm32与AT24C02的I2C通信总结(模拟时序)
2019-04-23 来源:eefocus
从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);
}
上一篇:stm32红外遥控的定时器实现
史海拾趣
|
急问:MP3电路原理图!请教高手,帮我分析下这个MP3原理图中各个组成部分的原理、处理器的功能。 http://blog.ednchina.com/Upload/Blog/2007/3/30/826adf84-7829-4de7-8065-2149d80d0c85.jpg 请高手帮我分析下这个MP3原理图中各个组成部分的原理、处理器的功能。 谢谢!… 查看全部问答> |
|
弱弱的问一个问题,Windows中的WinInet API在Window Mobile中能用吗? 例如HttpSendRequest、InternetReadFile之类的函数。 如果不可以,是否手机就不能通过http协议请求某个服务器的数据?… 查看全部问答> |
|
陶瓷材料因本身具有优良的绝缘、耐热及稳定等先天特性,所以被大量运用在电气设备的绝缘上,又因陶瓷金属化技术的成熟,近几年更被应用于led陶瓷散热基板与载板的线路铺设。陶瓷材料金属化技术主要分为「DBC(Direct Bonded Copper) 」及「DPC(Di ...… 查看全部问答> |
|
我的2812芯片flash写入了一次之后,就没办法写了怎么回事的?CCS连接之后点on-chip flash programmer,对话框全是灰色的,只有一个onlock按钮可以点,但是点了之后弹出unlock failed,CCS提示解锁失败,设备锁定。 但是上次烧写的时候我并没有改动 ...… 查看全部问答> |
|
记录学习LM3S的点点滴滴 (声明:该学习心得是本人通过学习周立功的相关资料后的个人理解后的笔记,由于本人水平有限,也许会有错误或是偏差,若想要保证准确无误,建议自己去下相关资料学习,本心得只供参考,若有错误之处,敬请指出,万分感谢 ...… 查看全部问答> |
|
本人刚开始学uCOS系统,现在有一块S3C44B0X的板子,想把uCOS移植进去,于是在网上找了一些基于S3C44B0X的uCOS源码,但是不知道如何运用编译器把源码处理,自然也就不知道怎么把内核系统烧进板子,现在不知道如何下手,而且在网上找的资料都没有运用 ...… 查看全部问答> |
|
我用Verilog HDL编写了一个rs232串口驱动程序。在用串口调试助手进行调试时,当我发送2,4,6,8,A,C,E时,接受没有出现一个乱码,但当我发送1,3,5,7,9,B,D,F时出现乱码,在每300中出现4——5个乱码,有时只出现一个。请问这是什么原因,还是 ...… 查看全部问答> |




