rtthread studio与正点原子apollo(5)--UART设备


前言

本文介绍RT-Thread中UART设备的使用,主要介绍UART的接收中断和DMA接收。


一、UART设备简介

UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。
串口通信的协议如下图所示:
在这里插入图片描述

串口线无数据传输时为空闲状态,串口线电平为高,当有数据传输时,电平由高变低,起始位占一个串口时钟,接着传递数据位,数据位长度可自定义,通常为8个位,校验位自定义,然后是停止位,数据传输完毕,串口线电平再次变为高电平即空闲状态。
串口通信的核心是配置串行数据格式及串口通信波特率即时钟。

二、RT-Thread使用UART设备

1.访问串口设备

RT-Thread中访问串口及相关API的介绍参考官方文档
UART设备

串口使用的主要步骤:
(1)定义串口设备并查找设备

#define SAMPLE_UART_NAME       "uart2"    /* 串口设备名称 */
static rt_device_t serial;                /* 串口设备句柄 */
/* 查找串口设备 */
serial = rt_device_find(SAMPLE_UART_NAME);

(2)控制串口设备

/* 初始化配置参数 */
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;  
/* 修改串口配置参数 */
config.baud_rate = BAUD_RATE_9600;        //修改波特率为 9600
config.data_bits = DATA_BITS_8;           //数据位 8
config.stop_bits = STOP_BITS_1;           //停止位 1
config.bufsz     = 128;                   //修改缓冲区 buff size 为 128
config.parity    = PARITY_NONE;           //无奇偶校验位
/* 控制串口设备。通过控制接口传入命令控制字,与控制参数 */
rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);

(3)打开串口

/* 以中断接收及轮询发送模式打开串口设备 */
rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
/* 以 DMA 接收及轮询发送模式打开串口设备 */
rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX);

(4)发送及接收数据

  1. 发送数据
char str[] = "hello RT-Thread!\r\n";
/* 发送字符串 */
rt_device_write(serial, 0, str, (sizeof(str) - 1));

数据发送结束可以设置发送完成回调函数

rt_err_t rt_device_set_tx_complete(rt_device_t dev, rt_err_t (*tx_done)(rt_device_t dev,void *buffer));
  1. 接收数据
    通常使用中断方式接收数据,首先设置接收回调函数
rt_err_t rt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_t dev,rt_size_t size));

读取数据

rt_size_t rt_device_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size);

2.UART使用实例

在RT-Thread studio中创建工程,并进行后续配置:
(1)采用普通中断的配置
在这里插入图片描述
如果使用DMA则开启DMA模式并设置DMA缓冲区大小
在这里插入图片描述
(2)打开board.h文件,根据提示进行串口配置
在这里插入图片描述
第一步:在(1)中已完成
第二步:定义串口并制定串口引脚
第三步:根据实际需要开启DMA,按(1)中方式进行
第四步:如果开启了DMA功能,则board.h串口配置需要添加一行代码
在这里插入图片描述
串口功能的具体配置代码可以参考uart_config.h文件
在这里插入图片描述
在这里插入图片描述
(3)上述配置完成后即可开始编写功能代码:
普通中断模式通常使用信号量,尽量不要在中断回调函数中进行数据接收,而DMA方式通常采用邮箱或队列方式,也不要在中断回调函数中接收数据

普通中断接收数据的完整示例代码如下:

#include <rtthread.h>
#include <rtdevice.h>
#include "string.h"

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

static rt_device_t serial2;//串口设备句柄
static struct rt_semaphore s2rx_sem;//定义信号量

char uart2_rec_buf[100];

static rt_err_t uart2_rec_callback(rt_device_t dev, rt_size_t size)//中断接收回调函数
{
    rt_sem_release(&s2rx_sem);//释放信号量
    return RT_EOK;
}

int main(void)
{
    char ch;
    rt_uint8_t i=0;

    rt_sem_init(&s2rx_sem, "serial2_rx_sem", 0, RT_IPC_FLAG_FIFO);//初始化信号量
    serial2=rt_device_find("uart2");//查询串口设备
    rt_device_open(serial2, RT_DEVICE_OFLAG_RDWR|RT_DEVICE_FLAG_INT_RX);
    rt_device_set_rx_indicate(serial2, uart2_rec_callback);//打开串口设备

    while (1)
    {
        if(rt_sem_take(&s2rx_sem,RT_WAITING_FOREVER)==RT_EOK)//等待信号量
        {
            rt_device_read(serial2, 0, &ch, 1);//读取串口数据
            uart2_rec_buf[i++]=ch;
            if(i>=2)
            {
                if(uart2_rec_buf[i-2]=='\r' && uart2_rec_buf[i-1]=='\n')
                {
                    rt_device_write(serial2, 0, uart2_rec_buf, i);
                    i=0;
                    memset(uart2_rec_buf, 0, sizeof(uart2_rec_buf));
                }
            }
        }
    }
    return RT_EOK;
}

DMA方式接收数据的完整示例:

#include <rtthread.h>
#include <rtdevice.h>

#define LED0_PIN    GET_PIN(B, 1)

#define UART_NAME "uart2"//定义串口名
static rt_device_t serial2;//串口设备句柄
rt_thread_t serial_tid=RT_NULL;

struct rx_msg//定义接收消息结构体
{
    rt_device_t dev;
    rt_size_t size;
};

static rt_mq_t uart2_rx_mq;//定义队列

rt_err_t uart2_rx_ind(rt_device_t dev,rt_size_t size)//串口接收中断回调函数
{
    rt_err_t ret;
    struct rx_msg msg;
    msg.dev=dev;
    msg.size=size;
    ret=rt_mq_send(uart2_rx_mq, &msg, sizeof(msg));//发送消息队列
    if(ret==RT_EFULL)
    {

        rt_kprintf("message queue full!\r\n");
    }
    return ret;
}

void serial_thread_entry(void *parameter)
{
    struct rx_msg msg;
    rt_uint16_t rx_len;
    char buf[128];
    while(1)
    {
        rt_memset(&msg,0,sizeof(msg));
        if(rt_mq_recv(uart2_rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER)==RT_EOK)//等待消息队列
        {
            rx_len=rt_device_read(msg.dev, 0, buf, msg.size);//读取串口数据
            rt_device_write(serial2, 0, buf, rx_len);
        }
    }

}

void uart_dma_sample(void)
{
    char str[]="hello RT-Thread!\r\n";
    uart2_rx_mq=rt_mq_create("uart_mq", 128, 8, RT_IPC_FLAG_FIFO);
    serial2=rt_device_find(UART_NAME);
    rt_device_open(serial2, RT_DEVICE_FLAG_DMA_RX);
    rt_device_set_rx_indicate(serial2, uart2_rx_ind);
    rt_device_write(serial2,0,str,(sizeof(str)-1));
    serial_tid=rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
    rt_thread_startup(serial_tid);
}

int main(void)
{
    uart_dma_sample();
    return RT_EOK;
}

总结

本文介绍了RT-Thread中UART设备的使用,分别介绍了普通中断方式接收和DMA方式接收。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值