赞
踩
DMA 传输必须设置传输的数据量,对应的中断也只有传输完成,半传输完成和传输错误中断,对于不定长数据的传输基本没有办法识别是否传输完成。
UART 有个 IDLE 标志,在 UART 总线上没有数据传输时,UART TX 和 RX 都会保持高电平,在识别到 RX 上连续的 10 bit (包含起始位,数据位,结束位)高电平时,会设置 IDLE 标志,当打开 IDLE 中断时即会触发 IDLE 中断。
所以,基于以上两点,可以配合 UART 的 IDLE 中断和 DMA 一起使用。
步骤:
1、AT32_Work_Bench 配置过程
2、代码编写main.c
- /* add user code begin Header */
-
- /**
-
- **************************************************************************
-
- * [url=home.php?mod=space&uid=288409]@file[/url] main.c
-
- * [url=home.php?mod=space&uid=247401]@brief[/url] main program
-
- **************************************************************************
-
- * Copyright notice & Disclaimer
-
- *
-
- * The software Board Support Package (BSP) that is made available to
-
- * download from Artery official website is the copyrighted work of Artery.
-
- * Artery authorizes customers to use, copy, and distribute the BSP
-
- * software and its related documentation for the purpose of design and
-
- * development in conjunction with Artery microcontrollers. Use of the
-
- * software is governed by this copyright notice and the following disclaimer.
-
- *
-
- * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
-
- * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
-
- * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
-
- * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
-
- * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
-
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
-
- *
-
- **************************************************************************
-
- */
-
- /* add user code end Header */
-
-
-
- /* Includes ------------------------------------------------------------------*/
-
- #include "at32f423_wk_config.h"
-
-
-
- /* private includes ----------------------------------------------------------*/
-
- /* add user code begin private includes */
-
- #include <string.h>
-
- /* add user code end private includes */
-
-
-
- /* private typedef -----------------------------------------------------------*/
-
- /* add user code begin private typedef */
-
-
-
- /* add user code end private typedef */
-
-
-
- /* private define ------------------------------------------------------------*/
-
- /* add user code begin private define */
-
-
-
- /* add user code end private define */
-
-
-
- /* private macro -------------------------------------------------------------*/
-
- /* add user code begin private macro */
-
- #define MS_TICK (system_core_clock / 8 / 1000U)
-
- #define TX_BUF_SIZE 100
-
- #define RX_BUF_SIZE 100
-
- /* add user code end private macro */
-
-
-
- /* private variables ---------------------------------------------------------*/
-
- /* add user code begin private variables */
-
- static volatile uint32_t sys_tick;
-
- uint8_t tx_buf[TX_BUF_SIZE]; /* uart 发送缓冲区 */
-
- volatile uint16_t tx_len; /* uart 实际发送数据长度 */
-
- volatile uint8_t tx_flag; /* uart 发送繁忙标志 */
-
- uint8_t rx_buf[RX_BUF_SIZE]; /* uart 接收缓冲区 */
-
- volatile uint16_t rx_len; /* uart 实际接收数据长度 */
-
- volatile uint8_t rx_flag; /* uart 接收完成标志 */
-
- static const char *start_msg = "The demo is started!\n";
-
- /* add user code end private variables */
-
-
-
- /* private function prototypes --------------------------------------------*/
-
- /* add user code begin function prototypes */
-
-
-
- /* add user code end function prototypes */
-
-
-
- /* private user code ---------------------------------------------------------*/
-
- /* add user code begin 0 */
-
- static void systick_init(void)
-
- {
-
- SysTick_Config(MS_TICK);
-
- systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_DIV8);
-
- }
-
-
-
- static void sys_tick_increament(void)
-
- {
-
- sys_tick++;
-
- }
-
-
-
- uint32_t sys_tick_get(void)
-
- {
-
- return sys_tick;
-
- }
-
-
-
- void SysTick_Handler(void)
-
- {
-
- sys_tick_increament();
-
- }
-
- /* add user code end 0 */
-
-
-
-
-
- /**
-
- * @brief take some delay for waiting power stable, delay is about 60ms with frequency 8MHz.
-
- * @param none
-
- * @retval none
-
- */
-
- static void wk_wait_for_power_stable(void)
-
- {
-
- volatile uint32_t delay = 0;
-
- for(delay = 0; delay < 50000; delay++);
-
- }
-
-
-
- /**
-
- * @brief main function.
-
- * @param none
-
- * @retval none
-
- */
-
- int main(void)
-
- {
-
- /* add user code begin 1 */
-
- uint32_t start_tick;
-
- /* add user code end 1 */
-
-
-
- /* add a necessary delay to ensure that Vdd is higher than the operating
-
- voltage of battery powered domain (2.57V) when the battery powered
-
- domain is powered on for the first time and being operated. */
-
- wk_wait_for_power_stable();
-
-
-
- /* system clock config. */
-
- wk_system_clock_config();
-
-
-
- /* config periph clock. */
-
- wk_periph_clock_config();
-
-
-
- /* nvic config. */
-
- wk_nvic_config();
-
-
-
- /* init dma1 channel1 */
-
- wk_dma1_channel1_init();
-
- /* config dma channel transfer parameter */
-
- /* user need to modify parameters memory_base_addr and buffer_size */
-
- wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&USART1->dt, (uint32_t)rx_buf, RX_BUF_SIZE);
-
- dma_channel_enable(DMA1_CHANNEL1, TRUE);
-
-
-
- /* init dma1 channel2 */
-
- wk_dma1_channel2_init();
-
- /* config dma channel transfer parameter */
-
- /* user need to modify parameters memory_base_addr and buffer_size */
-
- wk_dma_channel_config(DMA1_CHANNEL2, (uint32_t)&USART1->dt, (uint32_t)start_msg, strlen(start_msg));
-
- dma_channel_enable(DMA1_CHANNEL2, TRUE);
-
-
-
- /* init usart1 function. */
-
- wk_usart1_init();
-
-
-
- /* init gpio function. */
-
- wk_gpio_config();
-
-
-
- /* add user code begin 2 */
-
- systick_init();
-
-
-
- dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE); /* 打开 dma 发送完成中断 */
-
-
-
- rx_len = RX_BUF_SIZE; /* 设置接收的最大长度 */
-
- dma_flag_clear(DMA1_FDT1_FLAG); /* 清除 uart dma 传输完成标志 */
-
- usart_flag_clear(USART1, USART_IDLEF_FLAG); /* 清除空闲中断标志 */
-
- dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE); /* 打开 uart dma 接收完成中断 */
-
- usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE); /* 打开 uart 空闲中断 */
-
-
-
- start_tick = sys_tick_get();
-
- /* add user code end 2 */
-
-
-
- while(1)
-
- {
-
- /* add user code begin 3 */
-
- if (rx_flag) {
-
- rx_flag = 0;
-
-
-
- while (tx_flag == 0); /* 等待发送就绪 */
-
-
-
- if (rx_len) {
-
- memcpy(tx_buf, rx_buf, rx_len); /* 拷贝接收数据 */
-
- /* 配置 DMA 发送*/
-
- wk_dma_channel_config(DMA1_CHANNEL2, (uint32_t)&USART1->dt, (uint32_t)tx_buf, rx_len);
-
- dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE); /* 打开 dma 发送完成中断 */
-
- dma_channel_enable(DMA1_CHANNEL2, TRUE); /* 启动 dma 通道传输 */
-
- tx_flag = 0; /* 设置发送繁忙标志 */
-
- }
-
- // else {
-
- // while (1);
-
- // }
-
-
-
- /* 重新启动 uart dma 接收 */
-
- dma_flag_clear(DMA1_FDT1_FLAG); /* 清除 uart dma 传输完成标志 */
-
- usart_flag_clear(USART1, USART_IDLEF_FLAG); /* 清除空闲中断标志 */
-
- dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE); /* 打开 uart dma 接收完成中断 */
-
- usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE); /* 打开 uart 空闲中断 */
-
- rx_len = RX_BUF_SIZE; /* 设置接收的最大长度 */
-
- /* 重新配置 dma 接收参数 */
-
- wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&USART1->dt, (uint32_t)rx_buf, RX_BUF_SIZE);
-
- dma_channel_enable(DMA1_CHANNEL1, TRUE); /* 打开 dma 通道传输 */
-
- }
-
-
-
- if (sys_tick_get() - start_tick >= 500) { /* 每隔 500 ms 翻转一次 LED */
-
- start_tick = sys_tick_get();
-
- gpio_bits_toggle(LED2_GPIO_PORT, LED2_PIN);
-
- gpio_bits_toggle(LED3_GPIO_PORT, LED3_PIN);
-
- gpio_bits_toggle(LED4_GPIO_PORT, LED4_PIN);
-
- }
-
- /* add user code end 3 */
-
- }
-
- }
-
at32f423_int.c
- /* add user code begin Header */
-
- /**
-
- **************************************************************************
-
- * [url=home.php?mod=space&uid=288409]@file[/url] at32f423_int.c
-
- * [url=home.php?mod=space&uid=247401]@brief[/url] main interrupt service routines.
-
- **************************************************************************
-
- * Copyright notice & Disclaimer
-
- *
-
- * The software Board Support Package (BSP) that is made available to
-
- * download from Artery official website is the copyrighted work of Artery.
-
- * Artery authorizes customers to use, copy, and distribute the BSP
-
- * software and its related documentation for the purpose of design and
-
- * development in conjunction with Artery microcontrollers. Use of the
-
- * software is governed by this copyright notice and the following disclaimer.
-
- *
-
- * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
-
- * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
-
- * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
-
- * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
-
- * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
-
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
-
- *
-
- **************************************************************************
-
- */
-
- /* add user code end Header */
-
-
-
- /* includes ------------------------------------------------------------------*/
-
- #include "at32f423_int.h"
-
-
-
- /* private includes ----------------------------------------------------------*/
-
- /* add user code begin private includes */
-
-
-
- /* add user code end private includes */
-
-
-
- /* private typedef -----------------------------------------------------------*/
-
- /* add user code begin private typedef */
-
-
-
- /* add user code end private typedef */
-
-
-
- /* private define ------------------------------------------------------------*/
-
- /* add user code begin private define */
-
-
-
- /* add user code end private define */
-
-
-
- /* private macro -------------------------------------------------------------*/
-
- /* add user code begin private macro */
-
-
-
- /* add user code end private macro */
-
-
-
- /* private variables ---------------------------------------------------------*/
-
- /* add user code begin private variables */
-
-
-
- /* add user code end private variables */
-
-
-
- /* private function prototypes --------------------------------------------*/
-
- /* add user code begin function prototypes */
-
-
-
- /* add user code end function prototypes */
-
-
-
- /* private user code ---------------------------------------------------------*/
-
- /* add user code begin 0 */
-
-
-
- /* add user code end 0 */
-
-
-
- /* external variables ---------------------------------------------------------*/
-
- /* add user code begin external variables */
-
- extern volatile uint8_t tx_flag;
-
- extern volatile uint16_t rx_len;
-
- extern volatile uint8_t rx_flag;
-
- /* add user code end external variables */
-
-
-
- /**
-
- * @brief this function handles nmi exception.
-
- * @param none
-
- * @retval none
-
- */
-
- void NMI_Handler(void)
-
- {
-
- /* add user code begin NonMaskableInt_IRQ 0 */
-
-
-
- /* add user code end NonMaskableInt_IRQ 0 */
-
-
-
- /* add user code begin NonMaskableInt_IRQ 1 */
-
-
-
- /* add user code end NonMaskableInt_IRQ 1 */
-
- }
-
-
-
- /**
-
- * @brief this function handles hard fault exception.
-
- * @param none
-
- * @retval none
-
- */
-
- void HardFault_Handler(void)
-
- {
-
- /* add user code begin HardFault_IRQ 0 */
-
-
-
- /* add user code end HardFault_IRQ 0 */
-
- /* go to infinite loop when hard fault exception occurs */
-
- while (1)
-
- {
-
- /* add user code begin W1_HardFault_IRQ 0 */
-
-
-
- /* add user code end W1_HardFault_IRQ 0 */
-
- }
-
- }
-
-
-
- /**
-
- * @brief this function handles memory manage exception.
-
- * @param none
-
- * @retval none
-
- */
-
- void MemManage_Handler(void)
-
- {
-
- /* add user code begin MemoryManagement_IRQ 0 */
-
-
-
- /* add user code end MemoryManagement_IRQ 0 */
-
- /* go to infinite loop when memory manage exception occurs */
-
- while (1)
-
- {
-
- /* add user code begin W1_MemoryManagement_IRQ 0 */
-
-
-
- /* add user code end W1_MemoryManagement_IRQ 0 */
-
- }
-
- }
-
-
-
- /**
-
- * @brief this function handles bus fault exception.
-
- * @param none
-
- * @retval none
-
- */
-
- void BusFault_Handler(void)
-
- {
-
- /* add user code begin BusFault_IRQ 0 */
-
-
-
- /* add user code end BusFault_IRQ 0 */
-
- /* go to infinite loop when bus fault exception occurs */
-
- while (1)
-
- {
-
- /* add user code begin W1_BusFault_IRQ 0 */
-
-
-
- /* add user code end W1_BusFault_IRQ 0 */
-
- }
-
- }
-
-
-
- /**
-
- * @brief this function handles usage fault exception.
-
- * @param none
-
- * @retval none
-
- */
-
- void UsageFault_Handler(void)
-
- {
-
- /* add user code begin UsageFault_IRQ 0 */
-
-
-
- /* add user code end UsageFault_IRQ 0 */
-
- /* go to infinite loop when usage fault exception occurs */
-
- while (1)
-
- {
-
- /* add user code begin W1_UsageFault_IRQ 0 */
-
-
-
- /* add user code end W1_UsageFault_IRQ 0 */
-
- }
-
- }
-
-
-
- /**
-
- * @brief this function handles svcall exception.
-
- * @param none
-
- * @retval none
-
- */
-
- void SVC_Handler(void)
-
- {
-
- /* add user code begin SVCall_IRQ 0 */
-
-
-
- /* add user code end SVCall_IRQ 0 */
-
- /* add user code begin SVCall_IRQ 1 */
-
-
-
- /* add user code end SVCall_IRQ 1 */
-
- }
-
-
-
- /**
-
- * @brief this function handles debug monitor exception.
-
- * @param none
-
- * @retval none
-
- */
-
- void DebugMon_Handler(void)
-
- {
-
- /* add user code begin DebugMonitor_IRQ 0 */
-
-
-
- /* add user code end DebugMonitor_IRQ 0 */
-
- /* add user code begin DebugMonitor_IRQ 1 */
-
-
-
- /* add user code end DebugMonitor_IRQ 1 */
-
- }
-
-
-
- /**
-
- * @brief this function handles pendsv_handler exception.
-
- * @param none
-
- * @retval none
-
- */
-
- void PendSV_Handler(void)
-
- {
-
- /* add user code begin PendSV_IRQ 0 */
-
-
-
- /* add user code end PendSV_IRQ 0 */
-
- /* add user code begin PendSV_IRQ 1 */
-
-
-
- /* add user code end PendSV_IRQ 1 */
-
- }
-
-
-
- /**
-
- * @brief this function handles DMA1 Channel 1 handler.
-
- * @param none
-
- * @retval none
-
- */
-
- void DMA1_Channel1_IRQHandler(void)
-
- {
-
- /* add user code begin DMA1_Channel1_IRQ 0 */
-
- if(dma_flag_get(DMA1_FDT1_FLAG)) {
-
- rx_flag = 1; /* 标记接收到数据 */
-
-
-
- /* 关闭 dma 通道,关闭中断 */
-
- dma_channel_enable(DMA1_CHANNEL1, FALSE);
-
- dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, FALSE);
-
- usart_interrupt_enable(USART1, USART_IDLE_INT, FALSE);
-
- }
-
- /* add user code end DMA1_Channel1_IRQ 0 */
-
- /* add user code begin DMA1_Channel1_IRQ 1 */
-
-
-
- /* add user code end DMA1_Channel1_IRQ 1 */
-
- }
-
-
-
- /**
-
- * @brief this function handles DMA1 Channel 2 handler.
-
- * @param none
-
- * @retval none
-
- */
-
- void DMA1_Channel2_IRQHandler(void)
-
- {
-
- /* add user code begin DMA1_Channel2_IRQ 0 */
-
- if(dma_flag_get(DMA1_FDT2_FLAG)) {
-
- tx_flag = 1; /* 设置发送就绪 */
-
-
-
- dma_channel_enable(DMA1_CHANNEL2, FALSE); /* 关闭 dma 通道传输 */
-
- dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, FALSE); /* 关闭 dma 传输完成中断 */
-
- dma_flag_clear(DMA1_FDT2_FLAG); /* 清除传输完成标志 */
-
- }
-
- /* add user code end DMA1_Channel2_IRQ 0 */
-
- /* add user code begin DMA1_Channel2_IRQ 1 */
-
-
-
- /* add user code end DMA1_Channel2_IRQ 1 */
-
- }
-
-
-
- /**
-
- * @brief this function handles USART1 handler.
-
- * @param none
-
- * @retval none
-
- */
-
- void USART1_IRQHandler(void)
-
- {
-
- /* add user code begin USART1_IRQ 0 */
-
- if(usart_flag_get(USART1, USART_IDLEF_FLAG) != RESET)
-
- {
-
- rx_flag = 1; /* 标记接收到数据 */
-
- rx_len -= dma_data_number_get(DMA1_CHANNEL1); /* 计算实际接收到的数据长度 */
-
-
-
- /* 关闭 dma 通道,关闭中断 */
-
- dma_channel_enable(DMA1_CHANNEL1, FALSE);
-
- dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, FALSE);
-
- usart_interrupt_enable(USART1, USART_IDLE_INT, FALSE);
-
- }
-
- /* add user code end USART1_IRQ 0 */
-
- /* add user code begin USART1_IRQ 1 */
-
-
-
- /* add user code end USART1_IRQ 1 */
-
- }
-
-
-
- /* add user code begin 1 */
-
-
-
- /* add user code end 1 */
-
3、测试
可以看到,接收字节数 == 发送字节数
5.97 MB。
---------------------
作者:cuyebiren
链接:https://bbs.21ic.com/icview-3336688-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。