1.ADC函数模块 ADC.c
#include "stm32f10x.h"
#define GPIOx GPIOB
#define GPIO_Pin_x GPIO_Pin_0
#define RCC_APB2Periph_GPIOx RCC_APB2Periph_GPIOB
#define ADC_Channel_x ADC_Channel_8 //PB0
void AD_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //六分频 72M/6
GPIO_InitTypeDef GPIO_InitStructure; //建立外设结构体
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //GPIO无效模式(AD专用)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOx,&GPIO_InitStructure);
//配置规则组(选择通道) //如果想增加通道,就在原来基础上复制下面函数,更改通道数
//:将通道2(PA2口)放到规则组第一个序列
//:因为是非扫描模式,所以序列值一定为 1(第一个序列)
ADC_RegularChannelConfig(ADC1, ADC_Channel_x, 1 , ADC_SampleTime_55Cycles5);//放在第一个通道
ADC_InitTypeDef ADC_InitStruct;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//12位数据在16位寄存器中左对齐,可直接取出后显示
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部触发
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//单独模式(不配合其他ADC使用双模式)
ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//连续或单次扫描模式(单次)
ADC_InitStruct.ADC_NbrOfChannel = 1;///在扫描模式下会用到的通道数(在单次模式下只有序列1有效[ADC_Channel_0].
ADC_InitStruct.ADC_ScanConvMode = DISABLE;//扫描或非扫描模式(非扫描)
ADC_Init(ADC1, &ADC_InitStruct);
ADC_Cmd(ADC1, ENABLE);
//校准ADC(四条函数)
ADC_ResetCalibration(ADC1);//复位校准
while (ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准完成//<RSTCAL>==SET:未校准完成(在ADC_ResetCalibration(ADC1),将该位置1)
ADC_StartCalibration(ADC1);//开始校准
while (ADC_GetCalibrationStatus(ADC1)); //等待开始校准完成
}
uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//EOC:规则组或注入组装换完成标志位,由软件清除(置0),或者读取<ADC_DR>位会自动清除
//上条函数会等待约5.6us
return ADC_GetConversionValue(ADC1);//获取ADC值,会自动清除EOC
}
2.过程:打开外设ADC、GPIO的时钟,通过RCC配置ADC的分频,RCC最大频率不超过14Mhz,所以一般六分频。初始化GPIO,将GPIO设置为模拟输入输入。然后由于ADC的四种扫描模式:连续扫描、连续不扫描、不连续扫描、不连续不扫描。因此选最后一种,然后由软件调用函数申请获得数值。接着配置规则组函数,规则组序列号有1-16,不连续不扫描模式只能选择序列一,然后通道号就是对应的GPIO口,映射关系就会PA0-PB1 依次递增。配置ADC初始化函数,设置右对齐可直接获得数值,左对齐容易计算出精度较低的粗略值。使能ADC后,要对ADC进行重新校准。引用四个函数,分别是两个执行,两个判断。做一个获取ADC转换值的函数,首先调用软件申请转换函数,EOC位置自动置0,当转换完成会自动置1。然后使用获取数值函数,使用后,EOC位会自动复位置0.如果需要软件触发多个通道,可以在获取函数中开头加ADC_RegularChannelConfig();
3.主函数 main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Button.h"
#include "OLED.h"
#include "ADC1.h"
int main(void)
{
float valus;
uint16_t AD_Val;
uint8_t vals;
AD_Init();
LED3_Init();
OLED_Init();
OLED_ShowString(2, 1, "Savage_AD_Val:");
OLED_ShowString(3, 13, ". V");
while(1)
{
AD_Val = AD_GetValue();
valus = ((AD_Val/4096.0) * 3.3);
vals = ((uint16_t)valus%10);
OLED_ShowNum(3, 12, ((uint16_t)valus%10), 1);
OLED_ShowNum(3, 14, ((uint16_t)(valus*100)%100), 2);
OLED_ShowNum(3, 1, AD_Val, 4);
OLED_ShowBinNum(4, 1, AD_Val, 16);
Delay_ms(150);
}
}
4.效果演示
//Savage学习笔记,加油!博客又出现问题希望各位好朋友指正!