串口使用DMA的方式进行数据收发(AT32F403A)

回顾一下之前的单片机的DMA搬运通道。

DMA是不依赖于APB1和APB2总线的,可以大大提升单片机的效率。

功能:

1.USART1使用DMA1通道1发送数据

2.USART2使用DMA1通道2接收数据

直接上代码:

usrt.c

//串口调试驱动

#include "usart.h"

#define BUFF_LEN    10

u8 usart1_send_buff[BUFF_LEN];
u8 usart1_rcv_buff[BUFF_LEN];
bool send_flag = false;
bool rcv_flag = false;


//串口1初始化函数
void usart1_init(void)
{
    gpio_init_type gpio_init_struct;
    
    crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
    
    gpio_default_para_init(&gpio_init_struct);
    //TX配置
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_9;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);
    
    //RX配置
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_10;
    gpio_init_struct.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOA, &gpio_init_struct);
    
    //配置初始化串口参数
    usart_init(USART1, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);
    //使能串口数据发送
    usart_transmitter_enable(USART1, TRUE);
    //使能串口数据接收
    usart_receiver_enable(USART1, TRUE);
    //使能DMA串口DMA发送使能
    usart_dma_transmitter_enable(USART1, TRUE);
    //使能DMA串口DMA接收使能
    usart_dma_receiver_enable(USART1, TRUE);
    //使能串口
    usart_enable(USART1, TRUE);
}
dma_init_type dma_init_struct_send;
dma_init_type dma_init_struct_rcv;
//串口DMA配置
void usart1_dma_init(void)
{
    
    //配置DMA1通道1发送
    
    //DMA1时钟使能
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    //重置DMA1通道1
    dma_reset(DMA1_CHANNEL1);
    //缺省值配置
    dma_default_para_init(&dma_init_struct_send);
    //数据长度
    dma_init_struct_send.buffer_size = BUFF_LEN;
    dma_init_struct_send.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    //映射接收地址
    dma_init_struct_send.memory_base_addr = (uint32_t)usart1_send_buff;
    //1个字节数据宽度
    dma_init_struct_send.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    //传输后地址增量开启
    dma_init_struct_send.memory_inc_enable = TRUE;
    //外围设备基地址
    dma_init_struct_send.peripheral_base_addr = (uint32_t)&USART1->dt;
    //外围设备基地址数据宽度 1字节
    dma_init_struct_send.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    //传输后地址增量不是能
    dma_init_struct_send.peripheral_inc_enable = FALSE;
    //优先级选择 中等
    dma_init_struct_send.priority = DMA_PRIORITY_MEDIUM;
    //环回模式关闭
    dma_init_struct_send.loop_mode_enable = FALSE;
    //初始化配置
    dma_init(DMA1_CHANNEL1, &dma_init_struct_send);
    //使能DMA1通道1
    dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
    //使能DMA1中断
    nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
    dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART1_TX);
    
    
    //配置DMA1通道2接收
    /* dma1 channel2 for usart2 rx configuration */
    dma_reset(DMA1_CHANNEL2);
    dma_default_para_init(&dma_init_struct_rcv);
    dma_init_struct_rcv.buffer_size = BUFF_LEN;
    dma_init_struct_rcv.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    dma_init_struct_rcv.memory_base_addr = (uint32_t)usart1_rcv_buff;
    dma_init_struct_rcv.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct_rcv.memory_inc_enable = TRUE;
    dma_init_struct_rcv.peripheral_base_addr = (uint32_t)&USART1->dt;
    dma_init_struct_rcv.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct_rcv.peripheral_inc_enable = FALSE;
    dma_init_struct_rcv.priority = DMA_PRIORITY_MEDIUM;
    dma_init_struct_rcv.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL2, &dma_init_struct_rcv);
    dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE);
    nvic_irq_enable(DMA1_Channel2_IRQn, 0, 0);
    dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_UART1_RX);
    
    //使能DMA1通道1
    dma_channel_enable(DMA1_CHANNEL1, TRUE);
    //使能DMA1通道2
    dma_channel_enable(DMA1_CHANNEL2, TRUE);
    
}

void DMA1_Channel1_IRQHandler(void)
{
  if(dma_interrupt_flag_get(DMA1_FDT1_FLAG))
  {
    send_flag = true;
    dma_flag_clear(DMA1_FDT1_FLAG);
    dma_channel_enable(DMA1_CHANNEL1, FALSE);
//    dma_init(DMA1_CHANNEL1, &dma_init_struct_send);
//    dma_channel_enable(DMA1_CHANNEL1, TRUE);
  }
}

/**
  * @brief  this function handles dma1 channel2 handler.
  * @param  none
  * @retval none
  */
void DMA1_Channel2_IRQHandler(void)
{
  if(dma_interrupt_flag_get(DMA1_FDT2_FLAG))
  {
    rcv_flag = true;
    dma_flag_clear(DMA1_FDT2_FLAG);
    dma_channel_enable(DMA1_CHANNEL2, FALSE);
    dma_init(DMA1_CHANNEL2, &dma_init_struct_rcv);
    dma_channel_enable(DMA1_CHANNEL2, TRUE);
  }
}

u8 data[BUFF_LEN] = {0x23,0x24,0x25,0x26,0xAA,0x29,0x4F,0xA3,0x63,0xB2};
//DMA数据发送
void usart1_dma_data_send(void)
{
    //while(dma_flag_get(DMA1_FDT1_FLAG) == RESET);
    dma_channel_enable(DMA1_CHANNEL1, FALSE);
    
    memcpy(usart1_send_buff, data, BUFF_LEN);
    dma_init_struct_send.buffer_size = BUFF_LEN;      // 更新数据长度
    dma_init_struct_send.memory_base_addr = (uint32_t)usart1_send_buff; // 更新地址
    
    //重新初始化DMA
    dma_init(DMA1_CHANNEL1, &dma_init_struct_send);
    dma_channel_enable(DMA1_CHANNEL1, TRUE);
}

uart.h

#ifndef _USART_H_
#define _USART_H_

#include "config.h"

void usart1_init(void);

void usart1_dma_init(void);

void usart1_dma_data_send(void);

#endif

main.c

#include "usart.h"


/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
  system_clock_config();

  at32_board_init();
  usart1_init();
  usart1_dma_init();
  dma_flag_clear(DMA1_FDT2_FLAG);
  while(1)
  {
      usart1_dma_data_send();
      delay_sec(1);
  }
}

发送效果

接收效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值