IDE: RT-Thread Studio v2.1.0
系统版本:v4.0.2
芯片: STM32F407VG
工程创建完成后,双击工程目录下的 RT-Thread Setting
勾选使能串口DMA模式,设置缓冲区大小,ctrl+s保存配置后自动生成代码,然后退出配置页面。
打开 drivers/board.h ,按图示添加代码,引脚配置根据图示自行修改。
新建一对 uartdma.c && uartdma.h文件,在 uartdma.h中添加 Uart类定义,并声明UART1 和UART2对象。
#include "board.h"
typedef struct Uart
{
rt_device_t serial;
rt_mailbox_t mb;
rt_size_t (*send)(char *, rt_size_t);
rt_size_t (*recv)(char *, rt_int32_t);
rt_err_t (*input)(rt_device_t, rt_size_t);
int (*init)(uint32_t);
} Uart;
#ifdef BSP_UART1_RX_USING_DMA
extern Uart UART1;
#endif
#ifdef BSP_UART2_RX_USING_DMA
extern Uart UART2;
#endif
在 uartdma.c 中添加代码
#include "rtthread.h"
#include "uartdma.h"
#define RT_SERIAL_CONFIG_DEFAULT \
{ \
115200, /* 115200 bits/s */ \
8, /* 8 databits */ \
0, /* 1 stopbit */ \
0, /* No parity */ \
0, /* LSB first sent */ \
0, /* Normal mode */ \
256, /* Buffer size */ \
0 \
}
struct serial_configure
{
rt_uint32_t baud_rate;
rt_uint32_t data_bits :4;
rt_uint32_t stop_bits :2;
rt_uint32_t parity :2;
rt_uint32_t bit_order :1;
rt_uint32_t invert :1;
rt_uint32_t bufsz :16;
rt_uint32_t reserved :6;
};
#ifdef BSP_UART1_RX_USING_DMA
#define UART1_NAME "uart1" /* 串口设备名称 */
static rt_size_t uart1_send(char *data, rt_size_t size);
static rt_size_t uart1_recv(char *buffer, rt_int32_t timeout);
static rt_err_t uart1_input(rt_device_t dev, rt_size_t size);
static int uart1_init(uint32_t baud_rate);
Uart UART1 = {
RT_NULL,
RT_NULL, uart1_send, uart1_recv, uart1_input, uart1_init };
static rt_size_t uart1_send(char *data, rt_size_t size)
{
return rt_device_write(UART1.serial, 0, data, size);
}
static rt_size_t uart1_recv(char *buffer, rt_int32_t timeout)
{
rt_size_t len;
if (rt_mb_recv(UART1.mb, &len, timeout) != RT_EOK)
{
return 0;
}
len = rt_device_read(UART1.serial, 0, buffer, len);
return len;
}
/* 接收数据回调函数 */
static rt_err_t uart1_input(rt_device_t dev, rt_size_t size)
{
/* 发送邮件 */
return rt_mb_send(UART1.mb, size);
}
static int uart1_init(uint32_t baud_rate)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */
UART1.serial = rt_device_find(UART1_NAME);
if (!UART1.serial)
{
rt_kprintf("find %s failed!\n", UART1_NAME);
return RT_ERROR;
}
if (UART1.mb == RT_NULL)
{
UART1.mb = rt_mb_create("uart1_mb", 1, RT_IPC_FLAG_FIFO);
if (UART1.mb == RT_NULL)
{
return RT_ERROR;
}
}
/* step2:修改串口配置参数 */
config.baud_rate = baud_rate; //修改波特率
/* step3:控制串口设备。通过控制接口传入命令控制字,与控制参数 */
rt_device_control(UART1.serial, RT_DEVICE_CTRL_CONFIG, &config);
rt_device_set_rx_indicate(UART1.serial, UART1.input);
rt_device_open(UART1.serial, RT_DEVICE_FLAG_DMA_RX);
return RT_EOK;
}
#endif
#ifdef BSP_UART2_RX_USING_DMA
#define UART2_NAME "uart2" /* 串口设备名称 */
static rt_size_t uart2_send(char *data, rt_size_t size);
static rt_size_t uart2_recv(char *buffer, rt_int32_t timeout);
static rt_err_t uart2_input(rt_device_t dev, rt_size_t size);
static int uart2_init(uint32_t baud_rate);
Uart UART2 = {
RT_NULL,
RT_NULL, uart2_send, uart2_recv, uart2_input, uart2_init };
static rt_size_t uart2_send(char *data, rt_size_t size)
{
return rt_device_write(UART2.serial, 0, data, size);
}
static rt_size_t uart2_recv(char *buffer, rt_int32_t timeout)
{
rt_size_t len;
if (rt_mb_recv(UART2.mb, &len, timeout) != RT_EOK)
{
return 0;
}
len = rt_device_read(UART2.serial, 0, buffer, len);
return len;
}
/* 接收数据回调函数 */
static rt_err_t uart2_input(rt_device_t dev, rt_size_t size)
{
/* 发送邮件 */
return rt_mb_send(UART2.mb, size);
}
static int uart2_init(uint32_t baud_rate)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */
UART2.serial = rt_device_find(UART2_NAME);
if (!UART2.serial)
{
rt_kprintf("find %s failed!\n", UART2_NAME);
return RT_ERROR;
}
if (UART2.mb == RT_NULL)
{
UART2.mb = rt_mb_create("uart2_mb", 1, RT_IPC_FLAG_FIFO);
if (UART2.mb == RT_NULL)
{
return RT_ERROR;
}
}
/* step2:修改串口配置参数 */
config.baud_rate = baud_rate; //修改波特率
/* step3:控制串口设备。通过控制接口传入命令控制字,与控制参数 */
rt_device_control(UART2.serial, RT_DEVICE_CTRL_CONFIG, &config);
rt_device_set_rx_indicate(UART2.serial, UART2.input);
rt_device_open(UART2.serial, RT_DEVICE_FLAG_DMA_RX);
return RT_EOK;
}
#endif
int uart_init(void)
{
#ifdef BSP_UART1_RX_USING_DMA
if (UART1.init(115200) == RT_EOK)
{
rt_kprintf("uart1 dma init successful!\r\n");
}
#endif
#ifdef BSP_UART2_RX_USING_DMA
if (UART2.init(115200) == RT_EOK)
{
rt_kprintf("uart2 dma init successful!\r\n");
}
#endif
return RT_EOK;
}
INIT_ENV_EXPORT(uart_init); /* 使用组件自动初始化机制 */
编译下载运行
之后可以在应用层线程引入 uartdma.h ,调用 UART1.recv 和 UART1.recv,或者 UART2.send 和 UART2.recv进行收发数据。
但是在使用过程中,出现接收数据断帧问题。
参考博文 https://blog.csdn.net/coderdd/article/details/108264369