蓝桥杯国赛——第四站DMA学习与使用
学微嵌的时候就已经明白DMA的个中缘由了,但是一直没在板子上尝试过,虽然比赛使用的几率不大,但是还是想做一下。
网上各种轮询、中断、空闲中断,看的我头疼,不想拓展,就试试dma吧。
目的:完成ADC、Usart的DMA传输
特性:
1.两个DMA设备,各8条通道
2.外设到内存,内存到外设,内存到内存和外设到外设的数据传输
3.访问作为源和目的的片上存储器映射设备,如闪存,SRAM, AHB和APB外设
4.所有DMA通道均可独立配置
5.目的地址和源地址要对齐,数据大小则是相互独立的
6.每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求;
指针增量:
如果启用了增量模式(PINC或MINC设置为1),则下一个传输的地址是前一个传输的地址增加1、2或4,这取决于PSIZE[1:0]或MSIZE[1:0]中定义的数据大小。第一个传输地址是在DMA_CPARx或DMA_CMARx寄存器中编程的地址。在传输过程中,这些寄存器保留最初编程的值。当前的传输地址(在当前内部外设/内存地址寄存器中)是不能被软件访问的。
在循环模式下,在最后一次数据传输之后,DMA_CNDTRx寄存器会自动重新加载初始编程值。当前的内部地址寄存器用来自DMA_CPARx和DMA_CMARx寄存器的基址值重新加载。
ADC_DMA
CubeMx配置
ADC1采用正常的读写方式,我习惯配置异步分频2(图中没显示);采用周期640(max);
ADC2采用DMA方式(说实话,我没怎么搞懂,就是这个adc的dma我没有进入dma的中断,而是不断cycle,循环读adc并存,然后读出来)
不知道这样的方式adc是一直采样还是怎么?dma是一直能获取总线还是怎么?
ADC2主要是把连续采样和dma连续请求打开;
然后额外配置dma的通道:
采用半字:因为adc是16位精度,虽然库函数都是32bit,但是高位都是保留的,没有数据。
模式选择循环,保证持续请求。方向选择外设到mem,优先级随意。(dma通道这里显示channel 1 ,但是keil打开cube生产的,显示是channel 11 ?Amazing ! )
代码:
/*ADC.c和ADC.h直接用生产的工程就可以。为ADC1添加一个读即可:
/*main.c写点东西就行,然后什么it.c和dma.c都没动;
/*******adc.c******/ /*******END*********/ uint16_t Get_ADC1(void) { uint16_t a; HAL_ADC_Start(&hadc1); a = HAL_ADC_GetValue(&hadc1); return a; }/* Includes ------------------------------------------------------------------*/#include "main.h"#include "adc.h"
#include "dma.h" #include "usart.h" #include "gpio.h" #include "lcd.h" uint16_t ADC2_Val; uint16_t ADC2_Buff[10]; void SystemClock_Config(void); void Lcd_Proc(void); int main(void) { HAL_Init(); SystemClock_Config();
MX_GPIO_Init(); MX_DMA_Init(); MX_ADC1_Init(); MX_ADC2_Init();
/*******ADC校正一下********/ HAL_ADC_Start_DMA(&hadc2,(uint32_t*)&ADC2_Buff,10); MX_USART1_UART_Init(); LCD_Init(); LCD_Clear(Black); LCD_SetBackColor(Black); LCD_SetTextColor(White); while (1) {
Lcd_Proc(); } } void Lcd_Proc(void) { for(uint8_t i=0;i<10;i++) { ADC2_Val += ADC2_Buff[i]; } /****显示这个数值——Get_ADC1()*3.3/4095)*****/
/****显示这个数值——ADC2_Val*3.3/4095/10*****/
ADC2_Val = 0;
}
最后这个地方,说起来还闹了乌龙,就是dma格式读取的值显示出来只有一半,也就是3.3/2;
结果网上正好也有相关的情况,我就对照了找了好久bug,结果发现是学习别人博客里面dma设置的时候有个很简单的代码bug,啊啊啊!
tip:大家看我的代码学习就好,真的有可能误事,请您抱着批判的态度来!感谢!
Usart_DMA:IDLE空闲中断和单纯的dma收发数据两种。
感兴趣的可以参考下面的链接文章,折腾了两天,不想搞了。(基本完成指标了,但是后面不想移植到国赛使用,感觉作用不大,就先不更了)
(6条消息) STM32CUBEMX配置教程(九)STM32串口DMA收发数据_怡步晓心rui的博客-CSDN博客_stm32的pa9和pa10怎么接串口
(6条消息) STM32_HAL库_CubeMx串口DMA通信(DMA发送+DMA空闲接收不定长数据)_何为其然的博客-CSDN博客_hal库串口dma接收
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了