回顾一下之前的单片机的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);
}
}
发送效果
接收效果: