STM32F030 ADC1的DMA采样问题

发布者:zukeq2009最新更新时间:2018-04-15 来源: eefocus关键字:STM32F030  ADC  DMA采样 手机看文章 扫描二维码
随时随地手机看文章

搞了1天一直ADC没有出来,发现采处理的值一直是固定值..

去21IC求助贴.[STM32F0] STM32F030 ADC1采样问题请教

等了好久都没有人回复,但有人提醒我说需要等待DMA的数据完成.

后面对比了别人的代码,

/* ADC DMA request in circular mode */
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);

别人有这句代码,于是我加上这个话,则能够正常采样到数据了,

所以,必须得添加,否则无法获取到采样值.


接着又发现DMA传输到指定的数组数据顺序错乱了.....

类似别人的求助贴:[STM32F0] STM32F030 多通道ADC DMA读取问题

后面解决方式,按照最后帖子的方式解决的

        " F0的ADC在使用之前需要校准。这个7位的校准值也是放在ADC_DR中的,它也会触发DMA请求。可以参照F0的ADC-DMA例程,先做ADC校准、然后再设置DMA,再使能ADC的DMA。"


直接插入代码,正确的初始化代码:

  1. typedef enum  

  2. {  

  3.     ADC_PORTA0 = ADC_Channel_0,      

  4.     ADC_PORTA1 = ADC_Channel_1,  

  5.     ADC_PORTA2 = ADC_Channel_2,  

  6.     ADC_PORTA3 = ADC_Channel_3,  

  7.     ADC_PORTA4 = ADC_Channel_4,  

  8.     ADC_PORTA5 = ADC_Channel_5,  

  9.     ADC_PORTA6 = ADC_Channel_6,  

  10.     ADC_PORTA7 = ADC_Channel_7,  

  11.     ADC_PORTA8 = ADC_Channel_8,  

  12.     ADC_PORTA9 = ADC_Channel_9,  

  13.     ADC_PORTA10 = ADC_Channel_10,  

  14.     ADC_PORTA11 = ADC_Channel_11,  

  15.     ADC_PORTA12 = ADC_Channel_12,  

  16.     ADC_PORTA13 = ADC_Channel_13,  

  17.     ADC_PORTA14 = ADC_Channel_14,  

  18.     ADC_PORTA15 = ADC_Channel_15,  

  19. }AD_PORT;  

  20.   

  21. typedef enum   

  22. {  

  23.     KEY_LINE_1,  

  24.     KEY_LINE_2,  

  25.     ADC_KEY_LINE_MAX = KEY_LINE_2,  

  26.     BATTERY_AD,  

  27.     ADC_NUM_CNT,    //ADC的总数  

  28. }ADC_NUM;  

  29.   

  30.   

  31. volatile u16 g_uADC_ConVal[ADC_NUM_CNT] = {0};      // ADC转换值  

  32.   

  33.   

  34. u32 const  g_uADNum[]=  

  35. {     

  36.     //KEYPORTA1,   

  37.     ADC_PORTA9,    

  38.     ADC_PORTA8,    

  39.     ADC_PORTA2,  

  40.     //KEYPORTA0,  

  41. };  

  42.   

  43.   

  44. void Adc_Init(void)  

  45. {  

  46.     ADC_DeInit(ADC1);     

  47.       

  48.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  

  49.   

  50.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);  

  51.   

  52.     //打开DMA1的时钟  

  53.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  

  54.     //打开ADC1的时钟  

  55.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);  

  56.   

  57.     RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);  

  58.   

  59.     //初始化IO口  

  60.     GPIO_InitTypeDef    GPIO_InitStruct;  

  61.     GPIO_StructInit(&GPIO_InitStruct);  

  62.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;  

  63.     GPIO_InitStruct.GPIO_Pin =  AD_KEY1_PIN;  

  64.     GPIO_Init(AD_KEY1_PORT,&GPIO_InitStruct);               // KEY1  

  65.     GPIO_InitStruct.GPIO_Pin =  AD_KEY2_PIN;  

  66.     GPIO_Init(AD_KEY2_PORT,&GPIO_InitStruct);               // KEY2  

  67.     GPIO_InitStruct.GPIO_Pin =  BATTERY_AD_PIN;  

  68.     GPIO_Init(BATTERY_AD_PORT,&GPIO_InitStruct);;           // 电池电源采样  

  69.   

  70.     //配置ADC1的DMA模式  

  71.     ADC_InitTypeDef ADC_InitStructure;  

  72.     DMA_InitTypeDef DMA_InitStructure;  

  73.     DMA_DeInit(DMA1_Channel1);  

  74.     DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(ADC1->DR);             //定义DMA外设基地址,即为存放转换结果的寄存器  

  75.     DMA_InitStructure.DMA_MemoryBaseAddr = (u32)g_uADC_ConVal;      //定义内存基地址  

  76.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;          //定义AD外设作为数据传输的来源  

  77.     DMA_InitStructure.DMA_BufferSize = ADC_NUM_CNT;     //指定DMA通道的DMA缓存的大小,即需要开辟几个内存空间,本实验有两个转换通道,所以开辟两个  

  78.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;    //设定寄存器地址固定  

  79.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;         //设定内存地址递加,即每次DMA都是将该外设寄存器中的值传到三个内存空间中  

  80.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;     //设定外设数据宽度  

  81.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         //设定内存的的宽度  

  82.     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                     //设定DMA工作再循环缓存模式  

  83.     DMA_InitStructure.DMA_Priority = DMA_Priority_High;                 //设定DMA选定的通道软件优先级  

  84.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  

  85.     DMA_Init(DMA1_Channel1,&DMA_InitStructure);  

  86.   

  87.     /* ADC DMA request in circular mode */  

  88.     ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);                   //必须得添加,否则无法获取到采样值  

  89.   

  90.     ADC_StructInit(&ADC_InitStructure);  

  91.     ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;  

  92.     ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                  //设定AD转化在连续模式  

  93.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;         //不使用外部促发转换  

  94.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;                   //采集的数据在寄存器中以左对齐的方式存放  

  95.     ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;  

  96.     ADC_Init(ADC1, &ADC_InitStructure);   

  97.   

  98.     for(u8 uCnt = 0;uCnt < ADC_NUM_CNT;uCnt++)  

  99.     {  

  100.         /* Convert the ADC1  with 55.5 Cycles as sampling time */   

  101.         ADC_ChannelConfig(ADC1, g_uADNum[uCnt] , ADC_SampleTime_55_5Cycles);    //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间  

  102.     }  

  103.       

  104.     //ADC_ChannelConfig(ADC1, ADC_Channel_2 , ADC_SampleTime_55_5Cycles);   //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间  

  105.     //ADC_ChannelConfig(ADC1, ADC_Channel_8 , ADC_SampleTime_55_5Cycles);   //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间  

  106.     //ADC_ChannelConfig(ADC1, ADC_Channel_9 , ADC_SampleTime_55_5Cycles);   //设置指定ADC的规则组通道,设置它们的转化顺序和采样时间  

  107.     //ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);   

  108.   

  109.       

  110.     /* ADC Calibration */  

  111.     ADC_GetCalibrationFactor(ADC1);                     //校准ADC  

  112.   

  113.       

  114.     DMA_Cmd(DMA1_Channel1,ENABLE);  

  115.       

  116.     /* Enable ADC_DMA */  

  117.     ADC_DMACmd(ADC1, ENABLE);    

  118.   

  119.     ADC_Cmd(ADC1,ENABLE);                                                                   //使能指定的ADC1  

  120.     while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));             //等待ADC准备好  

  121.   

  122.   

  123.     ADC_StartOfConversion(ADC1);                        //启动转换  

  124. }  



另外补充,ADC_ScanDirection_Upward及ADC_ScanDirection_Backward的简要说明。假设ADC1有18个通道,1,2....18

ADC_ScanDirection_Upward表示从1~18开始扫描

ADC_ScanDirection_Backward表示从18~1方向扫描

这样就决定了,用户指定的内存数组里面存值的顺序.

像上面的代码,则对应关系为g_uADC_ConVal[0]--->AIN9  g_uADC_ConVal[1]--->AIN8 g_uADC_ConVal[2]-->AIN2


关键字:STM32F030  ADC  DMA采样 引用地址:STM32F030 ADC1的DMA采样问题

上一篇:串口进行STM32F0的IAP移植手记(包括RAM&ROM地址设置)
下一篇:手把手之STM32启动代码

推荐阅读最新更新时间:2024-03-16 16:00

STM32HAL库ADC实验(一)——阻塞查询法
实验现象 生成代码: int main(void) { /* USER CODE BEGIN 1 */ uint16_t adcData; float voltage; /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BE
[单片机]
STM32HAL库<font color='red'>ADC</font>实验(一)——阻塞查询法
STM8L051之通过ADC1与DMA读取内部参考电压
stm8L051芯片内部的参考电压与电源电压有一定的关系 这在芯片供电电压变化的情况下,测量外部ADC电压输入提供一个确定的参考电压。这里提前厘清下:该内部参考电压VREFINT 并非ADC 的参考电压,ADC 的参考电压依然是VDD。即使VDD 有所波动,这个VREFINT 电压恒定不变,对于ADC 电路而言,它只是个测试点。 对于某固定的ADC 参考电压情况下,所有被测电压点的AD转换值与该点电压值保持同一比例关系,换句话说,对于ADC参考电压固定情况下,各点的电压与ADC值与成线性关系。下面图形是芯片分别在3个不同参考电压的示意图,这里参考电压接VDD。下面三根斜线分别是VDD 为2.8V、3.2V、3.6V 时的A
[单片机]
STM8L051之通过<font color='red'>ADC</font>1与<font color='red'>DMA</font>读取内部参考电压
基于STM8的ADC读取---STM8-第四章
1. 综诉   想学会如何在STM8上使用ADC这个功能,我们先得了解单片机中ADC究竟是什么。   ADC是模拟信号转成数值信号,单片机只能识别TTL电平,其实就是 1 或者 0 ,但是如果我们给它一个3.3V电压,单片机就无法识别,,若想使用单片机读取出来得时候,它必须将模拟量变成数字量。 2. 关于STM8S103手册的ADC简介 由官方的全英手册可知。 -------------------------------------------------------------------------------------------------------------------------------
[单片机]
基于STM8的<font color='red'>ADC</font>读取---STM8-第四章
ATmega32 ADC噪声抑制模式
当SM2..0 为001 时, SLEEP 指令将使MCU 进入噪声抑制模式。在此模式下,CPU 停止运行,而ADC、外部中断、两线接口地址配置、定时器/ 计数器0 和看门狗继续工作。ATmega32这个睡眠模式只停止了clkI/O、clkCPU 和clkFLASH,其他时钟则继续工作。 此模式提高了ADC 的噪声环境,使得转换精度更高。ADC 使能的时候,进入此模式将自动启动一次AD 转换。ADC 转换结束中断、外部复位、看门狗复位、BOD 复位、两线接口地址匹配中断、定时器/ 计数器2 中断、SPM/EEPROM 准备好中断、外部中断INT0或INT1,或外部中断INT2 可以将MCU 从ADC 噪声抑制模式唤醒。
[单片机]
STM32F407 纯寄存器操作定时器,PWM,ADC(专治花里胡哨)
定时器 真多啊,14个定时器,三种。 通用定时器 注意: 需要手动清除中断标志 TIM3- ARR = 5000-1; //自动重载寄存器,10Khz 的计数频率,计数 5K 次为 500ms TIM3- PSC = 8400-1; //预分频器 两个寄存器的计算 PSC预分频器 //这里时钟选择为 APB1 的 2 倍,而 APB1 为 42M,所以TIM3的时钟频率为84M PSC=8400 f=84M/8400=10000Hz=10KHz t=1/f=0.1ms 每次技术时间0.1ms ARR=5000-1; //自动重载寄存器 计数5000次,共500ms //定时器溢出时间计算方法:Tou
[单片机]
STM32F407 纯寄存器操作定时器,PWM,<font color='red'>ADC</font>(专治花里胡哨)
STM32的ADC用法
AD采样在电路中是一种比较常见的功能,可以用于电池电压检测、传感器值读取、信号采集等。STM32的ADC,由于引入了DMA,以及多种触发源,功能自然强大,用法也多种多样。今天,我们简单说说在单通道情况下,AD采样的几种用法。 1、AD单次转换+软件启动 最基本的用法,通过程序启动AD,AD采集一次,我们就去读一次。这种情况,建议开启AD转换完成中断,在中断中读出AD值并做处理。 这种方式的优点是配置简单,缺点么,太T么简单~ 初始化的时候,启动一次。然后在主循环里,每隔一秒启动一次。 在中断回调函数里,进行相关处理: 电脑输出如下: 2、连续转换+软件启动 在方法1的基础上做调整,从单次转换,变成连续转换。
[单片机]
STM32的<font color='red'>ADC</font>用法
一种基于开关逻辑结构的低功耗SAR ADC的设计
  逐次逼近型模数转换器(successive approximati ON regi ST er analog-to-digital converter,SAR ADC)是应用于采样速率低于5,MHz 的中高分辨率的常见结构,其分辨率一般为8~16 位,因制造工艺与现代数字C MOS 工艺的兼容性好,且易于在较低的工艺成本下实现,所以广泛应用于现代超大规模 集成电路 与片上系统(system-on-chip,SOC),如便携式/ 电池 供电 仪表 、笔输入量化器、工业控制和数据/信号 采集器 等。   笔者设计了一款10位低功耗SAR ADC,采用温度计码控制的开关逻辑结构代替传统的开关阵列控制数模(digital-t
[电源管理]
一种基于开关逻辑结构的低功耗SAR <font color='red'>ADC</font>的设计
具宽输入共模范围的 16 位 5Msps SAR ADC 简化了模拟前端电路
加利福尼亚州米尔皮塔斯 (MILPITAS, CA) 2016 年 5 月 24 日 凌力尔特公司 (Linear Technology Corporation) 推出具有宽轨至轨输入共模范围的 16 位 5Msps 逐次逼近寄存器 (SAR) 型模数转换器 (ADC) LTC2311-16。LTC2311-16 提供了灵活的差分输入,可接受直至奈奎斯特频率的模拟信号。这可实现多种信号类型的直接转换,同时在 2.2MHz 输入信号时保持良好的 81.6dB 信噪比 (SNR),并在同样高速的输入信号时实现 85dB 的高共模抑制比 (CMRR)。 需要信道至信道隔离的仪表和医疗应用常常采用单通道 ADC,以单独地隔离前端电路。每
[模拟电子]
具宽输入共模范围的 16 位 5Msps SAR <font color='red'>ADC</font> 简化了模拟前端电路
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved