零死角玩转STM32---单通道ADC分析

/*adc.h*/
#define ADC1_DR_Address    ((u32)0x4001244C)
void ADC_Configuration(void);

/*adc.c*/
#include "adc.h"         
vu16 ADC_ConvertedValue;     //此变量用来存放DMA读取到的ADC转换的结果,在main函数中 extern vu16 ADC_ConvertedValue; 即可使用转换好的结果


/*ADC配置,包括了DMA的配置,只需要在main函数中调用这个函数即可*/
void ADC_Configuration( void)
{
  ADC_InitTypeDef ADC_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);     //初始化外设(DMA)的时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);  //初始化外设(ADC1,GPIOA)的时钟,因为使用的是GPIOA的第二功能,  所以还得把第二功能的时钟给启动了

  /* Configure PA.0x (ADC Channelx) as analog input -------------------------*/
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ;  //将GPIOA的第5引脚设置为模拟输入(如果需要使用其他的引脚的话,只需要把5改成对应的引脚,并修改对应的ADC通道(下方有说明)即可)
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;    //设置为模拟输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);     //调用初始化库函数,将上面的配置写入寄存器
   
  /* DMA channel1 configuration --------------设置DMA1通道11--------------------------------*/
  DMA_DeInit(DMA1_Channel1);                      
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;      / /DMA通道读取数据的源地址,(即在adc.h中定义的ADC数据寄存器的地址,ADC转换好之后会将结果保存在这个寄存器中)
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;   //DMA通道的目的地址,也就是上面我们定义的用来存放ADC转换结果的变量
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                //设置DMA传送的方向  外设到内存
  DMA_InitStructure.DMA_BufferSize = 1;            //缓存空间,因为是单通道的ADC转换,所以只需要设置为1(DMA传送是在这个缓冲空间满了之后才开始的!所以不要随便定义)
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //因为ADC转换之后结果一直都是存放在它的数据寄存器中,这个地址永远不会改变,所以这里禁止了地址自动增量
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;     //因为是单通道,只有一个变量,所以内存地址的自动增量也禁止了(多通道的时候用一个数组来存放转换结果,这时需要使能自动增量)
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;   //外设的数据宽度(这个可以查看对应的数据手册,ADC的数据寄存器是16的,所以设置为半字即可)
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   //内存的数据宽度
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;            //使能循环传送,这样就可以读到连续的变化的ADC转换值
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
 
  /* Enable DMA1 channel1 */
  DMA_Cmd(DMA1_Channel1, ENABLE);
    
  /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;    //ADC独立模式
  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数据对齐,右对齐(ADC的转换结果是12位的,而ADC的数据寄存器是16位的)
  ADC_InitStructure.ADC_NbrOfChannel = 1;          //ADC转换的通道数量1
  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular channel6 configuration */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5); //ADC规则转换配置,ADC1,通道5(需要换其他引脚的话,这个也要改成对应的ADC通道),因为是单通道,所以通道顺序也就设置为1了,最后是采样时间

  /* Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);   //使能ADC的DMA传送
 
  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);    //使能ADC1转换

  /* Enable ADC1 reset calibaration register */   
  ADC_ResetCalibration(ADC1);        //ADC校正,具体看我的上一篇博客
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* Start ADC1 calibaration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));
     
  /* Start ADC1 Software Conversion */
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);    //上面我们禁止了外部触发转换,是因为我们采用了软件触发
}

关于ADC单通道的程序分析到此结束,附上主函数代码 如果有错误的地方,欢迎各位拍砖,互相交流。。。
/*main.c*/

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "usart.h"    //串口打印的头文件
#include "adc.h"
#include "systick.h"  //这个主要就是延时的时候用到,如果不适用延时的话可不要
#include


void NVIC_Configuration( void)   //中断优先级配置
{
  NVIC_InitTypeDef NVIC_InitStructure;    //定义数据结构体
 
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000); //将中断矢量放到Flash的0地址

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //设置优先级配置的模式,详情请阅读原材料中的文章

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  NVIC_Init(&NVIC_InitStructure);     //将结构体丢到配置函数,即写入到对应寄存器中
}

float AD_value;
extern vu16 ADC_ConvertedValue;


int main(void)
{
  u32 i=0x03;
  SystemInit();
  Delay_Init();
  usart_Configuration();
  ADC_Configuration();
  NVIC_Configuration();
  while(1)
  {
        /* Printf message with AD value to serial port every 1 second */
      AD_value = ADC_ConvertedValue;
      AD_value = (AD_value/4096)*3.3;
    printf("The current AD value = %4.2fV \r\n", AD_value);
      Delay(1000);   /* delay 1000ms */
  }
}


 


你可能感兴趣的:(stm32,STM32)