做网页的网站叫什么,什么网站可以免费发布招聘信息,如何自己做代理网站的想法,主页不是wordpress飞书文档https://x509p6c8to.feishu.cn/wiki/MsB7wLebki07eUkAZ1ec12W3nsh
一、简介
IIC协议#xff0c;又称I2C协议#xff0c;是由PHILP公司在80年代开发的两线式串行总线#xff0c;用于连接微控制器及其外围设备#xff0c;IIC属于半双工同步通信方式。 IIC是一种同步…飞书文档https://x509p6c8to.feishu.cn/wiki/MsB7wLebki07eUkAZ1ec12W3nsh
一、简介
IIC协议又称I2C协议是由PHILP公司在80年代开发的两线式串行总线用于连接微控制器及其外围设备IIC属于半双工同步通信方式。 IIC是一种同步的串行通信总线协议它可以在多个设备之间传输数据。IIC总线由两根线组成数据线SDA和时钟线SCL。它使用主从模式其中一个设备作为主设备控制总线并向其他设备发出命令。IIC协议可以支持高速数据传输和多设备通信但它的距离限制较短。 UART是一种异步的串行通信协议它用于在两个设备之间传输数据。UART协议使用两根线TX发送和RX接收。UART没有时钟线数据传输的时序是通过发送和接收设备之间的协议约定实现的。UART协议通常用于短距离通信例如在计算机和串口设备之间进行通信。 因此IIC和UART协议在通信的方式、数据传输速度和距离限制等方面存在差异根据具体的应用场景和需求选择合适的协议更为重要。 多主控(multimastering)
其中任何能够进行发送和接收的设备都可以成为主总线一个主控能够控制信号的传输和时钟频率。当然在任何时间点上只能有一个主控。 特征简单性和有效性
两根线在标准模式下I2C总线的最大长度为5米最大速率为100 kbit/s。在快速模式下I2C总线的最大长度为1米最大速率为400 kbit/s。在高速模式下I2C总线的最大长度为0.4米最大速率为3.4 Mbit/s。需要注意的是总线长度的实际限制还取决于总线上的电容负载和电缆质量等因素。 IIC完成的通讯过程如下 IIC完整的通讯过程
1、总线是空闲状态SCL1SDA 12、要开始传输数据了此时SCL还是高电平SCL1主机将SDA从1变成03、跟哪个从机通讯把从机的地址发出去。一般地址是8个bit也有16个bit的这8个bit其实真实的地址是7个bit最后1个bit是用来表示读或者写的。1表示读0表示写这个过程相当于主机往SDA上发了8个bit的数据地址也是数据啊4、主机发地址的过程相当于在找从机从机是要给应答信号的就是ACK你老板喊你你也得先回答声A吧5、应答之后就是要传输数据了如果第3步中发的地址是写操作那就由主机来控制SDA的电平变化如果第3步中发的地址是读操作那就由从机来控制SDA的电平变化6、每次8bit的数据传输完成都要有个应答信号谁接收数据谁来应答7、完事之后在SCL高电平时主机把SDA从低电平拉高表示结束。 STM32中的I2C
STM32 芯片有多个 I2C 外设它们的 I2C 通讯信号引出到不同的 GPIO 引脚上使用时必须配置到这些指定的引脚。 SMBus(系统管理总线—System Management Bus) SMBus总线和I2C是比较类似的所以STM32兼容了这两种设计一般场景比较少用SMBusI2C则是非常多外设使用的接口我们本节课以I2C为主看看如何使用STM32的I2C功能。
选择为I2C功能后会自动选择对应的IO作为I2C的IO这里I2C是支持重映射的我们可以根据需要手动修改。 然后我们可以设置I2C的主从模式这里我们设置主机模式模式为Standard Mode速率为100000Hz。 Master features 主模式特性
Master 为主机模式相关参数如果是驱动触摸屏、传感器、EEPROM等外设只需配置这里的参数。
Slave 为从机模式相关参数如果是开发触摸屏传感器本身则需要配置从机参数。 Standard Mode标准模式
Fast Mode高速模式
这两种模式支持的通讯速率不同在标准模式中最大只能设置100KHz作为主机时速率大小要看从机支持的最大速率一般来说100KHz可以满足上述的触摸屏、传感器、EEPROM的驱动。 Slave features 从模式特性
作为主机使用时这里无需修改 Clock No Stretch Mode 时钟没有扩展模式 IIC时钟拉伸(Clock stretching)clock stretching通过将SCL线拉低来暂停一个传输.直到释放SCL线为高电平,传输才继续进行.clock stretching是可选的,实际上大多数从设备不包括SCL驱动,所以它们不能stretch时钟. Primary Address Length selection 从设备地址长度 设置从设备的地址是7bit还是10bit 大部分为7bit Dual Address Acknowledged 双地址确认 Primary slave address 从设备初始地址 然后就可以生成MDK工程这里主要用的函数有四个 HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); 功能IIC写数据 参数 *hi2c 设置使用的是那个IIC 例hi2c1 DevAddress 写入的地址 设置写入数据的地址 例 0xA0 *pData 需要写入的数据 Size 要发送的字节数 Timeout 最大传输时间超过传输时间将自动退出传输函数 HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); 功能IIC读一个字节 参数 *hi2c 设置使用的是那个IIC 例hi2c1 DevAddress 写入的地址 设置写入数据的地址 例 0xA0 *pData 存储读取到的数据 Size 发送的字节数 Timeout 最大读取时间超过时间将自动退出读取函数 HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); - 功能IIC写多个数据该函数适用于IIC外设里面还有子地址寄存器的地址比如E2PROM除了 设备地址每个存储字节都有其对应的地址。 - 参数 *hi2c 设置使用的是那个IIC 例hi2c1 DevAddress 写入的地址 设置写入数据的地址 例0xA0 MemAddress 从机寄存器地址每写入一个字节数据地址就会自动1 MemAddSize 从机寄存器地址字节长度 8位/16位 写入数据的字节类型 8位/16位 I2C_MEMADD_SIZE_8BIT I2C_MEMADD_SIZE_16BIT *pData 需要写入的数据的起始地址 Size 传输数据的大小需要发送的字节数 Timeout 最大传输时间超过传输时间将自动退出传输函数 - 例如HAL_I2C_Mem_Write(hi2c1,ADDR,i,I2C_MEMADD_SIZE_8BIT,(I2C_Buffer_Write[i]),8,1000); HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) - 功能IIC读多个数据该函数适用于IIC外设里面还有子地址寄存器的地址比如E2PROM除了 设备地址每个存储字节都有其对应的地址。 - 参数 *hi2c 设置使用的是那个IIC 例hi2c1 DevAddress 读设备的地址 设置读数据的地址 例0xA0 MemAddress 从机寄存器地址每读出一个字节数据地址就会自动1 MemAddSize 从机寄存器地址字节长度 8位/16位 读出数据的字节类型 8位/16位 I2C_MEMADD_SIZE_8BIT I2C_MEMADD_SIZE_16BIT *pData 需要读出的数据的起始地址 Size 传输数据的大小需要读出的字节数 Timeout 最大传输时间超过传输时间将自动退出传输函数 如果只往某个外设中写数据则用Master_Transmit。 如果是外设里面还有子地址例如我们的E2PROM有设备地址还有每个数据的寄存器存储地址。则用Mem_Write。 Mem_Write是2个地址Master_Transmit只有从机地址。 HAL_I2C_Mem_Write(hi2c1, 0xA0, 0, I2C_MEMADD_SIZE_8BIT,WriteBuffer,BufferSize, 0xff); HAL_I2C_Mem_Read(hi2c1, 0xA1, 0, I2C_MEMADD_SIZE_8BIT,ReadBuffer,BufferSize, 0xff); EEPROM
EEPROM (Electrically Erasable Programmable read only memory)是指带电可擦可编程存储器。是一种掉电后数据不丢失的存储芯片。
https://item.szlcsc.com/320744.html BL24C02是一个2Kbit的EEPROM 内部含有256个字节可以存储数据总共有32页每页8Byte。 设备读写地址说明
其中设备地址如下A2 A1 A0对应芯片硬件接的电平 如果我们把A2 A1 A0都接到GND这时候
写数据时设备地址字节应该是0b1010 00000xA0
读数据时设备地址字节应该是0b1010 00010xA1
参考飞书文档 字节写
每次写入一个Byte数据 先发送起始信号发送从设备地址写入标志数据Wbit0等待应答发送写入地址等待应答发送数据等待应答发送结束信号。 页写
每次可以写入一页8Byte的数据 读字节 连续读
连续读操作可通过立即读或选择性读操作启动。在 24C02 发送完一个 8 位字节数据后主器件产生一个应答信号来响应告知 24C02 主器件要求更多的数据对应每个主机产生的应答信号 24C02 将发送一个 8 位数据字节。当主器件不发送应答信号而发送停止位时结束此操作。 STM32CUBEMX开启I2C1对应PB6 PB7 然后打开USART1用于打印日志方便查看 注意要勾选MicroLIB哦否则printf打印不了数据 然后添加代码如下
main.c/* USER CODE BEGIN Includes */
#include stdio.h
/* USER CODE END Includes *//* USER CODE BEGIN 0 */
#define ADDR_24LCxx_Write 0xA0
#define ADDR_24LCxx_Read 0xA1
#define BufferSize 8
uint8_t WriteBuffer[BufferSize] {1,2,3,4,5,6,7,8};
uint8_t ReadBuffer[BufferSize] {0};
/* USER CODE END 0 */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */printf(start to test i2c eeprom\n);if(HAL_I2C_Mem_Write(hi2c1, ADDR_24LCxx_Write, 0, I2C_MEMADD_SIZE_8BIT, WriteBuffer, sizeof(WriteBuffer), 0xff) HAL_OK){printf(EEPROM 24C02 Write Test OK \r\n);}HAL_Delay(10); /* read date from EEPROM */HAL_I2C_Mem_Read(hi2c1, ADDR_24LCxx_Read, 0, I2C_MEMADD_SIZE_8BIT, ReadBuffer, sizeof(ReadBuffer), 0xff);for(int i 0; i sizeof(ReadBuffer); i){printf(0x%02X ,ReadBuffer[i]);}HAL_Delay(1000);}/* USER CODE END 3 *//* USER CODE BEGIN 4 */
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(huart1 , (uint8_t *)ch, 1, 0xFFFF);return ch;
}
打印如下 温湿度传感器 温湿度传感器CJ-GXHT3L
GXHT3L-DIS 是中科银河芯开发的新一代单芯片集成温湿度一 体传感器。
★ I2C 接口通信速度高达 1MHz
★ 两个用户可选择的地址
★ GXHT3L 典型精度为±4%RH 和±0.5°C
★ GXHT30 典型精度为±3%RH 和±0.3°C
★ GXHT31 典型精度为±2%RH 和±0.3°C
★ 单芯片集成温湿传感器
★ 高可靠性和长期稳定性
★ 测量 0-100%范围相对湿度
★ 测量-45-130℃范围内温度
https://item.szlcsc.com/3199174.html 关于设备地址与ADDR管脚说明 这里要注意的是0x44指的是I2C地址的高7位第八位为读写标志位。 0x44 0b0100 0100把最高位去掉 0b100 0100
写数据时设备地址字节应该是0b1000 10000x88
读数据时设备地址字节应该是0b1000 10010x89 高重复率和周期转换频率例如0x2130中21代表每秒转换一次30代表高重复率。 设置进入连续转换模式的命令 * USER CODE BEGIN Includes */
#include stdio.h
#define GXHT3L_ADDR_WRITE 0x441 //10001000
#define GXHT3L_ADDR_READ (0x441)1 //10001001typedef enum
{/* 软件复位命令 */SOFT_RESET_CMD 0x30A2, /* 加热使能/禁能命令 */PREHEAT_ENABLE_CMD 0x306D,PREHEAT_DISENABLE_CMD 0x3066,/* 芯片状态命令 */DEVICE_STATUS_CMD 0xF32D,/*单次测量模式命名格式Repeatability_CS_CMDCSClock stretching*/HIGH_ENABLED_CMD 0x2C06,MEDIUM_ENABLED_CMD 0x2C0D,LOW_ENABLED_CMD 0x2C10,HIGH_DISABLED_CMD 0x2400,MEDIUM_DISABLED_CMD 0x240B,LOW_DISABLED_CMD 0x2416,/*周期测量模式命名格式Repeatability_MPS_CMDMPSmeasurement per second*/HIGH_0_5_CMD 0x2032,MEDIUM_0_5_CMD 0x2024,LOW_0_5_CMD 0x202F,HIGH_1_CMD 0x2130,MEDIUM_1_CMD 0x2126,LOW_1_CMD 0x212D,HIGH_2_CMD 0x2236,MEDIUM_2_CMD 0x2220,LOW_2_CMD 0x222B,HIGH_4_CMD 0x2334,MEDIUM_4_CMD 0x2322,LOW_4_CMD 0x2329,HIGH_10_CMD 0x2737,MEDIUM_10_CMD 0x2721,LOW_10_CMD 0x272A,/* 周期测量模式读取数据命令 */READOUT_FOR_PERIODIC_MODE 0xE000,
} GXHT3L_CMD;
/* USER CODE END Includes *//* USER CODE BEGIN 0 */
/*** brief 向GXHT3L发送一条指令(16bit)* param cmd —— GXHT3L指令在GXHT3L_MODE中枚举定义* retval 成功返回HAL_OK
*/
static uint8_t GXHT3L_Send_Cmd(GXHT3L_CMD cmd)
{uint8_t cmd_buffer[2];cmd_buffer[0] cmd 8;cmd_buffer[1] cmd;return HAL_I2C_Master_Transmit(hi2c2, GXHT3L_ADDR_WRITE, (uint8_t*) cmd_buffer, 2, 0xFFFF);
}/*** brief 复位GXHT3L* param none* retval none
*/
static void GXHT3L_Reset(void)
{GXHT3L_Send_Cmd(SOFT_RESET_CMD);HAL_Delay(20);
}void GXHT3L_Preheat_Disable(void)
{GXHT3L_Send_Cmd(PREHEAT_DISENABLE_CMD);HAL_Delay(20);
}uint8_t GXHT3L_Read_Status(uint8_t* dat)
{GXHT3L_Send_Cmd(DEVICE_STATUS_CMD);return HAL_I2C_Master_Receive(hi2c2, GXHT3L_ADDR_READ, dat, 3, 0xFFFF);
}/*** brief 初始化GXHT3L* param none* retval 成功返回HAL_OK* note 周期测量模式
*/
uint8_t GXHT3L_Init(void)
{return GXHT3L_Send_Cmd(MEDIUM_2_CMD);
}/*** brief 从GXHT3L读取一次数据* param dat —— 存储读取数据的地址6个字节数组* retval 成功 —— 返回HAL_OK
*/
uint8_t GXHT3L_Read_Dat(uint8_t* dat)
{GXHT3L_Send_Cmd(READOUT_FOR_PERIODIC_MODE);return HAL_I2C_Master_Receive(hi2c2, GXHT3L_ADDR_READ, dat, 6, 0xFFFF);
}#define CRC8_POLYNOMIAL 0x31uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value)
{uint8_t remainder; //余数uint8_t i 0, j 0; //循环变量/* 初始化 */remainder initial_value;for(j 0; j 2;j){remainder ^ message[j];/* 从最高位开始依次计算 */for (i 0; i 8; i){if (remainder 0x80){remainder (remainder 1)^CRC8_POLYNOMIAL;}else{remainder (remainder 1);}}}/* 返回计算的CRC码 */return remainder;
}/*** brief 将GXHT3L接收的6个字节数据进行CRC校验并转换为温度值和湿度值* param dat —— 存储接收数据的地址6个字节数组* retval 校验成功 —— 返回0* 校验失败 —— 返回1并设置温度值和湿度值为0
*/
uint8_t GXHT3L_Dat_To_Float(uint8_t* const dat, float* temperature, float* humidity)
{uint16_t recv_temperature 0;uint16_t recv_humidity 0;/* 校验温度数据和湿度数据是否接收正确 */if(CheckCrc8(dat, 0xFF) ! dat[2] || CheckCrc8(dat[3], 0xFF) ! dat[5])return 1;/* 转换温度数据 */recv_temperature ((uint16_t)dat[0]8)|dat[1];*temperature -45 175*((float)recv_temperature/65535);/* 转换湿度数据 */recv_humidity ((uint16_t)dat[3]8)|dat[4];*humidity 100 * ((float)recv_humidity / 65535);return 0;
}/* USER CODE BEGIN 1 */uint8_t recv_dat[6] {0};uint8_t recv_status[3] {0};float temperature 0.0;float humidity 0.0;/* USER CODE END 1 *//* USER CODE BEGIN 2 */GXHT3L_Reset();if(GXHT3L_Init() HAL_OK)printf(GXHT3L init ok.\n);elseprintf(GXHT3L init fail.\n);if(GXHT3L_Read_Status(recv_status) HAL_OK){printf(GXHT3L Read Status ok. Status 0x%x%x\n,recv_status[0],recv_status[1]);}elseprintf(GXHT3L Read Status fail.\n);/* USER CODE END 2 */while (1){/* USER CODE BEGIN 3 */HAL_Delay(1000);if(GXHT3L_Read_Dat(recv_dat) HAL_OK){if(GXHT3L_Dat_To_Float(recv_dat, temperature, humidity)0){printf(temperature %f, humidity %f\n, temperature, humidity);}else{printf(crc check fail.\n);}}else{printf(read data from GXHT3L fail.\n);}}/* USER CODE END 3 *//* USER CODE BEGIN 4 */
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(huart1 , (uint8_t *)ch, 1, 0xFFFF);return ch;
}
/* USER CODE END 4 */
最终工程可以参考淘宝旺旺发送的源码部分哦