STM32之ADC通道采集片内温度并通过串口传输
软件实验要求
系统主频 16 MHZ,采用内部晶振,通过 DMA 采样三个数,一个是 PA4 引脚上的电压电平,一个是内部温度传感器数值,还有个是 VREF 电压。然后通过芯片 PB6,PB7 的 USART1 口,实现串口通信传输数据。
使用STM32CubeMX创建项目
使用STM32CubeMX新建并配置好 PA4 为 ADC 口,内部温度采集,以及内部参考电压采集,再配置 DMA 以及中断。
- 新建好 STM32G030C8T6 的 STM32CubeMX 工程之后,在如图 2.1 在Pinout&Configuration 栏目的 System Core 下,先点击 SYS,再勾选 Serial Wire 框,配置好 SWD 下载引脚设置,系统默认采用内部 16MHZ 晶振,默认系统主频是 16MHZ,所以不需要配晶振与 PLL。

图2.1
- 如图 2.2 的 1,2,3 步骤完成 PA4 引脚作为 ADC 通道 4 引脚,内部参考电压采集以及温度采集。

图2.2
- 如图 2.4,如图 2.5 完成 DMA 配置。

图2.4

图2.5
- 如图 2.3 的 1,2,3,4,5 步骤完成 ADC 采集参数配置。

图2.3
- 如图2.6,图2.7配置 PB6,PB7 为 USART1 收发引脚以及相应的中断使能。

图2.6

图2.7
- 如图2.8,图2.9 配置项目

图2.8

图2.9
完成配置之后,生成工程代码。
使用 Keil uVision 5编辑
在main.h中添加
//...
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
#define DIGITAL_SCALE_12BITS ((uint32_t) 0xFFF)
/* Init variable out of ADC expected conversion data range */
#define VAR_CONVERTED_DATA_INIT_VALUE (DIGITAL_SCALE_12BITS + 1)
/* Definition of ADCx conversions data table size */
#define ADC_CONVERTED_DATA_BUFFER_SIZE ((uint32_t) 3)
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
//...
在usart.h中添加
//...
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
void UART_Print(char *msg);
/* USER CODE END Includes */
extern UART_HandleTypeDef huart1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
// ...
在usart.c中定义
//...
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
#include "string.h"
/* USER CODE BEGIN 0 */
void UART_Print(char *msg) {
HAL_UART_Transmit(&huart1, (uint8_t *)msg, strlen(msg), HAL_MAX_DELAY);
}
/* USER CODE END 0 */
UART_HandleTypeDef huart1;
//...
在main.c中修改,首先添加头文件#include "stdio.h",然后
//...
//存放3组数据,分别是ADC1_Ch4,温度,参考电压
__IO uint16_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE];
//定义变量,在ADC采样结束,DMA传送完成置位,方便主程序取数据
__IO uint8_t ubDmaTransferStatus = 2;
//温度值,单位度
uint32_t Tempruate;
//参考电压值,ADC1_Ch4采样电压值,单位V
uint16_t VrefData, VolDta;
//ADC数据采样结束回调函数,用于置位采样结束标志位
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(hadc);
//置1
ubDmaTransferStatus=1;
}
//...
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t tmp_index_adc_converted_data = 0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
for (tmp_index_adc_converted_data = 0; tmp_index_adc_converted_data < ADC_CONVERTED_DATA_BUFFER_SIZE; tmp_index_adc_converted_data++)
{
//采样数组清零
aADCxConvertedData[tmp_index_adc_converted_data] = VAR_CONVERTED_DATA_INIT_VALUE;
}
//ADC自校准
if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)
{
/* Calibration Error */
while(1);
}
//启动ADC DMA传输
if (HAL_ADC_Start_DMA(&hadc1,
(uint32_t *)aADCxConvertedData,
ADC_CONVERTED_DATA_BUFFER_SIZE
) != HAL_OK)
{
/* ADC conversion start error */
while(1);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
/* Clear DMA buffer when filled before refilling it */
if (ubDmaTransferStatus == 1)//判断数据是否已经转换完成
{
VolDta=aADCxConvertedData[0]*3300/4096;//计算通道ADC1_Ch4采样到的电压值
VrefData=__LL_ADC_CALC_VREFANALOG_VOLTAGE(aADCxConvertedData[2],ADC_RESOLUTION_12B);//计算参考电压
Tempruate=__HAL_ADC_CALC_TEMPERATURE(VrefData,aADCxConvertedData[1],ADC_RESOLUTION_12B);//计算温度值
char message[100];
sprintf(message, "Voltage: %d mV, Temp: %lu C, Vref: %d mV\n", VolDta, Tempruate, VrefData);
UART_Print(message);
HAL_Delay(5000);
for (tmp_index_adc_converted_data = 0; tmp_index_adc_converted_data < ADC_CONVERTED_DATA_BUFFER_SIZE; tmp_index_adc_converted_data++)
{
aADCxConvertedData[tmp_index_adc_converted_data] = VAR_CONVERTED_DATA_INIT_VALUE;//采样数组清0
}
/* Update status variable of DMA transfer */
ubDmaTransferStatus = 0;//完成标志清0
}
}
/* USER CODE END 3 */
}
点击编译,导入程序

使用TTL转USB接上开发板,打开串口程序

为什么会出现923,922等数据,我暂时还没搞懂,之后再更新。
2025年3月28日更新:
之前有遇到会出现923,922这样的数据,大概是因为
char message[100];
sprintf(message, "Voltage: %d mV, Temp: %lu C, Vref: %d mV\n", VolDta, Tempruate, VrefData);
UART_Print(message);
这样的方法,造成了溢出,可以根据 https://www.syuez.com/blog/STM32%E4%B8%B2%E5%8F%A3%E9%80%9A%E4%BF%A1%E5%AE%9E%E9%AA%8C.html 文章中的printf()重定向来解决。
将发送方法改成
printf("Voltage: %d mV, Temp: %d C, Vref: %d mV\n", VolDta, Tempruate, VrefData);
文字部分代码由GPT-4o生成