历史上的今天
返回首页

历史上的今天

今天是:2025年01月29日(星期三)

2019年01月29日 | STM32实现DMA读取ADC数据

2019-01-29

学习了DMA写了一个用DMA读取ADC数据的程序,记录下整个过程和一点心得


 


DMA配置详细说明

(MDK的汉字2复制过来就是乱码,我重新打了一遍注释,晕~)

//DMA1各通道配置

//外设->存储器/16位数据宽度

//DMA_CHx:DMA通道CHx

//cpar:外设地址

//cmar:存储器地址

//cndtr:数据传输量(因为我是一个16位的数据,所以是一)

void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)

{

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);    //使能DMA时钟

    

    DMA_DeInit(DMA_CHx);   //重设DMA为缺省值

 

    DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;  //外设地址

    DMA_InitStructure.DMA_MemoryBaseAddr = cmar;  //存储器地址

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  //外设到存储器的传输模式

    DMA_InitStructure.DMA_BufferSize = 1;  //数据量为1(应该为cndtr参数)

    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  //

    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;  //

    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord  ;  //16位!!!特别注意

    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord  ; //16位!!!特别注意

    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //循环模式

    DMA_InitStructure.DMA_Priority = DMA_Priority_High; //优先级高

    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //(内存到内存禁止)

 

    DMA_Init(DMA_CHx,&DMA_InitStructure);  //初始化

    DMA_SetCurrDataCounter(DMA1_Channel1,1);//设置数据量(应该为cndtr参数,若有其它需要改变即 

                                            //可,我这里是为了直观)

ADC相关配置

//ADC初始化    

void  Adc_Init(void)

{

ADC_InitTypeDef ADC_InitStructure; 

GPIO_InitTypeDef GPIO_InitStructure;

 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE );   //相关时钟使能

 

 

RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置分频因子,ADC时间最大不过14M

 

//PA1寄存器初始化                        

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入模式

GPIO_Init(GPIOA, &GPIO_InitStructure);

 

ADC_DeInit(ADC1);   

 

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_InitStructure.ADC_NbrOfChannel = 1; //

ADC_Init(ADC1, &ADC_InitStructure); // 

 

ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5 );     

        //配置采样时间

ADC_Cmd(ADC1, ENABLE); //使能指定ADC

ADC_DMACmd(ADC1, ENABLE);//使能ADC - DMA

ADC_ResetCalibration(ADC1); //复位校准  

while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准

ADC_StartCalibration(ADC1); //开启AD校准

  while(ADC_GetCalibrationStatus(ADC1)); //等待结束

ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件启动

}   

主程序

u16 SendBuff = 0; //数据缓存区

 

u16 MYGet_Adc()

{

u32 temp_val=0;

u8 t;

for(t=0;t<5;t++)

{

temp_val+=SendBuff;

delay_ms(5);

}

return temp_val/5;

}  

 

 

int main(void)

{  

u16 adcx = 0;//用于显示的数据

float temp;

delay_init();        

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

uart_init(115200); //波特率

LED_Init();  

LCD_Init();

Adc_Init();  

POINT_COLOR=BLUE;//字体颜色

LCD_ShowString(60,0,300,24,24,"MODE: ADC-DMA");

LCD_ShowString(60,300,300,24,24,"ADC_CH0_VAL:");       

LCD_ShowString(60,350,300,24,24,"ADC_CH0_VOL:0.000V");

POINT_COLOR=RED;

    MYDMA_Config(DMA1_Channel1,(u32)&ADC1->DR, (u32)&SendBuff,1);//配置说明见上

 

    DMA_Cmd(DMA1_Channel1, ENABLE); //开启DMA通道

while(1)

{

 

 

    adcx = MYGet_Adc();//»ñÈ¡DMAÊý¾Ý

 

LCD_ShowxNum(204,300,adcx,4,24,0);//直接读取的值

temp=(float)adcx*(3.3/4096);

adcx=temp;

LCD_ShowxNum(204,350,adcx,1,24,0);//转化为电压

temp-=adcx;

temp*=1000;

LCD_ShowxNum(228,350,temp,3,24,0X80);

LED1 = ~LED1;//提示程序正常运行

delay_ms(250);

 

}

}

 


可能出现的问题:

数据错位:可能是DMA启动在ADC之前,而你设置存储器主动加一,那数据自然错位

数据残缺:配置DMA时设置错误,一定要仔细

                 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord  ;  //16位!!!特别注意

                 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord  ; //16位!!!特别注意


ADC读了一次就不读了:ADC配置循环ENABLE即可

后记:

参数的理解是第一位,不能只看别人的代码复制过来,要自己去明白理解才行。

推荐阅读

史海拾趣

Anderson Power Products公司的发展小趣事

Anderson Power Products(APP)是一家专注于电源连接器和配件的制造商,以下是该公司发展的相关故事:

  1. 公司成立与初期阶段:Anderson Power Products成立于1936年,总部位于美国华盛顿州斯特林。最初,公司主要从事电源连接器的制造和销售。创始人是William M. Anderson和Harold J. McKenzie,他们致力于提供高质量、可靠的连接器产品,以满足不断增长的市场需求。

  2. 技术创新与产品发展:随着市场的不断变化和技术的进步,Anderson Power Products不断进行技术创新和产品开发。公司推出了一系列新型的电源连接器和配件产品,包括Powerpole®连接器、SB®连接器等,这些产品具有高功率密度、高可靠性和易用性的特点,得到了广大客户的青睐。

  3. 客户合作与市场拓展:Anderson Power Products与全球各个行业的客户建立了长期稳定的合作关系。公司的客户群涵盖了汽车、航空航天、工业、能源等多个领域。通过与客户的紧密合作,Anderson Power Products不断拓展市场份额,提升品牌知名度,成为电源连接器领域的领先供应商之一。

  4. 全球布局与生产基地:为了更好地服务全球客户,Anderson Power Products在全球建立了多个生产基地和销售办事处。除了在美国的总部外,公司还在欧洲、亚洲等地区设立了生产工厂和销售办事处,以满足不同地区客户的需求。这些生产基地拥有先进的设备和技术,能够为客户提供高质量的连接器产品。

  5. 持续创新与未来展望:作为一家专注于电源连接器的公司,Anderson Power Products将继续致力于技术创新和产品发展。公司将不断推出适应市场需求的新产品,提升生产效率和产品质量,以满足客户不断变化的需求。同时,Anderson Power Products也将继续关注行业的发展趋势和技术变革,不断调整战略,保持在行业内的竞争优势。

Frequency Management International公司的发展小趣事

随着业务的不断发展,FMI开始积极拓展国内外市场。公司凭借高品质的产品和专业的服务,赢得了众多客户的信赖和支持。同时,FMI还积极实施国际化战略,通过参加国际展会、建立海外销售网络等方式,不断提升品牌国际影响力。目前,FMI的产品已经广泛应用于计算机外设、工业仪器、局域网/广域网、光网络、过程控制、电信和无线产品等多个领域,并远销全球多个国家和地区。

EWC Controls公司的发展小趣事

EWC Controls公司非常重视人才培养和团队建设。公司建立了一套完善的人才培养体系,通过内部培训、外部引进等方式吸引和培养了一批高素质的人才。同时,公司还注重团队合作和文化建设,鼓励员工之间的交流和合作,营造了积极向上的工作氛围。这种人才培养和团队建设的策略为公司的发展提供了有力的保障。

启英泰伦(Chiplntelli)公司的发展小趣事

启英泰伦(Chiplntelli)公司成立于2015年,专注于人工智能语音芯片及配套应用解决方案的研发。在公司创立初期,团队面临了众多技术挑战和市场竞争。然而,他们凭借对技术的深刻理解和不懈追求,成功推出了第一代深度神经网络语音AI芯片CI1006,这款芯片在行业内被认定为首创。这一重要里程碑为启英泰伦的发展奠定了坚实的基础,也标志着公司在人工智能语音芯片领域的正式起步。

BAE Systems公司的发展小趣事

BAE Systems公司一直致力于技术创新,不断推动电子行业的发展。公司投入大量资源进行研发,开发出了一系列先进的电子系统和产品。这些技术成果不仅提升了公司的竞争力,也为全球电子行业的技术进步做出了贡献。例如,公司在军事通信、雷达系统、导弹技术等领域都取得了重要的突破,为国家的安全和防御提供了强有力的支持。

ABC [ABC Taiwan Electronics Corp]公司的发展小趣事

ABC Taiwan Electronics Corp成立于上世纪八十年代,起初只是一个小型电子零件加工厂。面对激烈的市场竞争和有限的资源,公司创始人凭借对电子技术的深刻理解和敏锐的市场洞察力,带领团队不断研发新产品,逐步赢得了客户的信任。通过不断积累经验和扩大规模,ABC逐渐在电子零件加工领域站稳了脚跟。

问答坊 | AI 解惑

寻求电子领域创业伙伴

本人来深圳已有8年,一直从事电子工程师一职,曾经从CD/MP3一直做到现在PMP/高清播放器等,对产品设计开发/生产制作熟练,现寻找有一定客户能力,愿意创业的工程师或销售精英一起创业(工控,单片机,电子数码,音/视频播放器,ARM/DSP嵌入式产品,L ...…

查看全部问答>

2009全国大学生电子竞赛注意事项

本帖最后由 paulhyde 于 2014-9-15 08:55 编辑 2009全国大学生电子竞赛注意事项,以及前人的经验,希望对大家有用  …

查看全部问答>

招贤:电力测试仪器研师

我公司需要开发系列电力测试仪器,寻求在此开发方面有丰富经验的高级工程师合作。 可合作方式: (1)委托开发,技术合作(不限地区) (2)全职聘请 (3)兼职开发 要求: (1)3年以上电力测试仪器开发经验,精通各种单片机开发,熟练掌握模 ...…

查看全部问答>

大家指点指点这个段码式液晶的RAM映射图吧,看了很久了,未果!

段码式液晶,不是跟数码管的显示原理差不多吗,几个SEG公用一个COM,但是数码管有共阴极共阳极之分,这个段码式的液晶也一样有吗,望知道的大侠们,指点指点,也不用什么太复杂的原理,比如说,我要点亮COM7上的SEG0,和COM0上的SEG0, 又或是其他 ...…

查看全部问答>

第九届电源技术研讨会暨展示会有人参加不

从2002年起,电源技术专题研讨会已经连续成功举办了八届,涵盖了电源产品的各个方面,为工程师提供了有关电源的前沿资讯,为国内外电源生产商及相关产品技术供应商搭建了一个展示产品和交流最新技术的平台,已经成为连接厂商和用户的最佳桥梁。在厂 ...…

查看全部问答>

算是建议吧

其实每次的diy活动都是很有意思和有意义的,只不过参与的朋友没那么广阔而已。但令我感到遗憾的是,每期的diy活动结束后,好像就杳无音信了。其实我们可以将比较成功的diy形成一套比较完善的项目。比如整理一下diy产品的资料,形成课件。成型的diy ...…

查看全部问答>

quartus10.0 软件存在的几个问题,郁闷,新软件还是不要乱用

以前一直用是用7.0,感觉很好用,没有发现什么问题,但它不支持cyclone 3系列芯片,所以改用10.0,我在ubuntu系统和windows XP下都装了它,在两个系统下都有些问题:     ubuntu9.04下:     1、SOPC系统中不能生成almemdd ...…

查看全部问答>

电源电路中功率MOS管的设计参数优化及器件选择

     电源通常后面带有较大的电容,可限制电容在充电过程中产生的浪涌电流,以保护后面所带的负载芯片的安全。因此,在这些不同电压的多路电源主回路中通常插入由功率MOS管分立元件组成的负载开关电路。电路中功率MOS管有很长 ...…

查看全部问答>

四种形式的电压跟随器

第4种是2,3种的结合。 第2种是反馈限流:这种处理需不需要,哪种场合需要? 第3种是平衡正向端和反相端的电阻。 以上4种形式分别用在哪种场合,比如需要驱动电流大的情况下或者高精度的情况下? 以上4种形式对运放的选择上有什么讲究?…

查看全部问答>