第19章 内部温度传感器实验
第十九章 内部温度传感器实验
1. 硬件设计
本实验用到的硬件资源有:
-
指示灯DS0
-
TFTLCD模块
-
ADC
-
内部温度传感器
前三个之前均有介绍,而内部温度传感器也是在 STM32F4 内部,不需要外部设置,我们只需要软件设置就 OK 了。
2. 软件设计
2.1 ADC初始化
ADC_HandleTypeDef ADC1_Handler; // ADC句柄
// 初始化ADC
// ch: ADC_channels
// 通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
void MY_ADC_Init(void)
{
ADC1_Handler.Instance = ADC1;
ADC1_Handler.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 4分频,ADCCLK=PCLK2/4=90/4=22.5MHZ
ADC1_Handler.Init.Resolution = ADC_RESOLUTION_12B; // 12位模式
ADC1_Handler.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 右对齐
ADC1_Handler.Init.ScanConvMode = DISABLE; // 非扫描模式
ADC1_Handler.Init.EOCSelection = DISABLE; // 关闭EOC中断
ADC1_Handler.Init.ContinuousConvMode = DISABLE; // 关闭连续转换
ADC1_Handler.Init.NbrOfConversion = 1; // 1个转换在规则序列中 也就是只转换规则序列1
ADC1_Handler.Init.DiscontinuousConvMode = DISABLE; // 禁止不连续采样模式
ADC1_Handler.Init.NbrOfDiscConversion = 0; // 不连续采样通道数为0
ADC1_Handler.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
ADC1_Handler.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;// 使用软件触发
ADC1_Handler.Init.DMAContinuousRequests = DISABLE; // 关闭DMA请求
HAL_ADC_Init(&ADC1_Handler); // 初始化
}
2.2 ADC GPIO配置
// ADC底层驱动,引脚配置,时钟使能
// 此函数会被HAL_ADC_Init()调用
// hadc:ADC句柄
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_ADC1_CLK_ENABLE(); // 使能ADC1时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 开启GPIOA时钟
GPIO_Initure.Pin=GPIO_PIN_5; // PA5
GPIO_Initure.Mode=GPIO_MODE_ANALOG; // 模拟输入
GPIO_Initure.Pull=GPIO_NOPULL; // 不带上下拉
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}
2.3 采集一次ADC
// 获得ADC值
// ch: 通道值 0~16,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
// 返回值:转换结果
u16 Get_Adc(u32 ch)
{
ADC_ChannelConfTypeDef ADC1_ChanConf;
ADC1_ChanConf.Channel = ch; // 通道
ADC1_ChanConf.Rank = 1; // 1个序列
ADC1_ChanConf.SamplingTime = ADC_SAMPLETIME_480CYCLES;// 采样时间
ADC1_ChanConf.Offset = 0; // 偏移量
HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf); // 通道配置
HAL_ADC_Start(&ADC1_Handler); // 开启ADC
HAL_ADC_PollForConversion(&ADC1_Handler,10); // 轮询转换
return (u16)HAL_ADC_GetValue(&ADC1_Handler); // 返回最近一次ADC1规则组的转换结果
}
2.4 多次获取求平均值
// 获取指定通道的转换值,取times次,然后平均
// times:获取次数
// 返回值:通道ch的times次转换结果平均值
u16 Get_Adc_Average(u32 ch,u8 times)
{
u32 temp_val = 0;
u8 t;
for(t = 0; t < times; t++)
{
temp_val += Get_Adc(ch);
delay_ms(5);
}
return temp_val/times;
}
2.5 计算温度值
// 得到温度值
// 返回值:温度值(扩大了100倍,单位:℃.)
short Get_Temprate(void)
{
u32 adcx;
short result;
double temperate;
adcx = Get_Adc_Average(ADC_CHANNEL_TEMPSENSOR, 10); // 读取内部温度传感器通道,10次取平均
temperate=(float)adcx*(3.3/4096); // 电压值
temperate=(temperate-0.76)/0.0025 + 25; // 转换为温度值
result=temperate*=100; // 扩大100倍.
return result;
}
2.6 主函数
int main(void)
{
short temp;
HAL_Init(); // 初始化HAL库
Stm32_Clock_Init(336,8,2,7); // 设置时钟,168Mhz
delay_init(168); // 初始化延时函数
uart_init(115200); // 初始化USART
usmart_dev.init(84); // 初始化USMART
LED_Init(); // 初始化LED
KEY_Init(); // 初始化KEY
LCD_Init(); // 初始化LCD
MY_ADC_Init(); // 初始化ADC1
POINT_COLOR = RED; // 设置字体为红色
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"Temperature TEST");
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(30,140,200,16,16,"TEM PERATE: 00.00C");//先在固定位置显示小数点
while(1)
{
temp = Get_Temprate(); // 得到温度值
if(temp < 0)
{
temp =- temp; // 显示负数
LCD_ShowString(30+10*8,140,16,16,16,"-"); // 显示负号
}else LCD_ShowString(30+10*8,140,16,16,16," "); // 无符号
LCD_ShowxNum(30+11*8,140,temp/100,2,16,0); //显示整数部分
LCD_ShowxNum(30+14*8,140,temp%100,2,16,0); //显示小数部分
LED0 = !LED0;
delay_ms(250);
}
}
这里同上一章的主函数也大同小异, 这里,我们通过 Get_Temprate 函数读取温度值,并通过 TFTLCD 模块显示出来。
3. 小结
本章与上一章基本无异,特别之处就是换了一个通道用来测量芯片的温度,下面我们回顾一下:
实验目的
- 理解 STM32 内部温度传感器的工作原理。
- 学习如何配置 ADC 以读取温度值。
- 实际测量和输出温度值。
实验材料
- 开发板:STM32F4 或 STM32F103(任何支持内部温度传感器的 STM32 系列)。
- 编程工具:STM32CubeIDE 或 Keil uVision。
- 串口调试工具:如 PuTTY 或 Serial Monitor。
- 连接线:USB 线(用于连接开发板到电脑)。
编写代码
#include "main.h" // 包含 STM32 库的主头文件
// ADC 句柄和 UART 句柄的声明
ADC_HandleTypeDef hadc1;
UART_HandleTypeDef huart1;
// 函数原型声明
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_USART1_UART_Init(void);
int main(void) {
// 初始化 HAL 库
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化 GPIO、ADC 和 USART
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
while (1) {
// 启动 ADC 转换
HAL_ADC_Start(&hadc1);
// 等待 ADC 转换完成
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
// 读取 ADC 转换值
uint32_t adcValue = HAL_ADC_GetValue(&hadc1);
// 计算温度值
// 假设 Vref = 3.3V, 分辨率为 12 位
float voltage = (3.3f * adcValue) / 4095.0f; // 将 ADC 值转换为电压
// 温度计算公式
// 0.76 是温度传感器的偏置,0.0025 是温度系数(°C/V)
float temperature = (voltage - 0.76f) / 0.0025f + 25;
// 将温度值格式化为字符串,准备发送
char buffer[50]; // 缓冲区用于存储输出字符串
snprintf(buffer, sizeof(buffer), "Temperature: %.2f C\r\n", temperature);
// 通过串口发送温度值
HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
// 延时1秒
HAL_Delay(1000); // 等待 1 秒以便下次读取
}
}
// ADC 初始化函数
static void MX_ADC1_Init(void) {
// 配置 ADC 通道
ADC_ChannelConfTypeDef sConfig = {0}; // 创建一个 ADC 通道配置结构体
__HAL_RCC_ADC1_CLK_ENABLE(); // 启用 ADC1 的时钟
// 配置 ADC 的基本参数
hadc1.Instance = ADC1; // 选择 ADC1 实例
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // ADC 时钟预分频
hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 12 位分辨率
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 禁用扫描模式
hadc1.Init.ContinuousConvMode = ENABLE; // 启用连续转换模式
hadc1.Init.DiscontinuousConvMode = DISABLE; // 禁用不连续模式
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发转换
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据对齐方式
hadc1.Init.NbrOfConversion = 1; // 只进行一次转换
HAL_ADC_Init(&hadc1); // 初始化 ADC1
// 配置温度传感器通道
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; // 设置通道为温度传感器
sConfig.Rank = ADC_REGULAR_RANK_1; // 设置为常规通道的第一个
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; // 采样时间设置为 3 个时钟周期
HAL_ADC_ConfigChannel(&hadc1, &sConfig); // 配置 ADC 通道
}
// USART 和 GPIO 的初始化代码省略
static void MX_USART1_UART_Init(void) {
// 配置 UART 参数
huart1.Instance = USART1; // 选择 USART1 实例
huart1.Init.BaudRate = 9600; // 设置波特率为 9600
huart1.Init.WordLength = UART_WORDLENGTH_8B; // 8 位数据长度
huart1.Init.StopBits = UART_STOPBITS_1; // 1 个停止位
huart1.Init.Parity = UART_PARITY_NONE; // 无奇偶校验
huart1.Init.Mode = UART_MODE_TX_RX; // 同时支持发送和接收
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; // 禁用硬件流控制
huart1.Init.OverSampling = UART_OVERSAMPLING_16; // 16 倍过采样
HAL_UART_Init(&huart1); // 初始化 USART1
}
// GPIO 初始化函数
static void MX_GPIO_Init(void) {
// GPIO 初始化代码根据具体需求进行配置
}
// 系统时钟配置函数
void SystemClock_Config(void) {
// 系统时钟配置代码,设置主时钟源、分频器等
}