stm32g431水温传感器代码
时间: 2025-07-05 21:00:50 浏览: 12
<think>我们正在寻找适用于STM32G431微控制器的水温传感器代码示例。水温传感器通常使用DS18B20(单总线协议)或NTC热敏电阻(模拟电压读取)等。这里我们假设使用DS18B20数字温度传感器,因为它更常见且易于集成。步骤:1.配置微控制器的GPIO引脚用于单总线通信。2.初始化单总线并检测DS18B20的存在。3.发送温度转换命令并读取结果。注意:STM32G431需要使用HAL库进行开发。我们将使用一个GPIO引脚(例如PA0)作为单总线数据线。代码示例将包括:-初始化单总线-发送复位脉冲-读写位-读取温度值由于DS18B20的通信协议要求严格的时序,我们将使用延时函数(基于HAL库的延时)并直接操作GPIO。以下是示例代码的框架:```c#include"main.h"#include<string.h>//定义单总线引脚#defineDS18B20_PINGPIO_PIN_0#defineDS18B20_PORTGPIOA//单总线函数声明voidDS18B20_Init(void);uint8_tDS18B20_Start(void);voidDS18B20_WriteBit(uint8_tbit);uint8_tDS18B20_ReadBit(void);voidDS18B20_WriteByte(uint8_tbyte);uint8_tDS18B20_ReadByte(void);floatDS18B20_GetTemp(void);//延时函数(微秒级别)voidDelay_us(uint16_tus){uint16_ti;for(i=0;i<us;i++){//根据系统时钟调整,这里假设系统时钟为16MHz,每个循环约1us(实际需要调整)__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();}}//初始化单总线voidDS18B20_Init(void){//配置GPIO为开漏输出模式,并初始化为高电平GPIO_InitTypeDefGPIO_InitStruct={0};GPIO_InitStruct.Pin=DS18B20_PIN;GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_OD;//开漏输出GPIO_InitStruct.Pull=GPIO_NOPULL;GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(DS18B20_PORT,&GPIO_InitStruct);HAL_GPIO_WritePin(DS18B20_PORT,DS18B20_PIN,GPIO_PIN_SET);}//发送复位脉冲并检测存在脉冲uint8_tDS18B20_Start(void){uint8_tresponse=0;//拉低480us以上HAL_GPIO_WritePin(DS18B20_PORT,DS18B20_PIN,GPIO_PIN_RESET);Delay_us(480);//保持480us的低电平//释放总线(拉高)HAL_GPIO_WritePin(DS18B20_PORT,DS18B20_PIN,GPIO_PIN_SET);Delay_us(60);//等待15-60us后读取存在脉冲//读取存在脉冲(低电平表示存在)if(!HAL_GPIO_ReadPin(DS18B20_PORT,DS18B20_PIN)){response=1;//检测到存在脉冲}Delay_us(420);//等待剩余时间,使复位周期达到至少960usreturnresponse;}//写一个位voidDS18B20_WriteBit(uint8_tbit){HAL_GPIO_WritePin(DS18B20_PORT,DS18B20_PIN,GPIO_PIN_RESET);Delay_us(bit?5:60);//写1保持5us,写0保持60usHAL_GPIO_WritePin(DS18B20_PORT,DS18B20_PIN,GPIO_PIN_SET);Delay_us(bit?60:5);//恢复时间}//读一个位uint8_tDS18B20_ReadBit(void){uint8_tbit=0;HAL_GPIO_WritePin(DS18B20_PORT,DS18B20_PIN,GPIO_PIN_RESET);Delay_us(2);//拉低2usHAL_GPIO_WritePin(DS18B20_PORT,DS18B20_PIN,GPIO_PIN_SET);Delay_us(12);//等待12us后读取if(HAL_GPIO_ReadPin(DS18B20_PORT,DS18B20_PIN)){bit=1;}Delay_us(50);//整个时隙结束returnbit;}//写一个字节voidDS18B20_WriteByte(uint8_tbyte){for(uint8_ti=0;i<8;i++){DS18B20_WriteBit(byte&0x01);byte>>=1;}}//读一个字节uint8_tDS18B20_ReadByte(void){uint8_tbyte=0;for(uint8_ti=0;i<8;i++){byte>>=1;if(DS18B20_ReadBit()){byte|=0x80;}}returnbyte;}//获取温度值(摄氏度)floatDS18B20_GetTemp(void){uint8_ttemp_lsb,temp_msb;int16_ttemp;floattemperature;if(DS18B20_Start()){DS18B20_WriteByte(0xCC);//跳过ROMDS18B20_WriteByte(0x44);//启动温度转换//等待转换完成(可以查询总线,但这里简单延时)Delay_us(800000);//等待750ms(12位分辨率)DS18B20_Start();DS18B20_WriteByte(0xCC);//跳过ROMDS18B20_WriteByte(0xBE);//读取暂存器temp_lsb=DS18B20_ReadByte();temp_msb=DS18B20_ReadByte();temp=(temp_msb<<8)|temp_lsb;temperature=temp*0.0625;//12位精度,每个单位0.0625摄氏度returntemperature;}return-1000;//错误值}//在主函数中使用示例intmain(void){HAL_Init();//配置系统时钟等(省略)DS18B20_Init();floattemp=DS18B20_GetTemp();//使用温度值(例如通过串口发送)while(1);}```注意:上述代码中的延时函数`Delay_us`是简单的循环延时,实际应用中可能需要使用定时器来获得更精确的延时,或者使用HAL库的`HAL_Delay`(但HAL_Delay最小延时为1ms,不适用于us级延时)。因此,对于严格的时序,建议使用定时器或者调整循环次数以适应系统时钟。此外,由于DS18B20的通信时序要求严格,如果系统中有中断干扰,可能导致通信失败。因此,在实际应用中,可能需要暂时关闭中断。以上代码是一个基础示例,实际使用时需要根据硬件连接和系统时钟进行调整。§§相关问题§§1.如何提高DS18B20温度读取的精度?2.如何处理多个DS18B20传感器在同一总线上的情况?3.除了DS18B20,还有哪些适合STM32G431的水温传感器?4.如何通过STM32G431的ADC读取NTC热敏电阻的温度?</think>### STM32G431 水温传感器代码示例
以下是一个基于STM32G431的DS18B20数字水温传感器实现方案。DS18B20采用单总线协议,具有精度高(±0.5°C)、抗干扰强等优点,适合水温监测场景。
#### 硬件配置
1. **传感器**:DS18B20(防水型)
2. **连接方式**:
- VDD: 3.3V
- DQ: PA0 (单总线数据线)
- GND: 接地
3. **需4.7KΩ上拉电阻**:连接在DQ与VDD之间
#### 代码实现
```c
/* 文件: main.c */
#include "main.h"
#include <string.h>
// 单总线定义
#define DS18B20_PORT GPIOA
#define DS18B20_PIN GPIO_PIN_0
// 函数声明
void DS18B20_Init(void);
void DS18B20_StartConversion(void);
float DS18B20_ReadTemp(void);
static void Set_Pin_Output(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
static void Set_Pin_Input(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);
static uint8_t DS18B20_Reset(void);
static void DS18B20_WriteByte(uint8_t data);
static uint8_t DS18B20_ReadByte(void);
int main(void) {
HAL_Init();
SystemClock_Config();
// 初始化单总线
DS18B20_Init();
while (1) {
// 启动温度转换
DS18B20_StartConversion();
HAL_Delay(750); // 等待转换完成(12位精度需750ms)
// 读取温度
float temp = DS18B20_ReadTemp();
// 通过串口输出温度(需先初始化USART)
printf("水温: %.2f °C\n", temp);
HAL_Delay(2000); // 每2秒采样一次
}
}
// 初始化单总线GPIO
void DS18B20_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = DS18B20_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DS18B20_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET); // 初始高电平
}
// 启动温度转换
void DS18B20_StartConversion(void) {
if (DS18B20_Reset()) {
DS18B20_WriteByte(0xCC); // 跳过ROM
DS18B20_WriteByte(0x44); // 启动温度转换命令
}
}
// 读取温度值
float DS18B20_ReadTemp(void) {
uint8_t tempL, tempH;
int16_t temp;
if (DS18B20_Reset()) {
DS18B20_WriteByte(0xCC); // 跳过ROM
DS18B20_WriteByte(0xBE); // 读暂存器命令
tempL = DS18B20_ReadByte(); // LSB
tempH = DS18B20_ReadByte(); // MSB
temp = (tempH << 8) | tempL;
return (float)temp / 16.0; // 12位精度转换
}
return -1000; // 错误返回值
}
/* 底层单总线操作函数 */
static void Set_Pin_Output(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
static void Set_Pin_Input(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
static uint8_t DS18B20_Reset(void) {
uint8_t response = 0;
Set_Pin_Output(DS18B20_PORT, DS18B20_PIN);
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
HAL_Delay_us(480); // 保持480us低电平
Set_Pin_Input(DS18B20_PORT, DS18B20_PIN);
HAL_Delay_us(70); // 等待15-60us
// 检测存在脉冲(低电平)
if (!HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN)) {
response = 1;
}
HAL_Delay_us(410); // 总复位周期960us
return response;
}
static void DS18B20_WriteByte(uint8_t data) {
for (uint8_t i = 0; i < 8; i++) {
Set_Pin_Output(DS18B20_PORT, DS18B20_PIN);
// 写时隙开始
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
HAL_Delay_us(2); // 保持1us以上
// 写入位值
if (data & 0x01) HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET);
HAL_Delay_us(60); // 保持60us
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_SET); // 释放总线
data >>= 1;
}
}
static uint8_t DS18B20_ReadByte(void) {
uint8_t value = 0;
for (uint8_t i = 0; i < 8; i++) {
Set_Pin_Output(DS18B20_PORT, DS18B20_PIN);
HAL_GPIO_WritePin(DS18B20_PORT, DS18B20_PIN, GPIO_PIN_RESET);
HAL_Delay_us(2); // 至少1us
Set_Pin_Input(DS18B20_PORT, DS18B20_PIN);
HAL_Delay_us(10); // 等待15us后读取
// 读取位值
if (HAL_GPIO_ReadPin(DS18B20_PORT, DS18B20_PIN)) {
value |= (1 << i);
}
HAL_Delay_us(50); // 整个时隙60us
}
return value;
}
```
#### 关键配置说明
1. **时钟配置**:需在`SystemClock_Config()`中启用GPIOA时钟
2. **延时函数**:`HAL_Delay_us()`需实现微秒级延时(可通过SysTick或TIM实现)
3. **串口输出**:需初始化USART并重定向`printf`函数
4. **电源管理**:建议启用STM32G431的睡眠模式降低功耗[^1]
#### 优化建议
1. **多传感器支持**:通过ROM匹配命令实现多点监测
2. **精度调整**:修改配置寄存器可切换9-12位分辨率
3. **抗干扰处理**:添加CRC校验和数据重传机制
4. **低功耗设计**:使用VDD寄生供电模式节省电源线[^2]
[^1]: STM32G4参考手册 RM0440 Rev 7, 第6章电源控制
[^2]: DS18B20数据手册 MAXIM Integrated, 第7节供电方式
阅读全文
相关推荐


















