历史上的今天
返回首页

历史上的今天

今天是: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;

}


2.开始状态:当SCL为高电平时,SDA从高电平到低电平进行跳变,然后SCL跳变为低电平,时刻装备接收数据

                                     

按照上图实现如下代码 :(注意: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;

 

}


5.非应答信号

                                      

上图中的not acknowledge 就是非应答信号。


根据上图以及数据的有效性(在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协议的使用


推荐阅读

史海拾趣

Brilliance公司的发展小趣事

随着市场竞争的加剧,Brilliance公司意识到只有不断创新才能在行业中立足。于是,公司加大了对研发的投入,引进了一批高端人才和先进设备。经过无数次的试验和改进,Brilliance成功研发出了一项具有颠覆性的技术,并将其应用于新产品中。这款新产品不仅性能卓越,而且具有极高的性价比,迅速占领了市场份额。

ELM [ELM Electronics]公司的发展小趣事

随着产品线的不断扩张,ELM开始积极拓展市场,寻求更广阔的发展空间。公司制定了国际化战略,通过参加国际展会、建立海外销售渠道等方式,成功将产品打入国际市场。同时,ELM还积极与国际知名电子企业开展合作,共同研发新产品、开拓新市场。这些举措不仅为ELM带来了更多的商业机会,也提升了公司的国际影响力。

CT [ Central Technologies ]公司的发展小趣事

经过数年的努力,CT公司终于研发出了一款具有颠覆性的新型芯片技术。这款芯片在性能上大幅超越了当时的同类产品,引起了市场的广泛关注。多家知名企业纷纷与CT公司展开合作,将这款芯片应用于他们的产品中。随着合作伙伴的增加和市场份额的扩大,CT公司的知名度逐渐提升,成为了电子行业的一匹黑马。

宝乘(baocheng)公司的发展小趣事

宝乘公司自创立之初,便立志于在电子行业中开创新天地。面对国内外激烈的市场竞争,宝乘团队凭借对半导体功率器件领域的深入研究和不断创新,成功研发出一系列具有竞争力的产品。从芯片到整流桥,再到高压硅堆和电力电子模块,宝乘的产品线逐渐丰富,产品质量和技术水平也得到了业界的认可。

DATEL Inc公司的发展小趣事

随着公司业务的不断扩展,DATEL Inc.开始实施全球化战略。公司积极开拓国际市场,与全球各地的合作伙伴建立了紧密的合作关系。通过引进国际先进技术和管理经验,DATEL Inc.的产品质量和服务水平得到了进一步提升。同时,公司还加强了对海外市场的营销和推广力度,成功将DATEL Inc.的品牌推向了全球。

Goodwork Semiconductor ( GW )公司的发展小趣事
如果对电源质量要求较高,需要选择波形失真较小的稳压器。

问答坊 | AI 解惑

生物识别系统显神威 眨眨眼就可以开门

眼睛看一眼识别器,戒备森严的大门就会自动打开,这些以前只能在好莱坞大片中才能看到的生物识别系统,正在进入大家的日常生活。 生物识别系统,就是利用人体的声音、指纹、人脸、虹膜和掌纹等具有唯一性和稳定性的特征,识别出一个人的身份的系统 ...…

查看全部问答>

CS8900网络接口电路图

CS8900,CS8952网络接口电路图…

查看全部问答>

zlg7289

本帖最后由 paulhyde 于 2014-9-15 09:00 编辑 zlg7289  …

查看全部问答>

关于显示和中断~~~~

串口和键盘两个中断,键盘触发发送串口,显示屏接收数据,两者不干扰。但现在有键按下后,显示屏会被影响,不知道出了什么问题?…

查看全部问答>

步进电机和驱动器的问题,请解答

以有上面两个东西,现在想通过PC串口来控制步进电机,并写出VC程序。要求VC能控制电机以轴向距离1mm为单位移动 我的想法是通过一个串口转TTL的转接器接上驱动器然后驱动电机,最后用VC来控制串口 不知以上方案可行否? 请高手赐教    ...…

查看全部问答>

windows mobile 下如何获取IWebbrowser2 接口

windows mobile 下如何获取IWebbrowser2 接口,从而调用IE打开知道网址? 我的编码如下 CComPtr   browser; CoCreateInstance(CLSID_WebBrowser,   NULL,   CLSCTX_INPROC,         &nbs ...…

查看全部问答>

pads (PCB)问题

这个是地孔,如果不连起来,检测时就会出错。这是什么原因?群里有一哥们问的!…

查看全部问答>

STM32F103RC不能用ULINK2调试

使用ULINK 2调试自己的板子,(连接的JTAG信号线有:JTAG_TDI、JTAG_TDO、JTAG_TCK、JTAG_TMS、JTAG_TRST连接的信号),我开始认为是没有连接nreset的问题,把nreset脚与我电路板上的nreset链接以后现象还是一样,就是每次进入DEBUG调试状态 ...…

查看全部问答>

香水,提问了!关于TFTLCD的

                                 看到官方LWIP例程中有TFT部分,本人由于以前只玩过1602  和点阵,所以对开发板自带的那个TFT 320*240的L ...…

查看全部问答>

哥哥姐姐帮我看看I2C配置哪错了......

void RCC_Config(void) {         ErrorStatus HSEStartUpStatus;           RCC_DeInit();           RCC_HSEConfig(RCC_HSE_ON);     &nb ...…

查看全部问答>