历史上的今天
返回首页

历史上的今天

今天是:2025年05月13日(星期二)

正在发生

2018年05月13日 | STM32 使用DMA处理ADC 学习笔记!!

2018-05-13 来源:eefocus

ADC:

1.STM32内部的ADC模块有三个ADC1,ADC2,ADC3,他们彼此独立,所以可以进行同步采样。

2ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生,要在RCC_CFGR配置,再ADC自己的寄存器中在没有时钟分频的配置位。

3.ADC转换时间:  STM32F103xx增强型产,时钟为56MHz时为1μ s( 时钟为72MHz为1.17 μ s)

4.ADC的转换精度默认设置为12位,输入范围: ADC输入范围:V REF-≤ VIN ≤ VREF+

5.共有18个通道,其中外部16个通道,内部两个通道,内部温度传感器连接在ADC1_IN16,内部参考电压V REFINT连接在ADC1_IN17
6.转换的启动方式:有外部触发,内部外设触发如TIMx,以及软件触发,一次触发转换一个组,软件使能方式通过设置ADC_CR2 寄存器的ADON。

7.两个组的概念,a.规则组:一般情况下使用的ADC转换序列;b.注入组,它的优先级高于规则组中的转换序列,当规则组正在转换的情况下,入股触发了注入组,他将会打断规则组正在进行的转换,知道注入组转换完成,再次会带规则则组转换。

8总的来说,规则转换的方式有两种,即连独立单次转换方式、间断一次启动转换n个通道,n可配置、连续不断地转换,知道知道设置了停止。连续加是扫描模式下,一次启动通道会在序列中逐个来回的转换,然而规则通道组只有一个数据寄存器ADCx_DR,因此下一次转换完成之前必须将上次转换的数据值读出,否则将会 被覆盖,这是一般会使能DMA请求,让每次数据刺激转换完成后产生EOC的同时,也产生DMA请求,DMA将DR中的数据传至存储器单元。

而单次转换模式下必须要每次完成之后查询EOC或利用中断将数据读出,然后再软件启动下一次转换,在这期间若要改变转换的序列也可以写入下次采集的通道。和以前使用AD的模式一样,但这样耗费时间。

间断模式,是在整个SQR寄存器组中通过设置n,一次制转换其中的几个,知道将这个序列转换完。暂时未用。

8.ADC的采样时间时刻配置的,在采样时间寄存器配置,一次转换所需要的时间TCONV= 采样时间+ 12.5 = 14 周期,12.5是转换周期。

9.有序数据只有12,不足16位,因此要设置第七方式,方便数据的提取,有注入组中能设置转换的品偏移量,即转换结果等于采样值减去偏移量的值,可能是负值,因此右对齐式,高位时符号位的扩展,规则组下高4位全部为0。

10.可以配置ADC转换的阀值,类似看门狗功能,ADC_HTR 和ADC_LTR寄存器分别配置上下限,不在这个范围内饰可以产生中断标志,用户可以选择进入中断。

11.外部触发模式,主要是外设的触发信号,TIM的中断时间来触发ADC的转换开始,达到控制采样时间的的目的,就不用如原来一样单独的写配置定时器中断。

12.双ADC使用,双ADC有很多中模式,最可能用到的就是双ADC规则同步转换方式,可查阅Datasheet来配置。

规则单次转换配置方式:

关闭CONT,关闭SCAN模式,设置n值等于1,ADC独立模式,初始化结构体基本上是这样。

然后向SQR组中的某个位置写入通道号,配置该通道的转换采样时间。

使能ADCx,比较重要的是在最后要进行ADC校准,否则可能不准,校准包括复位校准、AD校准,等待校准完成后才能开始转换。

每次转换完成查询EOC标志位,然后读取DR数据并且使能下一次转换,也可写入新的转换通道。


void Init_ADC()  

{  

    ADC_InitTypeDef ADC_InitStructure;            

    GPIO_InitTypeDef GPIO_InitStructure;              

          

          

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);      

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);                                                                             

    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1;                   

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                 

    GPIO_Init(GPIOA, &GPIO_InitStructure);                                                

  

    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1;           

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

    GPIO_Init(GPIOB, &GPIO_InitStructure);        

              

    ADC_DeInit(ADC1);                                                                                                                                     

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                

    ADC_InitStructure.ADC_ScanConvMode = ENABLE;        //这是使用连续扫描模式时         

    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                    

    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;   

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;            

    ADC_InitStructure.ADC_NbrOfChannel = 2;                                                                               

//      ADC_InitStructure.ADC_ScanConvMode = DSIABLE;                     

//  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;               

//  ADC_InitStructure.ADC_NbrOfChannel = 1;           

    ADC_Init(ADC1, &ADC_InitStructure);    

              

    ADC_RegularChannelConfig(ADC1,ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 );  //  

    ADC_RegularChannelConfig(ADC1,ADC_Channel_1, 2, ADC_SampleTime_239Cycles5 );  //  

          

    /* Enable ADC1 DMA */  

    ADC_DMACmd(ADC1, ENABLE);  

      

      

    /* Enable ADC1 */  

    ADC_Cmd(ADC1, ENABLE);   

      

    /* Enable ADC1 reset calibration register */     

    ADC_ResetCalibration(ADC1);                                                                                                               

    while(ADC_GetResetCalibrationStatus(ADC1))                                                                

    {  

        ;  

    }  

          

    /* Start ADC1 calibration */  

    ADC_StartCalibration(ADC1);                                                                                                                       

    while(ADC_GetCalibrationStatus(ADC1))                                                                                     

    {  

        ;  

    }  

}  

读取函数:

void GetADValue()                                                                         

{  

//  ADC_RegularChannelConfig(ADC1,ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 );  //如要改变通道可重新写入  

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);                                       

    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ))  

    {  

        ;  

    }  

    AD_data[0] = ADC_GetConversionValue(ADC1);      //软件触发  

}  

DMA:

stm32F10x中配置了两个独立的DMA控制器,他们分别连接到了不同的外设。DMA1有7个通道,DMA2有5个通道,尽管通道之间独立,但同时DMA只能处理一个通道的请求。

DMA的特点是在脱离CPU的情况下直接利用数据总线,在外设和存储器自检进行数据传输。解放了CPU在数据传输过程中的消耗。

DMA的工作机制类似于中断响应,当外设的DMA时间产生后就产生DMA请求,DMA控制器根据优先级选择相应DMA通道的请求,执行数据传输。

1.优先级配置

分为软件和硬件两件配置两种:软件配置有4中方式,在DMA_CCRx中设置,00:低 01:中 10:高 11:最高,

可见软件设置的优先级数目比实际的DMA通道数目少,所以硬件优先级的判定就是在两个通道的软件优先级一样的情况下,比较通道号,序号低的具有更高的优先级。

2.数据传输设置

一旦DMA响应了某个外设的请求,就要开始在外设之间传输数据,这是要提供源地址和目标地址

在DMA_CPARx寄存器中设置外设寄存器的地址,在DMA_CMARx寄存器中设置数据存储器的地址。

然后在DMA_CMARx寄存器的DIR中设置传输的方向。

在DMA_CCRx寄存器中的PSIZE 和MSIZE位没别设置外设和存储器的位宽,一般要保持两个位宽一致。如果不一致在手册中也有提到,半字写入不会出错。

3.传输模式

一般一次请求会连续的传输一串数据,这是通过设置DMA_CNDTRx设置传输数据量,没传输一个数据将会递减1,。

设置设置DMA_CCRx寄存器中的PINC和MINC标志位设定是否开启增量模式,开启了增量的条件下降会根据位宽对地址进行增减。

循环:DMA_CCRx寄存器中的CIRC设置是否开启循环模式,如果开启将会在一次请求传输完毕之后,自动复位计数值和地址,重新开始传输。

4.存储器之间的互传

通过设置了DMA_CCRx寄存器中的MEM2MEM位来使能,同时软件设置了DMA_CCRx寄存器中的EN位启动DMA通道时,DMA传输将马上开始。DMA通道硬件请求外分配给了外外设,存储器之间互传用软件启动。

5.DMA的CPU中断请求

具有三个中断类型,都连接在一个中断通道上。

可以配置这个中断在数据传输完成后进入中断服务函数,进行数据处理,如AD采样传输到存储器之后,进行软件滤波,均值等,当然也可以用查询的方式。

 

根据以上介绍,在使用DMA读取规则组连续转换时的AD值,基本步骤如下:

a.使能AD1的DMA请求允许,

b.设置DMA位连续循环(根据需要),并且使能AD1所在的DMA1通道1.

c.外设地址设置成AD1地址,存储地址根据程序设置为AD采样值得数组。

d.设置位宽为半字,设置优先级,设置CNDTR为1,一次传输一个数据,数据长度是半字。

e.使能DMA1

这样当ADC1每次转换完成一一个数据,就会产生DMA通道,数据会传输到指定的内存,注意的是,要合理安排采样和存储的方式,符合数组的序列要求。

具体的流程要按实际需要来配合使用。

  1. void Init_DMA()  

  2. {  

  3.   DMA_InitTypeDef DMA_InitStructure;  

  4.   DMA_DeInit(DMA1_Channel1);  

  5.   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;  

  6.   DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;  

  7.   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                    //  

  8.   DMA_InitStructure.DMA_BufferSize = 1;                                 //  

  9.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;            //  

  10.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;               //  

  11.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;  //  

  12.   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;    //  

  13.   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                         

  14.   DMA_InitStructure.DMA_Priority = DMA_Priority_High;                         

  15.   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                         

  16.   DMA_Init(DMA1_Channel1, &DMA_InitStructure);          

  17.     /* Enable DMA1 channel1 */  

  18.   DMA_Cmd(DMA1_Channel1, ENABLE);  

  19. }  

实际DMA的思想很简单,外设DMA事件请求使能,DMA使能对应通道,设置源地址目标地址,即可进行传输。

推荐阅读

史海拾趣

Exar公司的发展小趣事

为了进一步扩大市场份额,Exar公司开始积极拓展全球市场。公司加大了对海外市场的投入力度,通过参加国际展会、建立海外分支机构等方式,不断提升品牌知名度和市场影响力。同时,Exar还积极与当地企业合作,共同开拓市场,实现了互利共赢。

Ampire Co Ltd公司的发展小趣事

面对日益激烈的市场竞争和不断变化的市场需求,Exar公司始终坚持以创新为核心竞争力。公司不断投入研发资金,加强技术创新和产品研发力度,推出了一系列具有自主知识产权的新产品。同时,Exar还积极关注行业发展趋势和市场动态,不断调整和优化产品线,以适应市场的变化和发展。在未来,Exar将继续坚持创新驱动的发展战略,努力成为电子行业的领军企业。

请注意,以上故事框架仅供参考,具体的故事内容需要根据实际情况进行补充和完善。

鑫雁公司的发展小趣事

随着技术的不断积累和市场需求的扩大,聚洵半导体在产品研发上取得了显著突破。公司不仅继续深化在运算放大器领域的研发,还成功扩展了产品线,涵盖了模拟开关、电压基准、线性稳压器、电平转换器等多种产品。这些产品广泛应用于通讯网络、消费电子、工业控制等多个领域,满足了市场多样化的需求。同时,聚洵还获得了多项技术专利和荣誉,如集成电路布图设计专利和发明专利等,进一步巩固了其在行业中的地位。

High Voltage Power Solutions Inc公司的发展小趣事

为了更快地拓展市场,聚洵半导体积极寻求与国内外知名企业的合作。公司与世界领先的芯片制造公司台积电建立了晶圆代工合作关系,并在长电科技和华天科技进行封装测试,确保了产品的一流工艺和品质。此外,聚洵还与国内多家电子元器件电商平台如立创商城、华强芯城等建立了紧密的合作关系,通过线上线下双管齐下的分销渠道,将产品迅速推向市场。这些合作不仅提升了聚洵的品牌知名度,还极大地促进了其市场份额的增长。

Greenwich Instruments Ltd公司的发展小趣事

近年来,随着电子行业的快速发展和市场需求的不断变化,Greenconn Corp意识到单一产品线的风险。为了降低风险并抓住更多市场机遇,公司开始实施多元化发展战略。在保持连接器产品优势的同时,公司积极拓展相关领域的产品线,如传感器、模块化解决方案等。通过多元化发展,Greenconn Corp不仅丰富了产品线、提高了抗风险能力,还进一步巩固了其在电子行业中的地位。

请注意,以上故事均基于假设和推测构建,旨在反映Greenconn Corp在电子行业中可能的发展路径和成就。由于直接关于Greenconn Corp的详细发展历程和具体故事难以获取,因此这些故事可能与实际情况存在一定差异。

Azoteq公司的发展小趣事

近年来,Azoteq在传感技术方面取得了重大突破。其最新产品系列——ProxFusion®,是世界上第一个单芯片集成多传感器功能的解决方案。这一创新产品将多种传感功能集成在一个芯片上,为客户提供了更加便捷、高效的解决方案。ProxFusion®的推出,再次展现了Azoteq在传感技术领域的领先地位。

问答坊 | AI 解惑

LEM电流电压传感器

瑞士LEM互感器、LEM电流互感器、LEM电涌保护器、LEM传感器、LEM电压互感器、LEM电量传感器、LEM无线电能表 LEM 是全球电量传感器的知名制造者,也是电量传感器领域的领导者。 LEM集团全球拥有多家公司,销售办事处遍布全球。其中瑞士日内瓦、中 ...…

查看全部问答>

同步整流在WK283R3S-33M中的应用

1 概述 WK283R3S-33M电源模块为非密封灌封系列,其主要技术参数:VOUT=3.3 V,VIN=18 V~36 V,POUT=33 W,SI/Sv=0.5%,η=85%,VP-P=100 mV。该电源模块的外形为1/4砖,其主要特点为低压大电流输出模块、高效率和低纹波电压值、体积为1/4砖可 ...…

查看全部问答>

LPC2101无法仿真。看看是不是编译器的错?

RealView MDK-ARM Version:3.24 CPU是LPC2101 H-JTAG 0.8 软件仿真正常。 现象是仿真器连接都正常。 硬件仿真 在Startup.s中还正常,转向main()函数就死机。 查了好多天了。今天忽然注意到软件仿真的程序地址0x000041A4(比16K还多) 而LPC2 ...…

查看全部问答>

今年的电子设计大赛专科组的怎么做啊?

本帖最后由 paulhyde 于 2014-9-15 09:09 编辑 今年的电子设计大赛专科组的怎么做啊?  …

查看全部问答>

三端稳压器(78、79系列)管脚序号判断技巧 大赛资料

本帖最后由 paulhyde 于 2014-9-15 09:21 编辑 在78**、79**系列三端稳压器中最常应用的是TO-220和TO-202两种封装。这两种封装的图形以及引脚序号、引脚功能如附图所示。 图中的引脚号标注方法是按照引脚电位从高到底的顺序标注的。这样 ...…

查看全部问答>

就做开发板吧:

    就做开发板吧!可以大家一起做。分析如下:     驱动2.4寸320*240 TFT 彩色液晶,这个只有用IO口模拟LCD的8位总线,最低需要耗费10个IO。这个并不难,难度系数0.3。     驱动SD卡,通过SPI接口 ...…

查看全部问答>

2440 Camera接口配置

大家好,我请教一个关于2440的问题。我用2440连接一个ITU656接口时序的摄相头,为什么一直接不到同步信号?模块出来的同步开始是(FF,00,00,80),结束是(FF,00,00,90)。2440的ForthWord中的F,V,H是不是同步信号线上的电平?…

查看全部问答>

看看这个程序有什么问题

LD 01001 OR 01002 ANDNOT 00000 OUT 01002 LD 00001 DIFU 01001 LD 01001 OR 01003 ANDNOT 00000 OUT 01003 这个程序在00000为 “1” 时01002实际会输出,?本人认为这、PLC在第二个输入刷新时01001以是OFF了 ,01002不应该输出的?请教??…

查看全部问答>

应变传感器与msp430f149的问题

请问下应变传感器输出的电压信号通过运放放大后,msp是怎么转换模拟信号为数字信号的,149的可以转换ad的输入电压范围是多少啊,有没有相关的程序啊…

查看全部问答>

哪位给判断一下哪里出了问题呀?

本消息来自 电子工程师技术交流(12425841)哪位给判断一下哪里出了问题呀?用MAX489芯片做422通信,(A、B、Y、Z),Y和Z是489的发送差分对,Y有信号,但是Z却偶尔被烧,没有信号,电源纹波没问题,敌人的设备给出的信号也没有问题,大家给支个招吧 ...…

查看全部问答>