基于STM8的IIC协议通信
一、 综述
I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。
它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU和被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。但在STM8中,400kHZ已经是最快速度了。
在往后的模块调试中也经常涉及,是一个很常见并且很好用的协议。
二、STM8S103中手册对I2C简介
看完中文资料手册,个人觉得比较浅显,具体使用在后面我会贴出来。
三、 I2C详细解析
I2C总共由五个核心函数,分别为:
①起始信号
②停止信号
③应答信号
④发送数据
⑤接收数据
通过这五个核心基本函数就能于大多数的传感进行通信了。
以下对各个部分进行详细介绍,附上部分主要代码,各位可以参考一下。
3.1 起始信号
当SCL为高电平期间,SDA由高电平到低电平的跳变过程;起始信号是一种电平跳变时序信号,而不是一个电平信号,如上图虚线框所。
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由低电平到高电平的跳变过程;停止信号也是一种电平跳变时序信号,而不是一个电平信号,如上图虚线框所。
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);//数据线拉高
}
3.3 应答信号
应答信号有两种:分别是主动应答信号和主动不应答信号
①Ack(主动拉低SDA形成应答信号)
I2C总线的数据都是以字节(8位)的方式传送的,发送器件每发送一个字节之后,在时钟的第9个脉冲期间释放数据总线,由接收器发送一个 ACK(把数据总线的电平拉低)来表示数据成功接收。
//主动应答信号
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。
//主动不应答 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(等待应答信号)
该信号在主机发送完数据后等待从机应答时候使用。
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)。
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信号给从机,以通知接收端结束数据接收。
//接收函数 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的时钟模块的传感通信博客贴出来,各位可以继续阅读下一篇博客做一下参考。
原文地址:https://www.cnblogs.com/shasha2019/p/12171728.html
- 使用Python爬取社交网络数据分析
- PHP爬虫源码:百万级别知乎用户数据爬取与分析
- 使用Python抓取欧洲足球联赛数据
- python爬取百度新闻:分析共享单车火爆背后有哪些规则?
- Python爬虫(urllib2+bs4)数据采集:分析找出百度贴吧谁是水贴王
- 学界 | OpenAI 发布稀疏计算内核,更宽更深的网络,一样的计算开销
- 【手把手教你做项目】自然语言处理:单词抽取/统计
- Kaggle赛题解析:逻辑回归预测模型实现
- R语言 使用BP神经网络进行银行客户信用评估
- 使用R语言挖掘QQ群聊天记录
- 解析滴滴算法大赛---GBDT进行数据预测
- 数据迁移中的数据库检查和建议(r2笔记71天)
- 决策树案例:基于python的商品购买能力预测系统
- 数据迁移前的准备和系统检查 (r2笔记70天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python爬虫三种解析方式,Pyhton360搜索排名查询
- Python关键词百度指数采集,抓包Cookie及json数据处理
- 常用的package.json,还有这么多你不知道的骚技巧
- 【词库】Python关键词筛选分类,Levenshtein编辑距离算法分词
- 爬取数据缺失的补坑,Python数据爬取的坑坑洼洼如何铲平
- 如何开发跨框架的组件
- SpringBoot系列之异步任务@Async使用教程
- 深入k8s:k8s部署&在k8s中运行第一个程序
- Java是如何实现Future模式的?万字详解!
- Tensorflow基础入门十大操作总结
- Django个人博客,三小时带你入门Django框架
- 微信公众号文章采集工具,可采集文章文字内容信息及图片
- Python打包GUI界面组件汇总,Tkinter(TK)实例代码
- 知了超细讲解Django打造大型企业官网学习记录,02diango url 笔记
- 直播卖货小程序源码中,商品分类页面是如何实现的