第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 以读取温度值。
  • 实际测量和输出温度值。

实验材料

  1. 开发板:STM32F4 或 STM32F103(任何支持内部温度传感器的 STM32 系列)。
  2. 编程工具:STM32CubeIDE 或 Keil uVision。
  3. 串口调试工具:如 PuTTY 或 Serial Monitor。
  4. 连接线: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) {
    // 系统时钟配置代码,设置主时钟源、分频器等
}

posted @ 2024-10-14 09:31  hazy1k  阅读(3)  评论(0编辑  收藏  举报