1、访问串口设备接口
1.1 应用程序通过RT-Thread提供的IO设备管理接口来访问串口硬件:
1.2 查找串口设备(例:”uart2”)
1.3 打开串口设备(串口收发数据模式:中断、轮询、DMA)
1.4 控制串口设备
rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg);
cmd 命令控制字,可取值:RT_DEVICE_CTRL_CONFIG
arg 控制的参数,可取类型:struct serial_conigure
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 :4;
};
/* 波特率可取值*/
#define BAUD_RATE_2400 2400
#define BAUD_RATE_4800 4800
#define BAUD_RATE_9600 9600
#define BAUD_RATE_19200 19200
#define BAUD_RATE_38400 38400
#define BAUD_RATE_57600 57600
#define BAUD_RATE_115200 115200
#define BAUD_RATE_230400 230400
#define BAUD_RATE_460800 460800
#define BAUD_RATE_921600 921600
#define BAUD_RATE_2000000 2000000
#define BAUD_RATE_3000000 3000000
/* 数据位可取值*/
#define DATA_BITS_5 5
#define DATA_BITS_6 6
#define DATA_BITS_7 7
#define DATA_BITS_8 8
#define DATA_BITS_9 9
/*停止位可取值 */
#define STOP_BITS_1 0
#define STOP_BITS_2 1
#define STOP_BITS_3 2
#define STOP_BITS_4 3
/*极性位可取值*/
#define PARITY_NONE 0
#define PARITY_ODD 1
#define PARITY_EVEN 2
/* 高低位顺序可取值*/
#define BIT_ORDER_LSB 0
#define BIT_ORDER_MSB 1
/*模式可取值*/
#define NRZ_NORMAL 0 /* normal mode */
#define NRZ_INVERTED 1 /* inverted mode */
/* 接收数据缓冲区默认大小*/
#define RT_SERIAL_RB_BUFSZ 64
RT-Thread 提供的默认串口配置
#define RT_SERIAL_CONFIG_DEFAULT \
{ \
BAUD_RATE_115200, /* 115200 bits/s */ \
DATA_BITS_8, /* 8 databits */ \
STOP_BITS_1, /* 1 stopbit */ \
PARITY_NONE, /* No parity */ \
BIT_ORDER_LSB, /* LSB first sent */ \
NRZ_NORMAL, /* Normal mode */ \
RT_SERIAL_RB_BUFSZ, /* Buffer size */ \
0 \
}
注:缓冲区通过 control 接口修改,缓冲区大小无法动态改变,只有在 open 设备之前可以配置。open 设备之后,缓冲区大小不可再进行更改。但除过缓冲区之外的其他参数,在 open 设备前 / 后,均可进行更改。
1.5 发送数据
1.6 设置发送完成回调函数
在应用程序调用 rt_device_write()写入数据时,如果底层硬件能够支持自动发送,那么上层应用可以设置一个回调函数。这个回调函数会在底层硬件数据发送完成后 (例如 DMA 传送完成或 FIFO 已经写入完毕产生完成中断时) 调用
1.7 设置接收回调函数
若串口以中断接收模式打开,当串口接收到一个数据产生中断时,就会调用回调函数,并且会把此时缓冲区的数据大小放在size参数里,把串口设备句柄放在dev参数里供调用者获取。
若串口以 DMA 接收模式打开,当 DMA 完成一批数据的接收后会调用此回调函数。
使用:一般情况下接收回调函数可以发送一个信号量或者事件通知串口数据处理线程有数据到达
1.8 接收数据
1.9 关闭串口设备
rt_err_t rt_device_close(rt_device_t dev);
2、串口案例
2.1 中断
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-08-27 RT-Thread first version
*/
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <serial.h>
rt_device_t u1_dev;
struct rt_semaphore sem;
rt_thread_t u1_th;
struct serial_configure u1_configs = RT_SERIAL_CONFIG_DEFAULT;
rt_err_t rx_callback(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&sem);
return RT_EOK;
}
void serial_thread_entry(void *parameter)
{
char buffer;
while(1){
while(rt_device_read(u1_dev, 0, &buffer, 1) != 1){
rt_sem_take(&sem, RT_WAITING_FOREVER);
}
rt_kprintf("%c",buffer);
}
}
int main(void)
{
rt_err_t ret = 0;
u1_dev = rt_device_find("uart1");
if(u1_dev == RT_NULL){
LOG_E("rt_device_find[uart1] failed...\n");
return -EINVAL;
}
ret = rt_device_open(u1_dev, RT_DEVICE_OFLAG_RDWR|RT_DEVICE_FLAG_INT_RX);
if(ret < 0){
LOG_E("rt_device_open[uart1] failed...\n");
return ret;
}
rt_device_control(u1_dev, RT_DEVICE_CTRL_CONFIG, (void *)&u1_configs);
rt_device_set_rx_indicate(u1_dev, rx_callback);
rt_sem_init(&sem,"rx_sem", 0, RT_IPC_FLAG_FIFO);
u1_th = rt_thread_create("u1_recv",serial_thread_entry , NULL, 1024, 10, 5);
rt_thread_startup(u1_th);
rt_device_write(u1_dev, 0, "Uart1 config...\n", rt_strlen("Uart1 config...\n"));
return RT_EOK;
}
2.2 DMA
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-08-27 RT-Thread first version
*/
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <serial.h>
rt_device_t u1_dev;
struct rt_semaphore sem;
rt_thread_t u1_th;
rt_size_t rx_len = 0;
struct serial_configure u1_configs = RT_SERIAL_CONFIG_DEFAULT;
rt_err_t rx_callback(rt_device_t dev, rt_size_t size)
{
rx_len = size;
rt_sem_release(&sem);
return RT_EOK;
}
void serial_thread_entry(void *parameter)
{
rt_size_t len = 0;
char buffer[512] = {0};
while(1){
rt_sem_take(&sem, RT_WAITING_FOREVER);
len = rt_device_read(u1_dev, 0, buffer, rx_len);
buffer[len] = '\0';
rt_kprintf("buffer:%s\n",buffer);
}
}
int main(void)
{
rt_err_t ret = 0;
u1_dev = rt_device_find("uart1");
if(u1_dev == RT_NULL){
LOG_E("rt_device_find[uart1] failed...\n");
return -EINVAL;
}
ret = rt_device_open(u1_dev, RT_DEVICE_FLAG_DMA_RX);
if(ret < 0){
LOG_E("rt_device_open[uart1] failed...\n");
rt_kprintf("ret : %d\n",ret);
return ret;
}
rt_device_control(u1_dev, RT_DEVICE_CTRL_CONFIG, (void *)&u1_configs);
rt_device_set_rx_indicate(u1_dev, rx_callback);
ret = rt_sem_init(&sem,"rx_sem", 0, RT_IPC_FLAG_FIFO);
if(ret < 0){
LOG_E("rt_sem_init failed[%d]...\n",ret);
return ret;
}
u1_th = rt_thread_create("u1_recv",serial_thread_entry , NULL, 1024, 10, 5);
rt_thread_startup(u1_th);
rt_device_write(u1_dev, 0, "Uart1 config...\n", rt_strlen("Uart1 config...\n"));
return RT_EOK;
}
上一篇:【RTT】IO设备模型
下一篇:C嵌入式