1.ADC 模块框图 (STM32F10xxx参考手册 图24 单个ADC框图)
2.ADC 引脚 (STM32F10xxx参考手册 表62 ADC引脚)
3.本例程软件设计思路
1)使用软件触发 ADC (连续)转换,通过 (规则) 通道1检测加于此通道引脚的电压值
2)开启转换完成中断,在中断中读取转换后的电压 AD 值
3)通过计算,将 AD 值转换成真实电压值输出
注意:此处测量的电压范围仅适用于 0 - 3.3V,不得高于 3.3V
4.代码编写
于 main.c 中编写代码
#include "stm32f10x.h"
#include "dr_usart.h"
uint16_t ADC_CurrentValue = 0;
float ADC_RealValue = 0.0;
static void delay_(uint32_t count);
static void ADC_NVIC_Config(void)
{
NVIC->IP[18] = ((uint8_t)6 << 4);
NVIC->ISER[0]|=((uint32_t)0x01 << 18);
}
void ADC1_GPIO_Config(void)
{
RCC->APB2ENR |= ((uint16_t)0x01 << 2);
GPIOA->CRL &= ~((uint32_t)0x0f << 4);
GPIOA->CRL |= ((uint32_t)0x00 << 4);
}
void ADC1_Config(void)
{
ADC1_GPIO_Config();
RCC->APB2ENR |= ((uint16_t)0x01 << 9);
ADC1->CR1 &= ~((uint32_t)0x0f << 16);
ADC1->CR1 &= ~((uint32_t)0x01 << 8);
ADC1->CR2 &= ~((uint32_t)0x01 << 20);
ADC1->CR2 &= ~((uint32_t)0x01 << 11);
ADC1->CR2 |= ((uint32_t)0x01 << 1);
ADC1->SQR1 &= ~((uint32_t)0x0f << 20);
RCC->CFGR |= ((uint32_t)0x03 << 14);
ADC1->SMPR2 |= ((uint32_t)0x07 << 3);
ADC1->SQR3 |= ((uint32_t)0x01 << 0);
ADC1->CR1 |= ((uint32_t)0x01 << 5);
ADC1->CR2 |= ((uint32_t)0x01 << 0);
ADC1->CR2 |= ((uint32_t)0x01 << 3);
while(0 != (ADC1->CR2 & ((uint32_t)0x01 << 3)));
ADC1->CR2 |= ((uint32_t)0x01 << 2);
while(0 != (ADC1->CR2 & ((uint32_t)0x01 << 2)));
ADC1->CR2 |= ((uint32_t)0x01 << 0);
}
int main(void)
{
User_Init();
ADC1_Config();
ADC_NVIC_Config();
while(1)
{
ADC_RealValue = (float)ADC_CurrentValue/4096*3.3 + 0.005;
printf("ADC_CurrentValue = %d.rn", ADC_CurrentValue);
printf("ADC_RealValue = %.2f V.rn", ADC_RealValue);
delay_(100);
}
}
void ADC1_2_IRQHandler(void)
{
if(2 == (ADC1->SR & ((uint32_t)0x01 << 1)))
{
ADC_CurrentValue = (uint16_t)ADC1->DR;
}
}
static void delay_(uint32_t count)
{
__IO uint32_t delay_count = (12000 * count);
while(delay_count--);
}
点击编译,如无错误可进入仿真界面
查看 ADC DR 寄存器,此寄存器存储了规则通道转换后的 AD 值
可以看出,目前此处值为0
点击运行,此处仍为0 (检测电压的 IO 口此时并未连接要测量的电压)
打开串口,此时串口输出为0
将 1V 电压加于此通道,观察 ADC DR 寄存器值 and 串口输出值,此时已测出电压值
将电压加到 2V,可以看出 ADC DR 寄存器值 and 串口输出值已经改变
停止并退出仿真界面,修改程序为使用外部事件触发转换 (EXTI 中断线11触发)
于 main.c 中编写代码 (单次转换模式)
uint16_t ADC_CurrentValue = 0;
float ADC_RealValue = 0.0;
static void delay_(uint32_t count);
static void ADC_NVIC_Config(void)
{
NVIC->IP[18] = ((uint8_t)6 << 4);
NVIC->ISER[0]|=((uint32_t)0x01 << 18);
}
void ADC1_GPIO_Config(void)
{
RCC->APB2ENR |= ((uint16_t)0x01 << 2);
GPIOA->CRL &= ~((uint32_t)0x0f << 4);
GPIOA->CRL |= ((uint32_t)0x00 << 4);
}
static void ADC_EXTI_Config(void)
{
RCC->APB2ENR |= ((uint16_t)0x01 << 2);
GPIOA->CRH &= ~((uint32_t)0x0f << 12);
GPIOA->CRH |= ((uint32_t)0x04 << 12);
RCC->APB2ENR |= ((uint16_t)0x01 << 0);
AFIO->EXTICR[3] &= ~((uint32_t)0x0f << 12);
AFIO->MAPR &= ~((uint32_t)0x01 << 18);
EXTI->EMR |= ((uint32_t)0x01 << 11);
EXTI->FTSR |= ((uint32_t)0x01 << 11);
}
void ADC1_Config(void)
{
ADC1_GPIO_Config();
RCC->APB2ENR |= ((uint16_t)0x01 << 9);
ADC1->CR1 &= ~((uint32_t)0x0f << 16);
ADC1->CR1 &= ~((uint32_t)0x01 << 8);
ADC1->CR2 |= ((uint32_t)0x0e << 17);
ADC1->CR2 &= ~((uint32_t)0x01 << 11);
ADC1->CR2 &= ~((uint32_t)0x01 << 1);
ADC1->SQR1 &= ~((uint32_t)0x0f << 20);
RCC->CFGR |= ((uint32_t)0x03 << 14);
ADC1->SMPR2 |= ((uint32_t)0x07 << 3);
ADC1->SQR3 |= ((uint32_t)0x01 << 0);
ADC1->CR1 |= ((uint32_t)0x01 << 5);
ADC1->CR2 |= ((uint32_t)0x01 << 0);
ADC1->CR2 |= ((uint32_t)0x01 << 3);
while(0 != (ADC1->CR2 & ((uint32_t)0x01 << 3)));
ADC1->CR2 |= ((uint32_t)0x01 << 2);
while(0 != (ADC1->CR2 & ((uint32_t)0x01 << 2)));
}
int main(void)
{
User_Init();
ADC1_Config();
ADC_EXTI_Config();
ADC_NVIC_Config();
while(1)
{
ADC_RealValue = (float)ADC_CurrentValue/4096*3.3 + 0.005;
printf("ADC_CurrentValue = %d.rn", ADC_CurrentValue);
printf("ADC_RealValue = %.2f V.rn", ADC_RealValue);
delay_(100);
}
}
void ADC1_2_IRQHandler(void)
{
if(2 == (ADC1->SR & ((uint32_t)0x01 << 1)))
{
ADC_CurrentValue = (uint16_t)ADC1->DR;
}
}
static void delay_(uint32_t count)
{
__IO uint32_t delay_count = (12000 * count);
while(delay_count--);
}
点击编译,如无错误再进入仿真界面,点击运行 (外加 3V 电压)
此时并未触发转换,所以未能读出 AD 值,显示为0
通过 EXTI 中断线11触发 (可以是外接的按键按下一次) 一次转换,此时再查看输出值
可以看出输出值已经改变,此时将外加电压调至 3.3 V,但并不会改变输出值,因为此处设定的为单次转换模式,即触发一次只转换一次
先查看电压是否已调至 3.3V
可以看出,引脚上电压值已变为 3.3V,但输出值仍为 3V
此时再触发一次转换,输出值已经改变
5.本篇总结
共设计了两个例程:1) 软件触发 ADC 转换 2) EXTI 外部事件触发 ADC 转换
经验证,程序运行结果均与预想一致



