欢迎来到SFWR的博客

训练题——ADC读取温度

Author:XuanYu

利用ADC测量单片机内部温度

废话不多说,直接开搞。

科普

先科普一下ADC(不是 AD carry!),ADC是模数转化器,就是模拟信号转换成数字信号的东西,通常的模数转换器是将一个输入电压信号转换为一个输出的数字信号。由于数字信号本身不具有实际意义,仅仅表示一个相对大小。故任何一个模数转换器都需要一个参考模拟量作为转换的标准,而输出的数字量则表示输入信号相对于参考电压的大小。 因此,模拟数字转换器会会将模拟信号转换为表示一定比例电压值的数字信号。
举个简单的例子,对于一般的单片机上的ADC,测量电压的范围也就是输入的模拟信号的范围是0-3.3V,而转化后的数字信号范围取决于ADC的位数,假如是12位的那就是0-2^12也就是0-4096,也就是说要是输入电压是1V的话,那转化的电压就是1/3.3*4096=1240。

ADC的主要作用就是读取输入到单片机的电压等物理量,当然也可以测温度,现在我们就来用单片机自带的温度传感器测温度吧!

配置

先用中断的方式使用ADC读取电压。
首先拿出我们的单片机(我用的是STM32f407ZGT6)然后放到一边
打开cubemx配置如下:
image
image
image

配置ADC这里可能不同的单片机温度传感器的位置不一样,要找到自己单片机的Temperature Sensor Channel并选中,同时勾选一下NVIC Settings里的那个Enabled下面的框,开启adc的全局中断。
image

这里配了一个串口,方便一会输出测量的温度,操作就是选一个串口然后把最上面的mode设置成Asynchronous就可以了。

最后再配置一下时钟树,前面应该有讲我就不赘述了。

然后生成工程,开始写代码。

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
    HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
    return ch;
}

现在最上面加这段代码,然后再按照下图操作
在cubeide主界面,选中工程,然后点击项目->属性->C/C++构建->设置->MCU Settings
image
把下面的两个Use都选上
这样就可以直接调用printf函数通过串口输出了。

使用ADC

然后再写一个adc的中断函数

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	   HAL_ADC_PollForConversion(&hadc1 ,10);  //等待adc采样结束
	   light_value=HAL_ADC_GetValue(hadc);      //读取adc采样的数值并赋值给light_value
	   v=light_value*3.3/4096;
tem=((light_value*3.3/4096-0.76)/0.0025)+25;   //计算温度

	  // printf("light_value=%d\n",light_value );
}

image

这个是我的单片机的温度传感器的一个电气特性,就是说adc采集的电压和实际的温度是一个正比的关系,然后第三行的Avg_Slope是斜率,也就是2.5mV/°C 然后第四行是说25°时读取的电压大约为0.76,所以就可以根据这两个算出当读取的电压值为v0时,实际的温度是(v0-0.76)/0.0025+25。

最后主函数中不断开启ADC中断就可以了。代码如下

while (1)
  {
	  HAL_ADC_Start_IT(&hadc1);
	  printf("get_value=%d,V=%f\r\n",light_value,v);
	  printf("temp=%f\r\n",tem);   //把温度值打印出来
	  HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

然后把程序烧到单片机里,连接串口调试助手结果如下:
image

输出的温度大概是18°左右,因为没有室温计所以没法比较误差,但是对比当时的天气预报显示的是20°(可能科协比较冷一点)也能反映这次测量大概是比较准的。

其他ADC调用方法

也可以用一种简单的查询阻塞的方式
这个配置起来就比较简单,和中断相比就不用勾选ADC的全局中断Enable了,其他的相同。
代码的话直接在主函数里写就行,
image

代码我就扔个图片就好。

最后还有一种方式通过DMA采集
这个博客建议大家看一看,挺实用的。
【STM32技巧】ADC模拟量采集的几种用法_小石头有大内涵的博客-CSDN博客_stm32模拟信号采集

关于DMA的配置也可以参考文章:https://blog.csdn.net/weixin_44584198/article/details/119453399
ADC是单片机里比较基础的也是最常用的东西了,希望大家都能认真学习,有问题先 csdn再找学长问,希望大家都能有所收获。

posted @ 2022-11-13 09:48  SFWR  Views(482)  Comments(0Edit  收藏  举报