操作系统:Windows 11 (x64)
微控制器:STM32F103C8T6
硬件外设:
-
USB-to-TTL串口(CH340)
【STM32】标准库与HAL库对照学习教程八--串口通信详解__修成真的博客https://xiuchengzhen.blog.csdn.net/article/details/121429721
-
SHT3x温湿度模块
STM32CubeIDE之SHT3X温湿度传感器移植HAL库_小梁子LZ的博客有了前面的OLED的学习,这个学习起来也很快。分以下几步走1.你要有个温度传感器,SHT3X这个型号的,因为我要讲这个2.你要有个STM32开发板(我用的是STM32L431RCT)3.顺便找台电脑下载一个STM32CubeIDE4.简单的找一个SHT3X的驱动,我是去某宝嫖的,一般卖这个的都有,这个驱动分两个文件,是.c和.h的,我直接把这两个放在下边读了我上一篇的人,看这个应该很熟悉吧,一样的套路,学习方法是一样的,你就照搬就行下面是sht3x.c的原文档,里面有个CRC..https://blog.csdn.net/qq_47736089/article/details/124675784
-
2节1.5V电池串联电源
-
杜邦线
工程文件:STM32CubeMX
-
配置 RCC 高速晶振,HCLK 为 72MHz
-
配置 SYS Debug 为 Serial Wire
-
使能 I2C1 用于 连接外设SHT3x
-
使能 USART1 异步 用于 串口通信,中断使能
IDE编辑/编译:Keil uVision5 MDK-ARM V5.32 / ARM Compiler V5
*** 新下载的 Keil uVision 没有 Compiler V5,需要下载ARMCC文件夹并且手动添加路径
图标“三方块”(项目管理) ==> (Folders/Extensions) ==> (Use ARM Complier [...]) ==> Add another
安装最新版keil5编译报错*** target ‘target 1‘ uses arm-compiler ‘default compiler version 5‘ which i,keil5.37版_mdk5编译出错_Score A的博客-CSDN博客原因是missingcompilerversion5,缺少V5编译器(compilerversion5),因为打开的工程比较老,是用v5的编译器写的,而现在下的keil5不再预装v5编译器;网上有很多说把Optionsfortarget中的ARMCompiler换成其他的试一下(因为那儿显示的是missingcompilerversion5,是因为。下载了放在ARM文件夹内,然后用上面的步骤添加下载的文件夹,就能用V5的编译器了。然后就是这样子,再点OK就行啦。...https://blog.csdn.net/qq_62078460/article/details/125579899?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168370144816800215031572%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168370144816800215031572&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-2-125579899-null-null.142%5Ev86%5Econtrol,239%5Ev2%5Einsert_chatgpt&utm_term=keil%20missing%20compiler%20version5&spm=1018.2226.3001.4187
烧录:CMSIS-DAP Debugger (创芯工坊 PWLINK2)
串口收发:
开启接收中断
Rx_buff 缓存是用来接收PC端发来的数据
HAL_UART_Receive_IT(&huart1, (uint8_t *)&Rx_buff, 1);
接收中断回调函数
Rx_String 将接收缓存原样发送回PC
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart == &huart1){Rx_String[Rx_Flag++] = Rx_buff; if(Rx_String[Rx_Flag-1] == 0x0A) {HAL_UART_Transmit(&huart1, (uint8_t *)&Rx_String, Rx_Flag,0xFFFF); while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX); memset(Rx_String,0x00,sizeof(Rx_buff)); Rx_Flag = 0; }HAL_UART_Receive_IT(&huart1, (uint8_t *)&Rx_buff, 1); }
}
串口发送
重定向printf()
意为重新定义 fputc 和 fgetc 以实现串口打印
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);return ch;
}int fgetc(FILE *f)
{uint8_t ch = 0;HAL_UART_Receive(&huart1, &ch, 1, 0xffff);return ch;
}
温湿度模块SHT3x驱动文件:
包含驱动文件 sht3x.c 和 sht3x.h
如何添加 .c .h 文件:
项目工程下(三方块图标)—— 新建Groups(虚线方框)—— 添加外部ch文件 —— OK;
魔法棒 —— C/C++ —— Include Paths —— 新建Path —— 添加外部ch文件夹 —— OK;
Keil5添加.c文件与.h文件的方法-导入支持库-新大陆物联网竞赛-Lora模块&NBIOT模块例程-添加导入文件_keil如何在c文件中添加h文件_西西菜鸟的博客-CSDN博客本文内容是Keil5的.c文件与.h文件的导入示例,导入所支持的文件库,可以使得我们学习并了解到更多的程序内容。https://blog.csdn.net/qq_39724355/article/details/127537579
sht3x.c 注意:
在 sht3x.c 中修改相应单片机型号的头文件;
0x44代表将 ADDR 针脚接地,如接高电平则应改为0x45;
以及所启用的I2C口,这里是I2C1,需 Ctrl+F 全局确认变量名是否统一;
#include "sht3x.h"
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h" #define SHT30_ADDR_WRITE 0x44<<1
#define SHT30_ADDR_READ (0x44<<1)+1
extern I2C_HandleTypeDef hi2c1;
sht3x.h 注意:
同样,修改包含的头文件名如果不是F1板;
头文件的最后一行必须是空行(不能有空格),意为 #endif ... 后必须回车;
#ifndef __SHT30_H_
#define __SHT30_H_#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
读取数据
uint8_t SHT30_Read_Dat(uint8_t* dat);uint8_t SHT30_Dat_To_Float(uint8_t* const dat, float* temperature, float* humidity);
主要由以上两个函数结合实现,SHT30_Read_Dat 可以粗略理解为通过I2C接收了一串来自
SHT3x的(16-bit 温度 ST + 16-bit 湿度 SRH)的数据流,将如此 raw data 存入提前声明的
变量中;SHT30_Dat_To_Float 则是将 raw data 通过以下公式转换成 温度 和 湿度 两个数据
并分别存入提前声明的变量中。
主函数代码:
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "string.h"
#include "sht3x.h"
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */
uint8_t Rx_String[100];
uint8_t Rx_Flag=0;
uint8_t Rx_buff;
/* USER CODE END PV */
/* USER CODE BEGIN 2 */SHT30_Reset();SHT30_Init();HAL_UART_Receive_IT(&huart1, (uint8_t *)&Rx_buff, 1);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){uint8_t dat;float temp, humi;SHT30_Read_Dat(&dat);SHT30_Dat_To_Float(&dat,&temp,&humi);printf("Temp:%.1f,Humi:%.1f\n",temp,humi);HAL_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart == &huart1){Rx_String[Rx_Flag++] = Rx_buff; if(Rx_String[Rx_Flag-1] == 0x0A) {HAL_UART_Transmit(&huart1, (uint8_t *)&Rx_String, Rx_Flag,0xFFFF); while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX); memset(Rx_String,0x00,sizeof(Rx_buff)); Rx_Flag = 0; }HAL_UART_Receive_IT(&huart1, (uint8_t *)&Rx_buff, 1); }
}int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);return ch;
}int fgetc(FILE *f)
{uint8_t ch = 0;HAL_UART_Receive(&huart1, &ch, 1, 0xffff);return ch;
}/* USER CODE END 4 */
运行结果: