历史上的今天
今天是:2024年09月11日(星期三)
2020年09月11日 | 基于STM8的IIC协议通信
2020-09-11 来源:eefocus
一、 综述
I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。
它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU和被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。但在STM8中,400kHZ已经是最快速度了。
在往后的模块调试中也经常涉及,是一个很常见并且很好用的协议。
二、STM8S103中手册对I2C简介




看完中文资料手册,个人觉得比较浅显,具体使用在后面我会贴出来。
三、 I2C详细解析
I2C总共由五个核心函数,分别为:
①起始信号
②停止信号
③应答信号
④发送数据
⑤接收数据
通过这五个核心基本函数就能于大多数的传感进行通信了。
以下对各个部分进行详细介绍,附上部分主要代码,各位可以参考一下。

3.1 起始信号
当SCL为高电平期间,SDA由高电平到低电平的跳变过程;起始信号是一种电平跳变时序信号,而不是一个电平信号,如上图虚线框所。
1 2 3 4 5 6 7 8 9 10 11 12 | void Start_Signal_IIC_(void){ //起始信号: GPIO_WriteHigh(GPIOD, GPIO_PIN_2);//数据线 IIC_Delay_4us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3);//时钟线 IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_2); //数据线 IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_3); //时钟线 IIC_Delay_4us(); } |
3.2 停止信号
当SCL为高电平期间,SDA由低电平到高电平的跳变过程;停止信号也是一种电平跳变时序信号,而不是一个电平信号,如上图虚线框所。
1 2 3 4 5 6 7 | void End_Data_IIC_() { GPIO_WriteLow(GPIOD, GPIO_PIN_2); //数据线拉低 IIC_Delay_4us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3);//时钟线拉高 IIC_Delay_4us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_2);//数据线拉高 |
1 | } |
3.3 应答信号

应答信号有两种:分别是主动应答信号和主动不应答信号
①Ack(主动拉低SDA形成应答信号)
I2C总线的数据都是以字节(8位)的方式传送的,发送器件每发送一个字节之后,在时钟的第9个脉冲期间释放数据总线,由接收器发送一个 ACK(把数据总线的电平拉低)来表示数据成功接收。
1 2 3 4 5 6 7 8 9 | //主动应答信号 void vIIC_Ack() { GPIO_WriteLow(GPIOD, GPIO_PIN_2); IIC_Delay_4us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); } |
②NAck(主动不拉低SDA不形成应答信号)
在时钟的第9个脉冲期间发送器释放数据总线,接收器不拉低数据总线表示一个NACK,NACK有两种用途:
a. 一般表示接收器未成功接收数据字节;
b. 当接收器是主控器时,它收到最后一个字节后,应发送一个NACK信号,以通知被控发送器结束数据发送,并释放总线,以便主控接收器发送一个停止信号STOP。
1 2 3 4 5 6 7 8 9 10 | //主动不应答 void vIIC_NAck() { GPIO_WriteHigh(GPIOD, GPIO_PIN_2); IIC_Delay_4us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); } |
③ReadAck(等待应答信号)
该信号在主机发送完数据后等待从机应答时候使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | u8 bIIC_ReadACK() { GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);//将SDA改为输入模式。 GPIO_WriteHigh(GPIOD, GPIO_PIN_3); //拉高时钟线。 IIC_Delay_4us(); if(IIC_SDA_R != 0) { //低 有应答 GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);//SDA return 1; } else //高 无应答 { GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST);//SDA return 0; } } |
3.4 发送数据
在发送起始信号后开始通信,主机发送一个8位数据。然后,主机释放SDA线并等待从从机发出得确认信号(ACK)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | void Send_Data_IIC_(uint8_t Data){ int i; //拉低数据线和时钟线 GPIO_WriteLow(GPIOD, GPIO_PIN_3); GPIO_WriteLow(GPIOD, GPIO_PIN_2); for(i=0;i<8;i++) { if(Data&0x80) GPIO_WriteHigh(GPIOD, GPIO_PIN_2); else GPIO_WriteLow(GPIOD, GPIO_PIN_2); Data= Data<<1; IIC_Delay_2us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_2us(); } } |
3.5 接收数据
在发送起始信号后开始通信,主机发送一个8位数据。然后,从机收到数据返回一个确认信号(ACK)给主机,这时候主机才开始接收数据,待主机接收数据完成后,发送一个NACK信号给从机,以通知接收端结束数据接收。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //接收函数 uint8_t uIIC_RecvByte() { uint8_t i,uReceiveByte = 0; GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_IN_PU_IT); for(i=0;i<8;i++) { uReceiveByte <<= 1; IIC_Delay_4us(); GPIO_WriteHigh(GPIOD, GPIO_PIN_3);//高时钟线时读取数据电平 IIC_Delay_4us(); if(IIC_SDA_R !=0 ) { uReceiveByte|=0x01; } IIC_Delay_4us(); GPIO_WriteLow(GPIOD, GPIO_PIN_3); IIC_Delay_4us(); } GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_HIGH_FAST); return uReceiveByte; } |
3.6 I2C通信总过程
以下图完美地诠释了iic从接收到发送全过程中,SDA和SCL线的变化线。综合上面的解释和过程代码,这张图可以帮助记忆和理解。

四、例程
4.1 编译环境:
这里用的是IAR进行编译,较为好用,后期使用STM32的开发板可以推荐使用CUBE直接生成初始化函数,与Keil5相互搭配使用,很是方便。
4.2 主芯片:
我的主芯片是STM8S系列中的103,其中STM8S的003、005、和103、105,配置一样(外设和CPU频率,FLASH),在代码相同的情况下均可进行烧写。
4.3 代码&解析
iic代码可以驱动几乎市面上的所有时钟模块,所以这里的代码可以与时钟模块的代码相互调用。每个函数我都有加以解释,可以详细了解一下。
看了上面的代码也可以知道,这个协议是由数据线和时钟线,数据发送接收要求拉高数据线或拉低时钟线。所以这里推荐直接使用库函数的拉高低,如果要方便的话,再加个宏定义可以更加直观方便。
五、结尾
以上是iic的核心函数,对于每个函数我已经写的很清楚,下一篇博客我会将基于iic的时钟模块的传感通信博客贴出来,各位可以继续阅读下一篇博客做一下参考。
史海拾趣
|
发动机被称为汽车的“心脏”,控制发动机的电子系统“电喷”又称为发动机的“心脏”。深圳康佳集团成功开发“电喷”系统,不但填补了国内空白,而且标志该集团进入汽车电子领域不久即占据产业与技术的最高端,成为中国汽车电子的主流企业。 “电喷 ...… 查看全部问答> |
|
dsp是强大的芯片,设计的技术很多,很杂,特别是一dsp作为核心的时候!现在大致有两种系统,一种是主从式的,说简单一点就是dsp和主机打交道!一种是dsp自成体系的,这个时候所有的控制,处理工作都是有dsp器件完成的,这样的系统一般都有自举引导 ...… 查看全部问答> |
|
由电涡流测功机感应子主要由旋转部分和摆动部分(电枢和励磁线圈)组成。转子轴上的感应子形状犹如齿轮,与转子同轴装有一个直流励磁线圈。当励磁线圈组通以直流电流时,其周围便有磁场存在,那么围绕励磁组就产生一闭合磁通。很明显,位于绕组 ...… 查看全部问答> |
|
问题: 要修改 LM3S8962 MAC Address 是否从下列圆中输入就行了,如可以要量产时是否也要一片一片板子来修改?? 再请教一下,有没有 LM Flash programmer S/W 操作手冊可看 答案: 用从标注的选项里面修改。因 ...… 查看全部问答> |
|
目前老师让做uCOS-II在XS128的移植,可是目前手头关于这款单片机的资料很少,不知道怎么用,更不知道怎么写,不知道他和MC9SDG128有什么区别,哪位同情下,给点帮助啊!… 查看全部问答> |
|
[TI M4申请]自主智能汽车运动控制和姿态测量系统(inemo入围项目) 自主智能汽车运动控制和姿态测量系统一、项目概述1.1 项目摘要本系统的目的是设计一种以IMEMS传感器为主的自主路径识别智能汽车的运动控制和测量系统。本系统采用双MCU架构, STM32F103 MCU负责车身信号的采集,各模块电源的管理和地磁传感器,陀螺 ...… 查看全部问答> |




