STM32F103是一款非常流行的32位微控制器,基于Cortex-M3内核,具备较强的处理能力和丰富的外设资源,广泛应用于工业控制、消费电子等领域。在嵌入式系统中,ADC(模拟数字转换器)功能非常重要,它可以将模拟信号(如温度、电压)转换为数字信号,供MCU进行处理。本篇文章将介绍如何在STM32F103中使用ADC,并通过示例代码展示如何采集模拟信号。
1. STM32F103硬件概述STM32F103拥有多达16通道的12位ADC,可以同时采集多个模拟信号。其ADC模块具备以下特点:
- 12位分辨率,高精度采集模拟信号
- 多通道支持,可以采集多个信号源
- DMA支持,可以通过DMA方式自动采集数据,减少CPU负担
- 转换速度快,适用于实时采集需求
2. 硬件准备- STM32F103开发板
- 一个可调电位器(作为输入模拟信号)
- 若干杜邦线
3. 开发环境- IDE: Keil MDK5
- 库文件: STM32F1 HAL库
4. ADC配置步骤在STM32F103中使用ADC主要分为以下几个步骤:
- GPIO配置:将模拟输入信号引脚配置为模拟模式
- ADC初始化:设置ADC的分辨率、时钟、触发方式等参数
- 采集数据:通过启动ADC并读取转换结果获取模拟信号的数字值
- 处理数据:将采集到的数字信号进行处理或显示
5. 示例代码:使用STM32F103采集模拟信号下面的代码展示了如何使用STM32F103的ADC功能,读取一个电位器的电压值并通过串口发送到PC端。
#include "stm32f10x.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
// ADC初始化
void ADC_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE); // 开启ADC1和GPIOA时钟
// 配置PA0为模拟输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 设置为模拟输入模式
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; // 采集通道数
ADC_Init(ADC1, &ADC_InitStructure);
// 配置ADC通道
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // 采集通道0(PA0)
// 启用ADC
ADC_Cmd(ADC1, ENABLE);
// 校准ADC
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
// 启动ADC转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
// 串口初始化
void USART_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置PA9为USART1_TX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置PA10为USART1_RX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置USART1
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
// 启用USART1
USART_Cmd(USART1, ENABLE);
}
// 串口发送字符
void USART_SendChar(char c) {
USART_SendData(USART1, c);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
// 串口发送字符串
void USART_SendString(char* str) {
while (*str) {
USART_SendChar(*str++);
}
}
int main(void) {
uint16_t adc_value;
ADC_Configuration(); // 初始化ADC
USART_Configuration(); // 初始化串口
while (1) {
adc_value = ADC_GetConversionValue(ADC1); // 读取ADC值
char buffer[10];
sprintf(buffer, "%d\n", adc_value); // 将ADC值转为字符串
USART_SendString(buffer); // 通过串口发送ADC值
for (int i = 0; i < 1000000; i++); // 延时
}
}
6. 代码解析- ADC_Configuration函数:初始化ADC模块,包括使能时钟、配置引脚和设置ADC工作模式等。ADC1被配置为单通道模式,并通过软件触发方式进行采样。
- USART_Configuration函数:配置USART1用于串口通信。通过PA9和PA10作为串口的TX和RX引脚,串口波特率设置为9600。
- main函数:主循环中不断读取ADC的转换值,并通过串口将结果发送到PC。通过电位器调节输入电压,ADC值会随之变化。
7. 实际应用在实际应用中,ADC可以用于采集多种模拟信号,如电压、电流、温度等。STM32F103的ADC模块性能强大,采样速度快,适用于需要精确采集信号的场景。通过本文的代码示例,开发者可以快速掌握STM32F103 ADC的使用方法,并将其应用于各种传感器或电压采集场景。
8. 常见问题- ADC采样精度不高:可能是因为参考电压不稳定或信号有干扰,可以考虑使用滤波器或稳定的外部参考电压。
- 串口数据乱码:检查串口的波特率设置是否正确,确保PC端的波特率与STM32F103一致。
- ADC转换速度慢:可以适当调整ADC的采样时间,或通过DMA方式提升数据传输效率。
9. 结论STM32F103的ADC模块功能强大,能够方便地采集模拟信号并将其转换为数字信号,供MCU处理。通过本文的示例代码,大家可以快速上手使用STM32的ADC功能,应用于各种模拟信号的采集场景。
|