X
首页
技术
模拟电子
单片机
半导体
电源管理
嵌入式
传感器
最能打国产芯
应用
汽车电子
工业控制
家用电子
手机便携
安防电子
医疗电子
网络通信
测试测量
物联网
最能打国产芯
大学堂
首页
直播
专题
TI 培训
论坛
汽车电子
国产芯片
电机驱动控制
电源技术
单片机
模拟电子
PCB设计
电子竞赛
DIY/开源
嵌入式系统
医疗电子
颁奖专区
【厂商专区】
【电子技术】
【创意与实践】
【行业应用】
【休息一下】
最能打国产芯
活动中心
直播
发现活动
颁奖区
电子头条
参考设计
下载中心
分类资源
文集
排行榜
电路图
Datasheet
最能打国产芯
国产芯片交流
[MCU] 【极海APM32F4xx Tiny】学习笔记09-串口DMA接收数据
chejia12
2023-7-7 23:09
楼主
# 【极海APM32F4xx Tiny】学习笔记09-串口DMA接收数据 1. 一共有两个 DMA 控制器,共 16 个数据流。每个数据流对应 8 个通道,但每 个数据流同一时刻只能使用 1 个通道。每个数据流可设置优先级,仲裁器可根据 数据流的优先级协调各个数据流对应的 DMA 请求的优先级 2. 每个数据流都有 5 个事件标志和独立中断
3. 第一阶段软件阶段分为最高、高、中等和低四个优先级;第二阶段硬件 阶段,在软件优先级相同的情况下,数据流编号越低优先级越高 4. FIFO 用来在源数据传输到目标地址之前临时存放数据,每个数据流都有 1 个独 立的 4 字 FIFO,可通过软件来控制 FIFO 阈值为 1/4、1/2、3/4 或满 这里由表格得到串口1的接收dma是**dma2的数据流2的通道4**,或者是**dma2的数据流5的通道4** ## 自己的实例函数 ### 头文件 ```c #ifndef __BSP_USART_IT_H #include "bsp_delay.h" #include "apm32f4xx.h" #include "apm32f4xx_gpio.h" #include "apm32f4xx_eint.h" #include "apm32f4xx_rcm.h" #include "apm32f4xx_syscfg.h" #include "apm32f4xx_misc.h" #include "apm32f4xx_usart.h" #define RX_BUFF_SIZE 256 typedef enum { UART_1, UART_2, UART_NUM }em_uart_id; void bsp_uart_send_data(em_uart_id id,uint8_t *dat, uint32_t count); void bsp_uart_it_init_all(void); void bsp_uart_recv_data(em_uart_id id,uint8_t *dat, uint32_t *count); void bsp_uart_dma_send_data(em_uart_id id, uint8_t *buff,uint32_t len); #endif ``` ### 源文件 ```c /* Includes */ #include "../usart_it/bsp_uart_it.h" #include
#include "apm32f4xx_dma.h" #define min(num0,num1) (num0>num1?num1:num0) typedef struct { DMA_T *dma;//哪一个dma外设 DMA_Stream_T *dma_stream; //dma数据流 DMA_CHANNEL_T ch;//dma通道 IRQn_Type irq;//dma对应的通道 } dma_t; static dma_t dmas[UART_NUM]= { {DMA2,DMA2_Stream5,DMA_CHANNEL_4, DMA2_STR5_IRQn}, }; typedef struct { GPIO_T *tx_gpio_grp; GPIO_PIN_T tx_pin; uint32_t tx_rcc; GPIO_PIN_SOURCE_T tx_pin_source; GPIO_T *rx_gpio_grp; GPIO_PIN_T rx_pin; uint32_t rx_rcc; GPIO_PIN_SOURCE_T rx_pin_source; GPIO_AF_T gpio_af; USART_T *uart; IRQn_Type irq; uint32_t uart_rcc; dma_t *pdma; // dma_t *pdma_tx; uint8_t rx_buff[RX_BUFF_SIZE]; uint8_t tx_buff[RX_BUFF_SIZE]; uint16_t rx_count; uint16_t idle; } uart_it_t; #define DATA_BUF_SIZE (32) static uart_it_t uarts_it[UART_NUM]= { { GPIOA,GPIO_PIN_9,RCM_AHB1_PERIPH_GPIOA,GPIO_PIN_SOURCE_9, GPIOA,GPIO_PIN_10,RCM_AHB1_PERIPH_GPIOA,GPIO_PIN_SOURCE_10,GPIO_AF_USART1, USART1,USART1_IRQn,RCM_APB2_PERIPH_USART1,dmas+0, }, { GPIOA,GPIO_PIN_2,RCM_AHB1_PERIPH_GPIOA,GPIO_PIN_SOURCE_2, GPIOA,GPIO_PIN_3,RCM_AHB1_PERIPH_GPIOA,GPIO_PIN_SOURCE_3,GPIO_AF_USART2, USART2,USART2_IRQn,RCM_APB1_PERIPH_USART2,0, }, }; static void bsp_uart_dma_config(uart_it_t *puart, dma_t* pdma) { /* Configure USART DMA*/ //RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_DMA2); if(pdma->dma==DMA2) { RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_DMA2); } else { RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_DMA1); } DMA_Config_T dmaConfigStruct; dmaConfigStruct.bufferSize = DATA_BUF_SIZE; dmaConfigStruct.fifoMode = DMA_FIFOMODE_DISABLE; dmaConfigStruct.fifoThreshold = DMA_FIFOTHRESHOLD_QUARTER; dmaConfigStruct.memoryBurst = DMA_MEMORYBURST_SINGLE; dmaConfigStruct.memoryDataSize = DMA_MEMORY_DATA_SIZE_BYTE; dmaConfigStruct.memoryInc = DMA_MEMORY_INC_ENABLE; dmaConfigStruct.loopMode = DMA_MODE_CIRCULAR; dmaConfigStruct.peripheralBaseAddr=(uint32_t) &(puart->uart->DATA) ; //(uint32_t) (&(USART1->DATA)); dmaConfigStruct.peripheralBurst = DMA_PERIPHERALBURST_SINGLE; dmaConfigStruct.peripheralDataSize= DMA_PERIPHERAL_DATA_SIZE_BYTE; dmaConfigStruct.peripheralInc = DMA_PERIPHERAL_INC_DISABLE; dmaConfigStruct.priority = DMA_PRIORITY_HIGH; // /* 串口发送dma DMA*/ // dmaConfigStruct.channel = DMA_CHANNEL_4; // dmaConfigStruct.dir = DMA_DIR_MEMORYTOPERIPHERAL; // dmaConfigStruct.memoryBaseAddr = (uint32_t)tx_buff; // DMA_Config(DMA2_Stream7, &dmaConfigStruct); /* USART RX DMA*/ dmaConfigStruct.channel = pdma->ch;// DMA_CHANNEL_4; dmaConfigStruct.dir = DMA_DIR_PERIPHERALTOMEMORY; dmaConfigStruct.memoryBaseAddr = (uint32_t)puart->rx_buff; DMA_Config(pdma->dma_stream, &dmaConfigStruct);// DMA_Config(DMA2_Stream5, &dmaConfigStruct); DMA_Enable(pdma->dma_stream); USART_EnableDMA(puart->uart,USART_DMA_RX); DMA_EnableInterrupt(pdma->dma_stream,DMA_INT_TCIFLG); NVIC_EnableIRQRequest(pdma->irq,1,0);//DMA2_STR5_IRQn } static void bsp_uart_dma_send_config(uart_it_t *puart, dma_t* pdma) { /* Configure USART DMA*/ //RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_DMA2); if(pdma->dma==DMA2) { RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_DMA2); } else { RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_DMA1); } DMA_Config_T dmaConfigStruct; dmaConfigStruct.bufferSize = DATA_BUF_SIZE; dmaConfigStruct.fifoMode = DMA_FIFOMODE_DISABLE; dmaConfigStruct.fifoThreshold = DMA_FIFOTHRESHOLD_QUARTER; dmaConfigStruct.memoryBurst = DMA_MEMORYBURST_SINGLE; dmaConfigStruct.memoryDataSize = DMA_MEMORY_DATA_SIZE_BYTE; dmaConfigStruct.memoryInc = DMA_MEMORY_INC_ENABLE; dmaConfigStruct.loopMode = DMA_MODE_NORMAL;//这里使用普通方式 dmaConfigStruct.peripheralBaseAddr=(uint32_t) &(puart->uart->DATA) ; dmaConfigStruct.peripheralBurst = DMA_PERIPHERALBURST_SINGLE; dmaConfigStruct.peripheralDataSize= DMA_PERIPHERAL_DATA_SIZE_BYTE; dmaConfigStruct.peripheralInc = DMA_PERIPHERAL_INC_DISABLE; dmaConfigStruct.priority = DMA_PRIORITY_HIGH; /* 串口发送dma DMA*/ dmaConfigStruct.channel = pdma->ch; dmaConfigStruct.dir = DMA_DIR_MEMORYTOPERIPHERAL;//这里传输方向不一样 dmaConfigStruct.memoryBaseAddr = (uint32_t)puart->tx_buff; DMA_Config(DMA2_Stream7, &dmaConfigStruct); USART_EnableDMA(puart->uart,USART_DMA_TX);//这里是发送 // 这里的中断可以不开启 // DMA_EnableInterrupt(pdma->dma_stream,DMA_INT_TCIFLG); // NVIC_EnableIRQRequest(pdma->irq,1,0);// } /* dma数据发送 */ void bsp_uart_dma_send_data(em_uart_id id, uint8_t *buff,uint32_t len) { uart_it_t *puart; if(UART_NUM>id) { puart = uarts_it+id; memcpy(puart->tx_buff,buff,min(len,DATA_BUF_SIZE)); DMA_ConfigDataNumber(puart->pdma->dma_stream,min(len,DATA_BUF_SIZE)); DMA_Enable(puart->pdma->dma_stream); } } static void bsp_uart_it_config(uart_it_t *puart) { USART_Config_T usartConfigStruct; usartConfigStruct.baudRate = 115200; usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE; usartConfigStruct.mode = USART_MODE_TX_RX; usartConfigStruct.parity = USART_PARITY_NONE; usartConfigStruct.stopBits = USART_STOP_BIT_1; usartConfigStruct.wordLength = USART_WORD_LEN_8B; if (puart->uart == USART1 || puart->uart == USART6) { RCM_EnableAPB2PeriphClock(puart->uart_rcc); } else { RCM_EnableAPB1PeriphClock(puart->uart_rcc); } /** USART configuration */ USART_Config(puart->uart, &usartConfigStruct); /** 使能串口的接收和空闲中断 */ if(!puart->pdma) { USART_EnableInterrupt(puart->uart, USART_INT_RXBNE); } USART_EnableInterrupt(puart->uart,USART_INT_IDLE); USART_ClearStatusFlag(puart->uart, USART_FLAG_RXBNE); NVIC_EnableIRQRequest(puart->irq,1,0); if(puart->pdma) { bsp_uart_dma_config(puart,puart->pdma); } /** Enable USART */ USART_Enable(puart->uart); } void DMA2_STR5_IRQHandler() { volatile int len=0; if(DMA_ReadIntFlag(DMA2_Stream5,DMA_INT_TCIFLG5)) { DMA_ClearIntFlag(DMA2_Stream5,DMA_INT_TCIFLG5); len = DMA_ReadDataNumber (DMA2_Stream5); } } static void bsp_uart_it_gpio_config(uart_it_t *puart) { GPIO_Config_T GPIO_configStruct; GPIO_ConfigStructInit(&GPIO_configStruct); /** 使能gpio的rcc*/ RCM_EnableAHB1PeriphClock(puart->tx_rcc|puart->rx_rcc ); /** Connect PXx to USARTx_Tx */ GPIO_ConfigPinAF(puart->tx_gpio_grp, puart->tx_pin_source, puart->gpio_af); /** Connect PXx to USARTx_Rx */ GPIO_ConfigPinAF(puart->rx_gpio_grp, puart->rx_pin_source, puart->gpio_af); /** Configure USART Tx as alternate function push-pull */ GPIO_configStruct.mode = GPIO_MODE_AF; GPIO_configStruct.pin = puart->tx_pin; GPIO_configStruct.speed = GPIO_SPEED_50MHz; GPIO_Config(puart->tx_gpio_grp, &GPIO_configStruct); /** Configure USART Rx as input floating */ GPIO_configStruct.mode = GPIO_MODE_AF; GPIO_configStruct.pin = puart->rx_pin; GPIO_Config(puart->rx_gpio_grp, &GPIO_configStruct); } void bsp_uart_it_init_all(void) { for(int i=0; i
id) puart = uarts_it+id; while(puart && count--) { while(USART_ReadStatusFlag(puart->uart, USART_FLAG_TXBE) == RESET); USART_TxData(puart->uart, *dat++); } } void bsp_uart_recv_data(em_uart_id id,uint8_t *dat, uint32_t *count) { uart_it_t *puart; if(UART_NUM>id) puart = uarts_it+id; if(puart && dat&&count && puart->idle) { *count = min(puart->rx_count,*count); memcpy(dat, puart->rx_buff,*count); puart->rx_count=0; } else { *count=0; } } static voidbsp_uart_ira_handler(uart_it_t *puart) { if(USART_ReadIntFlag(puart->uart, USART_INT_RXBNE) == SET) { USART_ClearIntFlag(puart->uart, USART_INT_RXBNE); puart->rx_buff[puart->rx_count++%RX_BUFF_SIZE] = (uint8_t)USART_RxData(puart->uart); } else if (USART_ReadIntFlag(puart->uart, USART_INT_IDLE) == SET) { USART_ClearIntFlag(puart->uart, USART_INT_IDLE); puart->idle=1; USART_RxData(puart->uart); if(puart->pdma) { dma_t *pdma = puart->pdma; puart->rx_count = DATA_BUF_SIZE-DMA_ReadDataNumber (pdma->dma_stream); DMA_Disable(pdma->dma_stream); DMA_ConfigDataNumber(pdma->dma_stream,DATA_BUF_SIZE); DMA_Enable(pdma->dma_stream); } } } void USART1_IRQHandler(void) { bsp_uart_ira_handler(uarts_it+UART_1); } void USART2_IRQHandler(void) { //bsp_uart_ira_handler(uarts_it+UART_2); } ``` ### 使用 ```c /* Includes */ #include "main.h" #include
#include "bsp_led.h" #include "bsp_usart.h" #include "../key/bsp_button_instance.h" #include "../usart_it/bsp_uart_it.h" #include "dma/dma.h" /* Delay */ void Delay(uint32_t count); /*! * @brief Main program * * @param None * * @retval None */ int main(void) { led_init(LED0); led_init(LED1); bsp_uart_it_init_all(); printf("hello apm32\r\n"); init_key_btn(); uint8_t buff[256]; uint32_t len =256; while (1) { Delay(0x2FFFFF); led_toggle(LED0); led_toggle(LED1); key_lib_buttons_process(); len=256; bsp_uart_recv_data(UART_1,buff,&len); if(len) { for(int i=0;i
); } printf("\r\n"); } } } /*! * @brief Delay * * @param count:delay count * * @retval None */ void Delay(uint32_t count) { volatile uint32_t delay = count; while(delay--); } ```
点赞
回复评论 (2)
沙发
lugl4313820
DMA用起来就是爽。
点赞
2023-7-8 07:18
板凳
Jacktang
仲裁器可根据 数据流的优先级协调各个数据流对应的 DMA 请求的优先级
这个仲裁器原来是这个意思
点赞
2023-7-8 09:05
最新活动
是德科技有奖直播 | 应对未来高速算力芯片的设计与测试挑战
免费申请 | 上百份MPS MIE模块,免费试用还有礼!
TI 有奖直播 | 使用基于 Arm 的 AM6xA 处理器设计智能化楼宇
Follow me第二季第3期来啦!与得捷一起解锁高性能开发板【EK-RA6M5】超能力!
报名直播赢【双肩包、京东卡、水杯】| 高可靠性IGBT的新选择——安世半导体650V IGBT
30套RV1106 Linux开发板(带摄像头),邀您动手挑战边缘AI~
随便看看
大家有么有遇到这种情况??
好想买一块msp432,板子要12.99美刀,为什么运费要15美刀
汇编问题
先睹为快——EEWORLD台历和拆机工具
讨教。
【雅特力开发板 AT32F421 测评】TEST06 CFFT相关测试
【LPC54100】板子收到,第二批,吐槽晒板
那位做Telechips方案的,知道这个芯片的NAND Flash启动地址吗?
最近 飞机坠毁的怎么这么多啊
这个汽车无触点电子闪光器的各个电子元器件的参数是什么?
求wince4.2用的vivi_wince_64m_32bit
怒滴UART HUB(上)
提问
EasyARM-RT1052测评】+ 基本的物联网传输框架(结项贴)
主动卷纸机
电感上的分布电容
利用MSP430FR5969开发平台快速搭建无线照度测量系统
怎么使用Timing closure floorplan
国家统计局官员:我国居民消费率不及印度(这个……)
仿真与烧写运行区别问题?
电子工程世界版权所有
京B2-20211791
京ICP备10001474号-1
京公网安备 11010802033920号
回复
写回复
收藏
回复