分享

野火STM32 ADC(DMA模式)实验 详细分析

 黄致明 2014-01-03
发现ADC(DMA模式)实验 啊,DMA 那里地方,讲解不是太详细。按照野火教程上,USART 的DMA 方式实验,没有讲。 所以还有些模糊,今天对照野火的ADC 程序,然后对照库函数,做了个详细的备注.这里只注释adc.c 函数的内容。 新手上路,喜欢搞得详细一些,分享给 和我一样的新手。 哈哈。。。
  1. /********************************************************************************
  2. ADC使用DMA 功能描述:
  3. 启动AD转换后,AD 每次转换完成后,由DMA 控制器把转换值从ADC数据寄存器(ADC_DR)
  4. 中转移到变量ADC_ConvertedValue,当DMA完成后,在main中使用的,就是ADC 转换的结果。

  5. ********************************************************************************/

  6. #include"adc.h"

  7. #define ADC1_DR_Address    ((u32)0x40012400+0x4c)   //宏定义   ADC1 转换后保存数据的地址

  8. //具体见 STM32参考手册 P178  0x4c  的意思就是ADC1_DR 的具体地址
  9. //0x40012400  是ADC 的寄存器首地址    STM32参考手册 P28 

  10. __IO uint16_t ADC_ConvertedValue;  //定义一个数据

  11. /********************************************************************************************
  12. 分析上面这个定义数据的意思:

  13. core_cm3.h 定义了 __IO:
  14. #define     __IO    volatile       !< defines 'read / write' permissions 

  15. volatile  作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值. 

  16. stdint.h定义了 uint16_t        :
  17. typedef unsigned short     int uint16_t;

  18. ADC_ConvertedValue   变量名

  19. ********************************************************************************************/

  20. void ADC1_Init(void)
  21. {
  22.         ADC1_GPIO_Config(); //ADC1 GPIO 设置
  23.         ADC1_Mode_Config();        //ADC1 工作方式设置
  24. }

  25. /*
  26. * 函数名:ADC1_GPIO_Config
  27. * 描述  :使能ADC1和DMA1的时钟,初始化PC.01
  28. * 输入  : 无
  29. * 输出  :无
  30. * 调用  :内部调用
  31. */
  32. static void ADC1_GPIO_Config(void)
  33. {
  34.         GPIO_InitTypeDef GPIO_InitStructure; //定义结构体 
  35.         // 结构体内容在stm32f10x_gpio.h  101行        //  见库函数 P125页  

  36.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);
  37.         //打开时钟

  38.         /* Enable DMA clock */                  //打开DMA 时钟
  39.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //注意它的时钟树


  40.         //初始化GPIO 见库函数 P125页 
  41.         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;           //要设置的PIN

  42.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  // 设置IO 为 模拟输入

  43. //        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;        //输入 不用设置速度
  44.         GPIO_Init(GPIOC,&GPIO_InitStructure);        //配置 IO        
  45. }

  46. /* 函数名:ADC1_Mode_Config
  47. * 描述  :配置ADC1的工作模式为MDA模式
  48. * 输入  : 无
  49. * 输出  :无
  50. * 调用  :内部调用
  51. */
  52. static void ADC1_Mode_Config(void)
  53. {
  54.         ADC_InitTypeDef ADC_InitStructure;  //定义 ADC 结构体
  55.         DMA_InitTypeDef DMA_InitStructure;        //定义 DMA 结构体

  56.         //DMA 初始化 函数使用   见库函数 P89页
  57.         /* DMA channel1 configuration */
  58.         DMA_DeInit(DMA1_Channel1); //将DMA 通道1寄存器 复位          ADC DMA 对应 通道1

  59.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;         //DMA外设基地址  即ADC地址
  60.         DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&ADC_ConvertedValue;//DMA内存基地址  即要存放数据的地址
  61.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设作为数据传输的来源
  62.         DMA_InitStructure.DMA_BufferSize = 1; //DMA 缓存大小
  63.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变
  64.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;  //内存地址不变
  65.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;        //外设数据宽度16位
  66.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //内存数据宽度
  67.         DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                //工作在循环缓存模式
  68.         DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设定DMA通道X 的优先级
  69.         DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA 通道X 没有设置 内存到内存传输
  70.         DMA_Init(DMA1_Channel1, &DMA_InitStructure); //配置DMA 通道1 参数
  71.                 /* Enable DMA channel1 */
  72.         DMA_Cmd(DMA1_Channel1, ENABLE);


  73.         
  74.         //ADC 初始化 函数使用   见库函数 P42页
  75.         /* ADC1 configuration */
  76.         ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;        //独立ADC模式
  77.         ADC_InitStructure.ADC_ScanConvMode = DISABLE ;          //禁止扫描模式,扫描模式用于多通道采集
  78.         ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;        //开启连续转换模式,即不停地进行ADC转换
  79.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不使用外部触发启动
  80.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;         //采集数据右对齐
  81.         ADC_InitStructure.ADC_NbrOfChannel = 1;                 //要转换的通道数目1

  82.         ADC_Init(ADC1,&ADC_InitStructure); //配置设定好的工作方式

  83.         /*配置ADC时钟,为PCLK2的8分频,即9MHz*/
  84.         RCC_ADCCLKConfig(RCC_PCLK2_Div8);
  85.         
  86.         /*配置ADC1的通道11为55.        5个采样周期,采样顺序为1 */   //见   库函数P49
  87.         ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);

  88.         /* Enable ADC1 DMA */
  89.         ADC_DMACmd(ADC1, ENABLE);         //使能ADC1 的DMA 请求        见库函数 P45
  90.         
  91.         /* Enable ADC1 */
  92.         ADC_Cmd(ADC1, ENABLE);           //使能ADC1 见库函数 P44    注意:函数ADC_Cmd 只能在其他ADC函数设置后被调用

  93.         //在开启AD 转换前  启动AD 自校准
  94.         /*复位校准寄存器 */   
  95.         ADC_ResetCalibration(ADC1);         //库函数 P46 页

  96.         /*等待校准寄存器复位完成 */
  97.         while(ADC_GetResetCalibrationStatus(ADC1));

  98.         /* 开启 ADC校准 */
  99.         ADC_StartCalibration(ADC1);
  100.         /* 等待校准完成*/
  101.         while(ADC_GetCalibrationStatus(ADC1));

  102.         /* 由于没有采用外部触发,所以使用软件触发ADC转换 */ 
  103.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);        ////库函数 P47 页
  104.          



  105. }

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多