一、实现的功能
ADC有18个转换通道,其中通道0~通道15是外部通道,使用的GPIO如下图: ADC1的通道16与内部的温度传感器相连(推荐采样17.1us),通道17与参考电源VREFINT 相连,使用ADC_TempSensorVrefintCmd()使能。
- ①通过LED1 ~ LED8显示0 ~ 255的数据,每隔1s增加1;
- ②每隔1s获取一次内部温度AD值和通道8外接电位器的AD值,并将其AD值和电压值打印到串口上面;
- ③把内部温度的AD值转化为温室值;
串口效果图:
二、根据功能实现代码
1、主文件main.c
#include"key.h"
#include"led.h"
#include"lcd.h"
#include "usart.h"
#include "i2c.h"
#include "adc.h"
unsigned int uiAdc_Val;
unsigned char ucSec,ucSec1;
unsigned char pucStr[21];
unsigned long ulTick_ms;
void ADC_Proc(void);
int main(void)
{
SysTick_Config(72000);
KEY_Init();
LED_Init();
STM3210B_LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
USART2_Init(9600);
i2c_init();
ADC1_Init();
sprintf((char *)pucStr," ADC DEMO");
printf("%s\r\n",pucStr);
while(1)
{
LED_Disp(ucSec);
ADC_Proc();
}
}
void ADC_Proc(void)
{
float fAdc_Val;
if(ucSec != ucSec1)
{
ucSec1 = ucSec;
uiAdc_Val = ADC1_Conv();
fAdc_Val = (float)uiAdc_Val*3.3/4095;
sprintf((char *)pucStr," %04u %5.2f",uiAdc_Val,fAdc_Val);
printf("%s",pucStr);
uiAdc_Val = ADC1_InjeConv();
fAdc_Val = (float)25+(5855.85-3.3*uiAdc_Val)/17.6085;
sprintf((char *)pucStr," %04u %5.2f",uiAdc_Val,fAdc_Val);
LCD_DisplayStringLine(Line6,pucStr);
printf("%s\r\n",pucStr);
}
}
void SysTick_Handler(void)
{
ulTick_ms++;
if(ulTick_ms % 1000 ==0)
ucSec++;
}
主函数分析:?? ?? ??
- 通过ucSec1和ucSec变量判断是否相等,判断上一次的状态是否与现在不同,从而实现1s采集一次ADC值;
- ADC值与电压的转化关系(分辨率为12,参考电压为3.3v),采集的电压 = 采集的ADC值 / 4095(212-1) * 3.3;
- %04u 表示用4位数字表示uiAdc_Val,如果不够4位往前面补0,%5.2f 表示用5位数并包含2位小数表示fAdc_Val;
- 通道16所连内部温度的计算,芯片内部温度 = 25 + (5855.85 - 3.3 * ADC值) / 17.6085;
2、ADC头文件“adc.h”
#include"stm32f10x.h"
void ADC1_Init(void);
unsigned int ADC1_Conv(void);
unsigned int ADC1_InjeConv(void);
简要分析:?? ??
- 包含通道8对于的引脚PB0和通道16以及ADC1的初始化;
- 转换通道使用规则通道返回的ADC值;
- 转换通道使用注入通道返回的ADC值;
3、ADC源文件“adc.c”
#include"adc.h"
void ADC1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
ADC_InitTypeDef ADC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
GPIO_InitStruct.GPIO_Pin =GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AIN;
GPIO_Init(GPIOB,&GPIO_InitStruct);
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_ScanConvMode =DISABLE;
ADC_InitStruct.ADC_ContinuousConvMode =DISABLE;
ADC_InitStruct.ADC_ExternalTrigConv =ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 1;
ADC_Init(ADC1,&ADC_InitStruct);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1,
ADC_SampleTime_1Cycles5);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_16, 1,
ADC_SampleTime_239Cycles5);
ADC_TempSensorVrefintCmd(ENABLE);
ADC_AutoInjectedConvCmd(ADC1,ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
unsigned int ADC1_Conv(void)
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
return ADC_GetConversionValue(ADC1);
}
unsigned int ADC1_InjeConv(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_JEOC));
return ADC_GetInjectedConversionValue(ADC1,ADC_InjectedChannel_1);
}
简要分析:?? ??
- 通道8所对应的PB0的GPIO初始化顺序:①初始化GPIO结构体 → ②使能GPIOB对应的APB2时钟 → ③配置引脚、模拟输入模式 → ④初始化GPIO的结构体;
- 配置ADC1的顺序:①初始化ADC结构体 → ②使能ADC1对应的APB2时钟 → ③配置工作模式、(禁止)使能扫描模式、(禁止)使能连续转换模式、不使用外部中断触发、向右对齐、ADC转换通道一个 → ④初始化ADC1的结构体 → ⑤配置通道的采样顺序与周期 → ⑥使能规则和注入通道 → ⑦启动ADC1 → ⑧进行ADC的校准;
- 获取规则通道ADC值unsigned int ADC1_Conv(void),先启动ADC1的软件转换功能,然后检测是否获取到ADC的标志位,最后**ADC_GetConversionValue()**获取规则通道的值;
- 获取注入通道ADC值unsigned int ADC1_InjeConv(void),先启动ADC1的软件转换功能,然后检测是否获取到ADC1的标志位,清除标志位,最后通过**ADC_GetInjectedConversionValue()**返回标志位;
三、实现功能过程的注意与学习点
1、注意点
1、同一个ADC进行多个规则通道采集,会产生串联干扰,可分别设置规则通道和注入通道进行ADC采集,解决多通道采集干扰问题; 2、配置ADC参数可根据实际需求进行配置,可灵活更换一些参数;
2、学习的知识点
- ①规则通道由最多16个通道组成,按顺序转换,使用ADC_RegularChannelConfig()进行配置,使用ADC_GetConversionValue()获取转换值;
- ②注入通道由最多4个通道组成,可插入转换,使用ADC_InjectedChannelConfig()进行配置,使用ADC_GetInjectedConversionValue()获取转换值
- ③ADC通道配置的一个主要参数是采样时间,采样时间通过采用周期数进行配置,两者的关系是 : ` `` 采样时间 = (采样周期数 + 12.5) / fADCCLK (ADC时钟频率)
- ⑤默认状态下,ADCCLK为36MHz,改变规则通道8会引起内部通道16的波动,是因为采样时间有问题,RCC_ADCCLKConfig(RCC_PCLK2_Div6)设置ADCCLK为12MHz温度基本保持稳定。
?? ?? ?? ?? ?? ??
|