通信协议简述
- 三条线:串行数据线(SDA)、串行时钟线(SCL),地线;
- 半双工 一问一答 ,主从模式,多设备模式
- 总线协议:支持多个设备进行通信(多主多从)
- 异步模式(串口):通信双方约定好波特率,然后各自按照自己时钟进行通信。
好处:便捷;
缺点:双方必须时钟精确,否则对不齐了。
- 同步通信(IIC):由主机的时钟总线确定通信速率
- 选择IIC原因:考虑小型传感器没有晶振提供精确的时钟基准
通信协议过程
在IIC总线上,每个从机都有其唯一的默认设备地址【这个设备地址由谁规定的呢?】。发送数据时采用广播形式,数据最开始带着从机地址,其他设备会选择性失聪。
1、通信开始前:
两总线电平处于拉高状态:
主机在时钟线上产生恒定的时钟脉冲
2、主机发起通信:
在时钟线某个高电平时,数据线下拉;随机主机会在时钟线上产生一个恒定的时钟脉冲信号。
3、数据发送过程:
接下来每一个时钟周期内,SDL上发送电平基本小规则:
主机在低电平时钟时,设置数据;从机在高时钟时,读取数据。
字节数据发送主要规则:
每当发送器传输完一个字节(8 bit)的数据之后,发送端会等待一定的时间,等接收方的应答信号。接收端通过拉低SDA数据线,给发送端发送一个应答信号,以提醒发送端我这边已经接受完成,数据可以继续传输,接下来,发送端就可以继续发送数据了。如此反复,直到发送完所有数据。
即每一帧的数据传送与应答数据 共有9bit
总线寻址:
值得注意的是,IIC通信中,主机发送的第一个字节往往是某个从机在总线上的地址:
数据读写方向:
参考来源:
IIC详解,包括原理、过程,最后一步步教你实现IIC_iic协议-CSDN博客
4、通信终止信号:
然后主机会在时钟线处于高电平时,将数据线拉高,通信终止信号。整段通信完成。
起始信号和终止信号都是由主机发送的。在起始信号产生之后,总线就处于被占用的状态,在终止信号产生之后,总线就处于空闲状态。
注意:每次数据传送总是由主机产生的终止信号来结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。
模拟IIC协议代码实现
代码实现-学习视频推荐
iic读取函数书写_哔哩哔哩_bilibiliiic读取函数书写, 视频播放量 2012、弹幕量 4、点赞数 57、投硬币枚数 17、收藏人数 62、转发人数 0, 视频作者 小远课堂, 作者简介 作者已关闭了评论提醒,相关视频:I2C时序图解讲解[上],IIC的代码不会写?,秒懂I2C时序图,IIC时序图讲解【中】,I2C入门第一节-I2C的基本工作原理,I2C写字节的基本流程,lcd1602看时序图写代码,I2C时序图讲解【下】,学完C语言,做不出小程序,做不出图形化界面,只有黑乎乎的窗口,自学编程的几点建议,7分钟看懂时序图,不懂你骂我,花了四个多小时画了人生第一块PCBhttps://www.bilibili.com/video/BV1Vj411Z7qN/?spm_id_from=333.788&vd_source=f443c8140671d1c361aa817ad1193312代码更详细实现-博客推荐
【通信协议】IIC通信协议详解-CSDN博客IIC的基本介绍IIC总线的发展: 芯片间总线(Inter Interface Circuit,IIC),是应用广泛的芯片间串行扩展总线。目前世界上采用的IIC总线一共有两个规范,分别由荷兰飞利浦公司和日本索尼公司提出的,现在基本采用荷兰飞利浦的IIC总线的技术规范。IIC总线的优点:1、IIC总线优点中最主要的优点是其简单性(IIC只有两条信号线)和有效性(根据SCL线上的时钟线来判断)。带有IIC总线的接口的单片机都可直接与具有IIC总线接口的各种扩展器件..._iic通信协议https://blog.csdn.net/qq_53918631/article/details/124810934?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-124810934-blog-107078170.235%5Ev38%5Epc_relevant_anti_vip_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-124810934-blog-107078170.235%5Ev38%5Epc_relevant_anti_vip_base&utm_relevant_index=2
头文件myiic.h#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h" //IO方向设置
//CRH,CRL 端口输入输出模式寄存器。CRH为8-15引脚,CRL为0-7引脚
#define SDA_IN() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}//PC11引脚为上拉/下拉输入
#define SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}//PC11为推挽输出//IO操作函数
#define IIC_SCL PCout(12) //SCL
#define IIC_SDA PCout(11) //SDA
#define READ_SDA PCin(11) //输入SDA//IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号//一下两个函数实际并未被定义
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif.c文件#include "myiic.h"
#include "delay.h"//初始化IIC
//硬件I2C必须开漏输出
//模拟I2C则为推挽输出(方便输出高低电平?)
void IIC_Init(void)
{ GPIO_InitTypeDef GPIO_InitStructure;//RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);IIC_SCL=1;//PCout(12)IIC_SDA=1;//PCout(11)}
//产生IIC起始信号
//SCL为高时,SDA拉低,准备开始传数据。(记得再拉低SCL,这个是为什么?)
//SCL为高时,SDA拉高,结束传输数据。
//传输数据时,SCL为高时数据有效
void IIC_Start(void)
{SDA_OUT(); //sda线输出IIC_SDA=1; //SDA = 1,SCL = 1 空闲状态 IIC_SCL=1;delay_us(4);IIC_SDA=0;//START:when CLK is high,DATA change form high to lowdelay_us(4);IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{SDA_OUT();//sda线输出IIC_SCL=0;IIC_SDA=0;//STOP:when CLK is high DATA change form low to highdelay_us(4);IIC_SCL=1;IIC_SDA=1;//发送I2C总线结束信号delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{u8 ucErrTime=0;SDA_IN(); //SDA设置为输入 IIC_SDA=1;delay_us(1); IIC_SCL=1;delay_us(1); //设置数据有效while(READ_SDA)//READ_SDA为0时表示接收到应答{ucErrTime++;if(ucErrTime>250){IIC_Stop();return 1;}}IIC_SCL=0;//时钟输出0 return 0;
}
//产生ACK应答
void IIC_Ack(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=0;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SCL=0;
}
//不产生ACK应答
void IIC_NAck(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=1;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SCL=0;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//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); //对TEA5767这三个延时都是必须的IIC_SCL=1;delay_us(2);IIC_SCL=0; delay_us(2);}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{unsigned char i,receive=0;SDA_IN();//SDA设置为输入for(i=0;i<8;i++ ){IIC_SCL=0;delay_us(2);IIC_SCL=1;receive<<=1;if(READ_SDA)receive++; delay_us(1);} if (!ack)IIC_NAck();//发送nACKelseIIC_Ack(); //发送ACK return receive;
}
————————————————
版权声明:本文为CSDN博主「碑 一」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dedell/article/details/96628955
模拟IIC应用实战:
stm32无人机:利用上面基础模拟IIC代码把数据从mpu6050传感器数据读取出来(未完成)
*stm32 HAL库 实现和使用IIC总线*#include "stm32xxxxx.h"
#include "stm32xxxxx_hal.h"I2C_HandleTypeDef hi2c1;void SystemClock_Config()
{// 配置系统时钟// ...
}void GPIO_Configuration()
{// 配置GPIO引脚// ...
}void I2C_Configuration()
{// 配置I2C外设hi2c1.Instance = I2C1;hi2c1.Init.Timing = 0x00303D5B; // 根据具体系统时钟和I2C时钟频率调整这个值hi2c1.Init.OwnAddress1 = 0;hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c1.Init.OwnAddress2 = 0;hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;// 初始化I2C外设HAL_I2C_Init(&hi2c1);
}int main(void)
{uint8_t sendData[] = {0x01, 0x02, 0x03};uint8_t receiveData[3];// 初始化系统时钟SystemClock_Config();// 配置GPIO引脚GPIO_Configuration();// 配置I2C外设I2C_Configuration();// 发送数据HAL_I2C_Master_Transmit(&hi2c1, DeviceAddress, sendData, sizeof(sendData), HAL_MAX_DELAY);// 延时等待数据发送完成HAL_Delay(1); // 根据实际情况调整延时时间// 接收数据HAL_I2C_Master_Receive(&hi2c1, DeviceAddress, receiveData, sizeof(receiveData), HAL_MAX_DELAY);while (1){// 主程序逻辑}
}
参考:
【物联网】I2C(IIC)通信协议详解与应用_iic通信_嵌入式小白—小黑的博客-CSDN博客
【通信协议】IIC通信协议详解-CSDN博客IIC的基本介绍IIC总线的发展: 芯片间总线(Inter Interface Circuit,IIC),是应用广泛的芯片间串行扩展总线。目前世界上采用的IIC总线一共有两个规范,分别由荷兰飞利浦公司和日本索尼公司提出的,现在基本采用荷兰飞利浦的IIC总线的技术规范。IIC总线的优点:1、IIC总线优点中最主要的优点是其简单性(IIC只有两条信号线)和有效性(根据SCL线上的时钟线来判断)。带有IIC总线的接口的单片机都可直接与具有IIC总线接口的各种扩展器件..._iic通信协议https://blog.csdn.net/qq_53918631/article/details/124810934?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-124810934-blog-107078170.235%5Ev38%5Epc_relevant_anti_vip_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~Rate-1-124810934-blog-107078170.235%5Ev38%5Epc_relevant_anti_vip_base&utm_relevant_index=2
案例:利用IIC从单片机读取温湿度显示到电脑
数据显示到电脑上:
前几节用到的串口以及串口调试助手 - 从单片机发送数据到pc上,显示出来
IIC写驱动
项目架构
直接看“传感器数据手册”
重点关注:设备从机地址 0X71
【STM32入门教程-2023】第12集 IIC通信与温湿度传感器AHT20(DHT20)_哔哩哔哩_bilibili本期视频我们一起来了解一下如何使用STM32的IIC通信, 获取你房间的温度与湿度~------------------------------------------------------------------------------学习套件获取: https://b23.tv/sblUuvI 或者直接某宝搜索"keysking stm32", 认准店铺"波特律, 视频播放量 24904、弹幕量 140、点赞数 1026、投硬币枚数 605、收藏人数 1354、转发人数 109, 视频作者 keysking, 作者简介 立志做最好最简洁最易懂的教程!!!,相关视频:【STM32入门教程-2023】第14集 如何在OLED屏幕上挥毫,STM32物联网入门30步--STM32CubeMX+HAL库 CubeIde蓝牙 WIFI ESP8266 嵌入式物联网开发教学 基于F103 30集全,STM32入门100步→100集系统化STM32入门方案=STM32F103+KEIL标准库+C语言基础+代码逐行分析+独家教学PPT+人机界面开发全过程,【STM32入门教程-2023】第13集 IIC的中断与DMA以及状态机编程,【洋桃电子】STM32入门F4:F407+CubeMX+HAL库(CubeIDE)+蓝牙 WIFI ESP8266+原创例程+独家PPT图表(更新中),【STM32入门教程-2023】应该是全B站最好的STM32教程了,5分钟看懂!串口RS232 RS485最本质的区别!,电路里为什么要摆这两个电容?,【洋桃电子】洋桃补习班(为0基础的初学者补足基础知识)STM32入门100步系列视频,10行代码,就能让你真正理解DMA!你用的可能很少,但是在单片机中非常重要!https://www.bilibili.com/video/BV1QN411D7ak/?spm_id_from=333.788&vd_source=f443c8140671d1c361aa817ad1193312
从面试角度看IIC的提问点:
1、为什么选择IIC通信,和SPI UART 的区别,哪个更快?
2、IIC最大速率
3、IIC协议,帧格式,收发数据的时序流程
4、介绍一下IIC
5、调试IIC过程中遇到的问题
6、iic寻址,主机从机如何对接的