STM32中ADC模拟信号转数字信号

来源:互联网 发布:潍坊四中的网络签章 编辑:程序博客网 时间:2024/05/29 03:49

模拟信号转数字信号大致都不陌生,模拟信号是连续性变化的信号,ADC就是把连续型信号通过线性变换,转换成相应的数字信号保存在寄存器里,MCU直接读取即可。(传感器一般是线性的数据变换)

基础知识:1. 51中PCF8591是8位ADC芯片 (I2C对SCL,SDA控制,也算方便。后面把I2C,1-wire,SPI协议都讲了,就把各个协议对比一下,使用情况也分析一下)。而STM32内是12位ADC转换,18个通道(16个外部ADC, 2个内部信号源,下面代码就是测试使用内部信号源)

    2. 4种模式:单次,连续 ,扫描和间断模式执行

    3. ADC的输入时钟不能超过14MHZ, 像STM32F103ZE的RCC就是72MHZ,然而使用必须分频低于14MHZ来使用(ADC转换是要时间的,它要将模拟信号转换成数字信号填入数据寄存器,如果晶振太大,精度就会受影响,后面的数据没填进去)

    4. 中断源:很多外设都有中断,ADC同样有

    5. 可以使用DMA, 后面会将DMA_ADC混合使用复习一下

   ADC引脚:

Vref, Vdda, Vref-, Vssa 这些了解一下即可,不重要。

ADCx_IN    模拟输入信号  (16个模拟输入信号,2个内部的不用ADCx_IN)

18个通道挂接在ADC1,ADC2,ADC3上,  16通道只负责ADC1的温度传感器

  17通道只负责ADC1的内部参考电压(ADC采集可以随意挂接其他通道)

          至于各个模式,结构体配置有介绍,代码里注解写上,也把个人认为有参考的心得,吐槽加上


#include "adc.h"

void adc_init()
{
GPIO_InitTypeDef GPIO_InitStructure;         /*
 配置GPIO结构体*/
ADC_InitTypeDef ADC_InitStructure;           /*
配置ADC结构体*/

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);  /
ADC1挂接APB2总线上,APB2总线开启复用功能,ADC还不算复用?下次将STM32系统总线,AHB,APB1,APB2,DNA,FSMC挂接方式,总线仲裁写一下/
RCC_ADCCLKConfig(RCC_PCLK2_Div6);            /
72Mhz进行6分频,ADC晶振不能超过14Mhz/


/*
使用到GPIO采集数据,所以要配置GPIO */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  /
配置晶振/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;          //ADC123_IN1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;      /
讲过,ADC模拟量的采集就是这个模式/
GPIO_Init(GPIOA,&GPIO_InitStructure);            

/*
配置ADC结构体 */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;   /
独立工作模式/
ADC_InitStructure.ADC_ScanConvMode =DISABLE;         /
多通道采集ENABLE,单通道DISABLE。我们就采集小手掌处电压值,故使用单通道     
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;  /
单次采集DISABLE,多次采集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_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5)
/核心板上写的是ADC2,其实都是复用的,ADC123都是等价的,随意自己使用,但主意,ADC123_IN1代表ADC随意用,但通道是1,不然读不出来/;
ADC_Cmd(ADC1, ENABLE);                 /
使能/
ADC_ResetCalibration(ADC1);            /
重设ADC1校准/
while(ADC_GetResetCalibrationStatus(ADC1));  /
ADC外设速度都较慢,都要等待校准结束,后面还有外设如此/
ADC_StartCalibration(ADC1);       /
正式校准,吐槽:为毛不直接校准,还有重设这东西/
while(ADC_GetCalibrationStatus(ADC1)); /
判断,再次吐槽,这博客注解不能加在//后,还乱码,TMD/



ADC_SoftwareStartConvCmd(ADC1, ENABLE); 
}



main.c文件

#include "public.h"
#include "Systick.h"
#include "printf.h"
#include "adc.h"

int main()
{
u8 i;
u32 ad=0;
printf_init();
adc_init();
while(1)
{
for(i=0;i<50;i++)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);            
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));    
ad=ad+ADC_GetConversionValue(ADC1);
}
ad=ad/50;
printf("AD=%fV!\r\n",ad*3.3/4096);              
delay_ms(1000);
}
}
    

原创粉丝点击