专注手机网站建设上传文件网站

当前位置: 首页 > news >正文

专注手机网站建设,上传文件网站,网页打不开怎么办页面无法显示,网站建设和咨询服务合同文章目录一、基础知识点二、开发环境三、STM32CubeMX相关配置四、Vscode代码讲解GPIO模拟I2C代码SHT30相关代码main函数中循环代码五、结果演示方式一、示波器分析I2C数据方式2、通过Modbus将获取到的数据传到PC上一、基础知识点 本实验通过I2C通信获取SHT30温湿度值#xff… 文章目录一、基础知识点二、开发环境三、STM32CubeMX相关配置四、Vscode代码讲解GPIO模拟I2C代码SHT30相关代码main函数中循环代码五、结果演示方式一、示波器分析I2C数据方式2、通过Modbus将获取到的数据传到PC上一、基础知识点 本实验通过I2C通信获取SHT30温湿度值显示数码管以及通过modbus协议传送给PC端。 本实验内容知识点 1、 I2C通信协议 2、温湿度传感器 SHT3x-DIS 手册 解析 、TM1620芯片手册 解析 3、数码管显示 详解 4、RS485 Modbus通信编程详解 5、定时器中断 详解 6、I2C引脚SDA既要输出也要输入因此要配置为准双向口。先来看下STM32普通GPIO口内部图了解下准双向口。 将IO口配置为开漏输出时输出控制器中P-MOS管断开输出通过N-MOS管决定。 只有输出高电平的时候N-MOS管截止这时IO口就能作为输入使用获取IO口的状态。P-MOS和N-MOS都截止 这样I2C SDA引脚就不用重新初始化为输入模式。这也就是准双向口的原理。 准备好了吗开始实战show time。 二、开发环境 1、硬件开发准备 主控STM32F103ZET6 温湿度传感器SHT3X 2、软件开发准备 软件开发使用虚拟机 VScode STM32Cube 开发STM32在虚拟机中直接完成编译下载。 该部分可参考软件开发环境构建 三、STM32CubeMX相关配置 1、STM32CubeMX基本配置 本实验基于CubeMX详解构建基本框架 进行开发。 2、STM32CubeMX I2C相关配置 1GPIO配置 配置I2C两个引脚默认高电平I2C处于空闲状态 配置I2C两个引脚为开漏输出。 四、Vscode代码讲解 GPIO模拟I2C代码 I2C时序由空闲时序、开始时序、停止时序、发送一个字节时序、接收一个字节时序这四种时序部分组成。GPIO只要模拟出这四种时序就能满足所有的完整I2C时序。因此制作一个结构体来实现所有I2C时序部分接口。其他函数就能直接调用这几个接口构成完整的I2C时序通信。 typedef struct {void (*Init)(void); //I2C初始化——I2C空闲时序void (*start)(void); //I2C开始时序void (*stop)(void); //I2C停止时序 ACK_Value_t (*Write_Byte)(uint8_t); //I2C写字节时序uint8_t (*Read_Byte) (ACK_Value_t); //I2C读字节时序 } Myi2c_t;Myi2c_t Myi2c {Init,start,stop,Write_Byte,Read_Byte };实现具体的I2C时序 初始化I2C信号 —— 空闲信号SCL和SDA信号都为高电平 static void Init(void)
{I2C_SCL_SET; // SCL置高 I2C_SDA_SET; // SDA置高 } 开始信号SCL为高电平时SDA由高电平向低电平跳变开始传送数据。 static void start(void) {I2C_SCL_SET; // SCL置高I2C_SDA_SET; // SDA置高I2C_Delay_us(1);I2C_SDA_RESET; // SDA清零I2C_Delay_us(10);I2C_SCL_RESET; // SCL清零I2C_Delay_us(1); }结束信号SCL为高电平时SDA由低电平向高电平跳变结束传送数据。 static void stop(void) {I2C_SDA_RESET; // SDA清零I2C_SCL_SET; // SCL置高I2C_Delay_us(1);I2C_SDA_SET; // SDA置高I2C_Delay_us(10); }I2C写字节时序1、主机发送1个字节2、接收从机发来的ACK信号 3、释放信号线 注在SCL低变高的时候数据变化在SCL高电平时保持数据变化 static ACK_Value_t Write_Byte(uint8_t data) {uint8_t i;ACK_Value_t ACK_Rspond;// When SCL is in low power hours, SDA changes its state. // When SCL is in high power hours, SDA state must be stable.for(i0;i8;i){I2C_SCL_RESET; // SCL清零准备发送数据位I2C_Delay_us(1);if((dataBIT7) BIT7) // 要发送的数据最高位高位先发I2C_SDA_SET;elseI2C_SDA_RESET;I2C_Delay_us(1);I2C_SCL_SET; // SCL置高发送数据I2C_Delay_us(10);data 1; // 移位准备下个数据位发送}I2C_SCL_RESET; // SCL清零准备接收从机发来的ACK信号I2C_SDA_SET; // 将SDA释放信号I2C_Delay_us(1);I2C_SCL_SET; // 接收从机发来的信号I2C_Delay_us(10);ACK_Rspond (ACK_Value_t)I2C_READ_SDA; // 将信号保存到ACK_RspondI2C_SCL_RESET; // 释放SCLI2C_Delay_us(1);return ACK_Rspond; // 返回ACK信号 }
I2C读字节时序1、主机接收1个字节2、接收完成主机发ACK信号回复从机 3、释放信号线 注在SCL低变高的时候数据变化在SCL高电平时保持数据变化可采到接收值 static uint8_t Read_Byte(ACK_Value_t ack) {uint8_t RD_Byte0,i;for(i0; i8; i) // 循环接收一个字节数据{RD_Byte 1; // 准备接收下一位数据I2C_SCL_RESET; // SCL清零从机SDA准备数据I2C_Delay_us(10);I2C_SCL_SET; // SCL置高获取数据I2C_Delay_us(10);RD_Byte | I2C_READ_SDA; // 将数据保存在RD_Byte缓存里}I2C_SCL_RESET; //SCL清零主机准备应答信号I2C_Delay_us(1);if(ack ACK){I2C_SDA_RESET; // 主机SDA清零回应从机ACK接收成功}else{I2C_SDA_SET; // 主机SDA置高回应从机NACK接收失败}I2C_SCL_SET; // SCL置高发送ACKI2C_Delay_us(10);//释放SDA数据线//SCL先清零再释放SDA防止连续传输数据时从机错将SDA释放信号当成NACk信号I2C_SCL_RESET; I2C_SDA_SET; I2C_Delay_us(1);return RD_Byte; // 返回接收到的字节 }static void I2C_Delay_us(uint8_t us) {uint8_t i 0;//通过示波器测量进行校准while(us–){for(i0;i7;i);} }SHT30相关代码 构建一个SHT30结构体并初始化 typedef struct {float fTemperature_Value; // 保存温度值uint8_t ucHumidity_Value; // 保存湿度值void (*Measure_Period_Mode)(void); // 测量函数 } SHT3X_t;extern SHT3X_t SHT3X;SHT3X_t SHT3X {0.0,0,Measure_Period_Mode }; 调用I2C接口实现SHT30时序获取当前温湿度值 #define SHT3X_ADDR (uint8_t)(0x44 1) // SHT30地址I2C地址位为7位因此一定要向左移一位。第8位为读写位 #define Write_CMD 0xFE #define Read_CMD 0x01static void Measure_Period_Mode(void) {uint8_t SHT32X_RD_array[6] {0};uint16_t temp_uint 0;float temp_float 0;// 1、设备芯片检测模式启动周期性测量 High repeat , mps 10Myi2c.start();Myi2c.Write_Byte(SHT3X_ADDRWrite_CMD);Myi2c.Write_Byte(0x27);Myi2c.Write_Byte(0x37);// 2、读当前温湿度值寄存器0xE000Timer6.SHT30_Measure_Timeout 0; // 使用定时器6 定时测量时间do{if(Timer6.SHT30_Measure_Timeout TIMER6_2S) //2s内没获取到数据退出等待break;Myi2c.start();Myi2c.Write_Byte(SHT3X_ADDRWrite_CMD);Myi2c.Write_Byte(0xE0);Myi2c.Write_Byte(0x00);Myi2c.start();} while (Myi2c.Write_Byte(SHT3X_ADDR | Read_CMD) NACK);if(Timer6.SHT30_Measure_Timeout TIMER6_2S){SHT32X_RD_array[0]Myi2c.Read_Byte(ACK);SHT32X_RD_array[1]Myi2c.Read_Byte(ACK);SHT32X_RD_array[2]Myi2c.Read_Byte(ACK);SHT32X_RD_array[3]Myi2c.Read_Byte(ACK);SHT32X_RD_array[4]Myi2c.Read_Byte(ACK);SHT32X_RD_array[5]Myi2c.Read_Byte(NACK);Myi2c.stop();// 3、CRC校验以及温度计算见手册讲解if(CRC_8(SHT32X_RD_array,2) SHT32X_RD_array[2]) //CRC-8 校验{temp_uint SHT32X_RD_array[0]*256SHT32X_RD_array[1];temp_float ((float)temp_uint)*0.267032-4500;SHT3X.fTemperature_Value temp_float*0.01;}// 3、CRC校验以及温度计算见手册讲解if(CRC_8(SHT32X_RD_array[3],2) SHT32X_RD_array[5]) //CRC-8 校验{temp_uint SHT32X_RD_array[3]*256SHT32X_RD_array[4];temp_float ((float)temp_uint)*0.152590;temp_float temp_float*0.01;SHT3X.ucHumidity_Value (unsigned char)temp_float; }} } main函数中循环代码 while (1) {float Temp_float 0;uint16_t Temp_uint 0;//获取SHT30的温湿度SHT3X.Measure_Period_Mode();//数码管显示//温度if(SHT3X.fTemperature_Value 0) //负温{Temp_float 0 - SHT3X.fTemperature_Value;Display.Disp_Other(Disp_NUM_GRID3,0x40,Disp_DP_OFF); //4号数码管显示负号}else{Temp_float SHT3X.fTemperature_Value;Display.Disp_Other(Disp_NUM_GRID3,0x00,Disp_DP_OFF); //4号数码管关闭}Temp_uint (uint16_t)(Temp_float10);Display.Disp(Disp_NUM_GRID4,Temp_uint/100,Disp_DP_OFF);Display.Disp(Disp_NUM_GRID5,Temp_uint%10010,Disp_DP_ON);Display.Disp(Disp_NUM_GRID6,Temp_uint%10,Disp_DP_OFF);//湿度Display.Disp(Disp_NUM_GRID1,SHT3X.ucHumidity_Value/10,Disp_DP_OFF);Display.Disp(Disp_NUM_GRID2,SHT3X.ucHumidity_Value%10,Disp_DP_OFF);HAL_Delay(500); }五、结果演示 方式一、示波器分析I2C数据 实验结果 温度21.4℃ 湿度47 方式2、通过Modbus将获取到的数据传到PC上 修改Modbus相关代码 diff –git a/MyApplication/Src/Modbus.c b/MyApplication/Src/Modbus.c index 7665eee..b6caf10 100755 — a/MyApplication/Src/Modbus.cb/MyApplication/Src/Modbus.c-106,24 106,26 static void Modbus_Read_Register(UART_t UART)//功能码*(COM_UART-pucSend_Buffer1) FunctionCode_Read_Register;//数据长度(字节)

  • (COM_UART-pucSend_Buffer2) 2;(COM_UART-pucSend_Buffer2) 6;//发送数据// deep status(COM_UART-pucSend_Buffer3) 0;(COM_UART-pucSend_Buffer4) Deep.Read_Deep();
  • *(COM_UART-pucSend_Buffer5) 0;
  • (COM_UART-pucSend_Buffer6) 0x66;(COM_UART-pucSend_Buffer5) ((uint16_t)(SHT3X.fTemperature_Value10))/256;(COM_UART-pucSend_Buffer6) ((uint16_t)(SHT3X.fTemperature_Value10))%256;(COM_UART-pucSend_Buffer7) 0;*(COM_UART-pucSend_Buffer8) SHT3X.ucHumidity_Value;//插入CRC
  • CRC_16.CRC_Value CRC_16.CRC_Check(COM_UART-pucSend_Buffer,7); //计算CRC值CRC_16.CRC_Value CRC_16.CRC_Check(COM_UART-pucSend_Buffer,9); //计算CRC值CRC_16.CRC_H (uint8_t)(CRC_16.CRC_Value 8);CRC_16.CRC_L (uint8_t)CRC_16.CRC_Value;- *(COM_UART-pucSend_Buffer7) CRC_16.CRC_L;
  • (COM_UART-pucSend_Buffer8) CRC_16.CRC_H;(COM_UART-pucSend_Buffer9) CRC_16.CRC_L;^M*(COM_UART-pucSend_Buffer10) CRC_16.CRC_H;^M//发送数据
  • UART3.SendArray(COM_UART-pucSend_Buffer,9);UART3.SendArray(COM_UART-pucSend_Buffer,11);}}主设备为PC端安装的MThings进行Modbus收发数据。 MThings软件具体操作可参考Modbus通信详解中的结果演示以及报文解析 [2023-03-18 15:45:34-919]COM38-发送01 03 9c 41 00 03 7b 8f 0x01主机要查询的从设备地址 0x03功能码 查询读操作 0x9c 0x41寄存器地址0x9c41转十进制地址为40,001 0x00 0x02读取三个数据一个数据3字节 0x7b 0x8fCRC校验码 [2023-03-18 15:45:34-941]COM38-接收01 03 06 00 00 00 d6 00 2e 91 40 0x01告诉主机自己从设备地址 0x03功能码 读操作 0x00 0x00读出第一个数据为0x01当前蜂鸣器关闭状态 0x00 0xd6读取第二个数据为0xd6温度值214/1021.4℃ 发送代码将值乘以10这里需要除以10获取真实温度值 0x00 0x2e读取第二个数据为0x2e湿度值46 0x91 0x40CRC校验码