温度采集是产品开发过程中至关重要。读取温度的方法有很多,包括特殊的温度采集芯片、温度传感器、热敏电阻等,以获得温度。今天,我将总结使用热敏电阻来收集温度。
先看看热敏电阻的概念
也就是说,将温度变化转化为电阻值变化,可以通过电阻值的大小间接判断当前的温度值。读取电阻值在实际应用中非常不方便。如果将电阻值转换为电压值,则通过单片机AD采样功能,读取电压值。这相当于间接读取温度值。
下面总结一下使用情况STM8单片机,通过NTC读取热敏电阻温度值得的方法。
首先看热敏电阻的样子
选用的是5K阻值的NTC其电阻和温度对照表如下:
通过固定电阻和NTC热敏电阻串联分压,然后将两个电阻的中间节点连接到单片机AD采样口。
ADC口接单片机AD采样口,通过AD采样功能,读取采样电压值,然后对应电压值、电阻值和温度值,通过电压值的变化反映温度的变化。
原理图中的ADC口接单片机PD6口,即模拟输入6口,PD5口作为串口输出口,输出读取的采样值。硬件上的电路相对简单,只需要一个最小的系统,然后是外部的5个K固定电阻和NTC热敏电阻就行了。下面看一下代码的实现:
首先将PD6口设置为ADC通过中断读取功能ADC采样值。
#include "adc.h" #include "main.h" u16 DATAH = 0; //ADC转换值高8位 u16 DATAL = 0; //ADC转换值低8位 _Bool ADC_flag = 0; //ADC转换成功标志 //AD通道引脚的初始化 void ADC_GPIO_Init( void ) { PD_DDR &= ~( 1 << 6 ); //PD6 设置为输入 AIN6 PD_CR1 &= ~( 1 << 6 ); //PD6 设置为悬空输入 } //ADC输入通道初始化入口参数表示通道选择 void ADC_CH_Init( u8 ch ) { char l = 0; ADC_CR1 = 0x00; //fADC = fMASTER/2, 8Mhz 单次转换,禁止转换 ADC_CSR = ch 1; //控制状态寄存器 选择要 AD输入通道 如:PD2(AIN3) ADC_CR2 = 0x00; ///默认左对齐 读数据时,先读高,读低 ADC_TDRL = ( 1 << ( ch 1 ) ); //禁止相应通道 施密特触发功能 1左移ch 1位 ADC_CR1 |= 0x01; //使能ADC并开始转换 ADC_CSR |= 0x20; //EOCIE 中断转换结束 EOC中断使能 for( l = 0; l < 100; l ); //延时,保证ADC模块上电完成 至少7us ADC_CR1 = ADC_CR1 | 0x01; //再次将CR寄存器最低位置11 使能ADC 并开始转换 } //采集PD6电压值 AIN6 u16 ReadVol_CH6( void ) { u16 voltage = 0; ADC_CH_Init( 5 ); if( ADC_flag ) { ADC_flag = 0; voltage = ( DATAH << 2 ) DATAL ; ///获取十位精度数据 0--1024 //ADC_CR1 = ADC_CR1 | 0x01; //再次将CR寄存器最低位置11 启动下一个转换 }; return voltage; } //AD中断服务函数 中断号22 #pragma vector = 24 // IAR中断号,要在STVD中断号加2 __interrupt void ADC_Handle( void ) { ADC_CSR &= ~0x80; // 标志位在转换结束时清零 EOC ///默认左对齐 读数据时,先读高8位 再读低8位 DATAH = ADC_DRH; // 读出ADC结果的高8位 DATAL = ADC_DRL; // 读出ADC结果的低8位 ADC_flag = 1; // ADC中断标志 置1 }
接下来将PD五口设置为串口发送功能:
#include "uart.h" #include "main.h" //在Library Options中将Printf formatter改成Large ///重新定向putchar支持函数printf函数 int putchar( int ch ) { while( !( UART1_SR & 0X80 ) ); ///循环发送,直到发送完成 UART1_DR = ( u8 ) ch; return ch; } //串口只用发送口,不用接收口 void Uart1_IO_Init( void ) { PD_DDR |= ( 1 << 5 ); ///输出模式 TXD PD_CR1 |= ( 1 << 5 ); //推挽输出 } //最大波特率为38400 void Uart1_Init( unsigned int baudrate ) { unsigned int baud; baud = 16000000 / baudrate; Uart1_IO_Init(); UART1_CR1 = 0; //禁止发送和接收
UART1_CR2 = 0; //8 bit
UART1_CR3 = 0; //1 stop
UART1_BRR2 = ( unsigned char )( ( baud & 0xf000 ) >> 8 ) | ( ( unsigned char )( baud & 0x000f ) );
UART1_BRR1 = ( ( unsigned char )( ( baud & 0x0ff0 ) >> 4 ) );
// UART1_CR2_bit.REN = 1; //接收使能
UART1_CR2_bit.TEN = 1; //发送使能
// UART1_CR2_bit.RIEN = 1; //接收中断使能
}
串口只用到了发送功能,所以串口只需要初始化发送口和设置波特率就行。此处putchar(),函数是用于将printf()打印功能重映射到串口1。
下面看主函数代码
void main( void )
{
__asm( "sim" ); //禁止中断
SysClkInit();
delay_init( 16 );
Uart1_IO_Init();
Uart1_Init( 9600 );
ADC_GPIO_Init();
__asm( "rim" ); //开启中断
while( 1 )
{
val_ch6 = ReadVol_CH6();
printf( "%d\r\n", val_ch6);
delay_ms( 200 );
}
}
主函数中每隔0.2s读取一次电压值,并通过串口发送出来。
下面通过串口波形显示软件看看采样的温度曲线。
通过曲线可以看到,温度刚开始时发生了波动,然后就趋于稳定,稳定后的采样值为500。STM8单片机的AD采样分辨率为10位,也就是采样最大值为2^10=1024,单片机为5V供电,也就是5V对应的采样值为1024,那么采样值500对应的电压值就为 500/1024*5=2.44V
可以计算出NTC当前电阻值为4.77K,通过NTC阻值和温度对照表可以看出4.77K对应的温度值在26℃左右。说明当前测量的温度值为26℃。为了方便显示温度,可以将采样的电压值和温度值做成一个表格存储在单片机中,这样每次采样到数据后,通过查表就能得到温度值了。