STM32开发(九)STM32F103 通信

您所在的位置:网站首页 stm32f103数码管程序 STM32开发(九)STM32F103 通信

STM32开发(九)STM32F103 通信

2023-03-22 06:31| 来源: 网络整理| 查看: 265

文章目录 一、基础知识点二、开发环境三、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相关配置 (1)GPIO配置 在这里插入图片描述 配置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(i=0;i uint8_t RD_Byte=0,i; for(i=0; i I2C_SDA_RESET; // 主机SDA清零,回应从机ACK,接收成功 } else { I2C_SDA_SET; // 主机SDA置高,回应从机NACK,接收失败 } I2C_SCL_SET; // SCL置高,发送ACK I2C_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(i=0;i 0.0, 0, Measure_Period_Mode };

调用I2C接口实现SHT30时序,获取当前温湿度值

#define SHT3X_ADDR (uint8_t)(0x44 0}; uint16_t temp_uint = 0; float temp_float = 0; // 1、设备芯片检测模式:启动周期性测量 High repeat , mps = 10 Myi2c.start(); Myi2c.Write_Byte(SHT3X_ADDR&Write_CMD); Myi2c.Write_Byte(0x27); Myi2c.Write_Byte(0x37); // 2、读当前温湿度值,寄存器0xE000 Timer6.SHT30_Measure_Timeout =0; // 使用定时器6 定时测量时间 do { if(Timer6.SHT30_Measure_Timeout >= TIMER6_2S) //2s内没获取到数据,退出等待 break; Myi2c.start(); Myi2c.Write_Byte(SHT3X_ADDR&Write_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 temp_uint = SHT32X_RD_array[0]*256+SHT32X_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]*256+SHT32X_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 Temp_float = SHT3X.fTemperature_Value; Display.Disp_Other(Disp_NUM_GRID3,0x00,Disp_DP_OFF); //4号数码管关闭 } Temp_uint = (uint16_t)(Temp_float*10); Display.Disp(Disp_NUM_GRID4,Temp_uint/100,Disp_DP_OFF); Display.Disp(Disp_NUM_GRID5,Temp_uint%100/10,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.c +++ b/MyApplication/Src/Modbus.c @@ -106,24 +106,26 @@ static void Modbus_Read_Register(UART_t* UART) //功能码 *(COM_UART->pucSend_Buffer+1) = FunctionCode_Read_Register; //数据长度(字节) - *(COM_UART->pucSend_Buffer+2) = 2; + *(COM_UART->pucSend_Buffer+2) = 6; //发送数据 // deep status *(COM_UART->pucSend_Buffer+3) = 0; *(COM_UART->pucSend_Buffer+4) = Deep.Read_Deep(); - *(COM_UART->pucSend_Buffer+5) = 0; - *(COM_UART->pucSend_Buffer+6) = 0x66; + *(COM_UART->pucSend_Buffer+5) = ((uint16_t)(SHT3X.fTemperature_Value*10))/256; + *(COM_UART->pucSend_Buffer+6) = ((uint16_t)(SHT3X.fTemperature_Value*10))%256; + *(COM_UART->pucSend_Buffer+7) = 0; + *(COM_UART->pucSend_Buffer+8) = 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_Buffer+7) = CRC_16.CRC_L; - *(COM_UART->pucSend_Buffer+8) = CRC_16.CRC_H; + *(COM_UART->pucSend_Buffer+9) = CRC_16.CRC_L;^M + *(COM_UART->pucSend_Buffer+10) = 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 0x8f:CRC校验码

[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/10=21.4℃ (发送代码将值乘以10,这里需要除以10获取真实温度值) 0x00 0x2e:读取第二个数据为0x2e,湿度值=46 0x91 0x40:CRC校验码



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3