历史上的今天
今天是:2025年02月23日(星期日)
2021年02月23日 | STM32F4之模拟I2C通信协议的实现
2021-02-23 来源:eefocus
一,何为IIC?
I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。
它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。
IIC是半双工通信方式。
二,IIC通信的6种状态
1.空闲状态
2.开始信号
3.停止信号
4.应答信号
5.数据的有效性
6.数据传输
三.用代码实现I2C协议的模拟
1.空闲状态:当SDA以及SCL两条总线都处于高电平状态时,处于空闲状态
void IIC_init()
{
//声明一个GPIO的结构体变量
GPIO_InitTypeDef GPIO_InitStructure;
//使能GPIO外设时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
//定义该GPIO结构体
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8 |GPIO_Pin_9; //两个GPIO
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //输出模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; //100MHz
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉
//初始化GPIOB
GPIO_Init(GPIOB,&GPIO_InitStructure);
//初始化I2C总线,使之成为空闲状态
IIC_SCL=1;
IIC_SDA=1;
}
按照上图实现如下代码 :(注意:SDA有输入,输出两种状态)
void IIC_start()
{
//将SDA的IO设置为输出状态
SDA_OUT();
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;
delay_us(4);
IIC_SCL=0; //拉低数据总线,时刻准备接收数据
}
按照上图实现如下代码 :(注意:SDA有输入,输出两种状态)
void IIC_start()
{
//将SDA的IO设置为输出状态
SDA_OUT();
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;
delay_us(4);
IIC_SCL=0; //拉低数据总线,时刻准备接收数据
}
按照上图实现代码如下 :(在SCL为高电平时,SDA进行跳变)
//产生停止信号
void IIC_stop()
{
//数据输出
SDA_OUT();
IIC_SCL=0;
IIC_SDA=0;
delay_us(4);
IIC_SCL=1; //按照上图,在SCL为高电平时,SDA进行跳变
IIC_SDA=1;
delay_us(4);
}
4.应答信号:
当发送器每发送一个字节,就会在第9周期释放数据总线(即SDA为高电平),等待接收器发送一个应答信号
该应答信号:(接收应答信号时,SDA需改变为输入状态)
当读到来自接收器的低电平,表明已经接收设备已经接收到数据。
当读到来自接收器的低电平,表明接收设备未能正常接收数据。
根据上图以及数据的有效性(在SCL信号由低到高,再由高到低的过程中,高电平保持期间,SDA保持不变,SDA即发送的数据),可以写出以下代码:
//产生应答信号
void IIC_ack()
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
根据上图以及数据的有效性(在SCL信号由低到高,再由高到低的过程中,高电平保持期间,SDA保持不变,SDA即发送的数据),可以写出以下代码:
//产生非应答信号
void IIC_nack()
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
6.等待应答的信号
在SCL的有效周期期间,读到SDA线上的数据
//将数据总线进行释放
//SDA为输入模式,进行应答信号的读取
//返回值: 1,无应答
// 0,有应答
u8 IIC_Wait_Ack()
{
u8 ucErrTime=0;
//SDA输入模式设置
SDA_IN();
IIC_SDA=1;
delay_us(1);
IIC_SCL=1;
delay_us(1);
while(READ_SDA)//应答信号的读取
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_stop();
return 1;
}
}
IIC_SCL=0;
return 0;
}
7.数据的接收
在SCL有效周期内对数据进行接收(SCL=0 ---> SCL=1 读SDA --->SCL=0 形成数据的有效性)
(注意:receive需将其初始化为0,否则会出现数据传输错误,因为局部变量的值为脏值,在栈上的值)
u8 IIC_Read_Byte(unsigned char ack)
{
u8 receive=0,t;
SDA_IN();
for(t=0;t<8;t++)
{
IIC_SCL=0; //SCL=0 -> SCL=1 读SDA ->SCL=0 形成数据的有效性
delay_us(2);
IIC_SCL=1;
receive<<=1; //接收一位数据为0
if(READ_SDA)
{
receive++; //接收一位数据为1
}
delay_us(1);
}
if(!ack)
{
IIC_nack();
}else
{
IIC_ack();
}
return receive;
}
8.数据的发送(SCL=0 ---> SCL=1 发送SDA --->SCL=0 形成数据的有效性)
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;
for(t=0;t<8;t++)
{
IIC_SDA=(txd&0x80)>>7;//将最高位的数据进行输出
txd<<=1; //将最高位的数据溢出,准备发送次高位的数据
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
以上为I2C通信协议的实现(部分代码未给出),后续文章为I2C协议的使用
史海拾趣
|
眼睛看一眼识别器,戒备森严的大门就会自动打开,这些以前只能在好莱坞大片中才能看到的生物识别系统,正在进入大家的日常生活。 生物识别系统,就是利用人体的声音、指纹、人脸、虹膜和掌纹等具有唯一性和稳定性的特征,识别出一个人的身份的系统 ...… 查看全部问答> |
|
以有上面两个东西,现在想通过PC串口来控制步进电机,并写出VC程序。要求VC能控制电机以轴向距离1mm为单位移动 我的想法是通过一个串口转TTL的转接器接上驱动器然后驱动电机,最后用VC来控制串口 不知以上方案可行否? 请高手赐教 ...… 查看全部问答> |
|
windows mobile 下如何获取IWebbrowser2 接口 windows mobile 下如何获取IWebbrowser2 接口,从而调用IE打开知道网址? 我的编码如下 CComPtr browser; CoCreateInstance(CLSID_WebBrowser, NULL, CLSCTX_INPROC, &nbs ...… 查看全部问答> |
|
使用ULINK 2调试自己的板子,(连接的JTAG信号线有:JTAG_TDI、JTAG_TDO、JTAG_TCK、JTAG_TMS、JTAG_TRST连接的信号),我开始认为是没有连接nreset的问题,把nreset脚与我电路板上的nreset链接以后现象还是一样,就是每次进入DEBUG调试状态 ...… 查看全部问答> |
|
void RCC_Config(void) { ErrorStatus HSEStartUpStatus; RCC_DeInit(); RCC_HSEConfig(RCC_HSE_ON); &nb ...… 查看全部问答> |






