【国民技术N32G457评测】4、串口2 DMA 中断接收与发送
本帖最后由 lugl4313820 于 2022-1-23 22:36 编辑<p><span style="font-size:16px;"> 由于rt_thread 串口默认为finsh使用,这里测试使用串口2:</span></p>
<p><span style="font-size:16px;"> 打开《DS_N32G457系列数据手册V1.2.1.pdf》找到串口2的定义:USART2_TX 为PA2,USART2_RX为PA3。</span></p>
<p> 新建工程UART2DEMO:</p>
<p> <span style="font-size:16px;">修改drv_gpio.c的GPIO管脚设置:#define N32F10X_PIN_NUMBERS 100 //</span></p>
<p> 打开RT_Thread Settins使能uar2:如图</p>
<p><span style="font-size:16px;"> 然后关闭Settings,选择保存,自动更新项目。</span></p>
<p><span style="font-size:16px;">在apllications文件夹下新建uar2.h、uart2.c。</span></p>
<p><span style="font-size:16px;">编译一下,有报错:</span></p>
<p><span style="font-size:16px;">../board/msp/n32_msp.c:347:18: error: 'NULL' undeclared (first use in this function)<br />
if (uartx == NULL)</span></p>
<p><span style="font-size:16px;">这是系统生成的代码有误,我们找到错误,把NULL修改为RT_NULL。</span></p>
<p><span style="font-size:16px;">然后还有两个警告:</span></p>
<p><span style="font-size:16px;">../board/msp/n32_msp.c:353:37: warning: implicit declaration of function 'strlen' [-Wimplicit-function-declaration]<br />
rt_device_write(uartx, 0, name, strlen(name));</span></p>
<p><span style="font-size:16px;">是由于没有引入stdlib.h与string.h所引起的,加入引用</span></p>
<p><span style="font-size:16px;">#include<stdlib.h><br />
#include<string.h></span></p>
<p><span style="font-size:16px;">然后编译就OK了:</span></p>
<p><span style="font-size:16px;">参照《</span>RT-Thread API参考手册<span style="font-size:16px;">》的UART例子uart.c 与uart2.h如下:</span></p>
<p>uart.c:</p>
<pre>
<code>/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-01-23 Administrator the first version
*/
/*
* 程序清单:这是一个 串口 设备使用例程
* 例程导出了 uart_sample 命令到控制终端
* 命令调用格式:uart_sample uart2
* 命令解释:命令第二个参数是要使用的串口设备名称,为空则使用默认的串口设备
* 程序功能:通过串口输出字符串"hello RT-Thread!",然后输出输入的字符
*/
#ifndef _UART2_C_
#define _UART2_C_
#include "uart2.h"
#include <rtthread.h>
#define UART2_NAME "uart2" /* 串口设备名称 */
/* 用于接收消息的信号量 */
static struct rt_semaphore rx_sem;
static rt_device_t serial2;
/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
/* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void serial2_thread_entry(void *parameter)
{
char ch;
while(1)
{
/*从串口2读取一个字节的数据,没有读取到则等待接收信号量 */
while(rt_device_read(serial2, -1, &ch, 1) != 1)
{
/* 阻塞等待接收信号量,等到信号接收后再次读取数据 */
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
}
/*读取到的数据通过串口输出*/
rt_device_write(serial2, 0, &ch, 1);
}
}
int uart2_sample(void)
{
rt_err_t ret = RT_EOK;
char uart_name;
char str[] = "hello RT-Thread!\r\n";
rt_strncpy(uart_name, UART2_NAME, RT_NAME_MAX);
/*查找串口设备 */
serial2 = rt_device_find(uart_name);
if(!serial2)
{
rt_kprintf("find %s failed!\r\n", uart_name);
return RT_ERROR;
}
/*初始化信号量 */
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
/* 以读写及中断接收方式打开串口设备 */
rt_device_open(serial2, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
/* 设置接收回调函数 */
rt_device_set_rx_indicate(serial2, uart_input);
/* 发送字符串 */
rt_device_write(serial2, 0, str, (sizeof(str)-1));
/*创建serial2线程 */
rt_thread_t thread_serial2 = rt_thread_create("serial2", serial2_thread_entry, RT_NULL, 1024, 25, 10);
/*创建成功则启动线程 */
if(thread_serial2 != RT_NULL)
{
rt_thread_startup(thread_serial2);
}
else {
{
ret = RT_ERROR;
}
}
return ret;
}
#endif /* _UART2_C_ */
</code></pre>
<p>uart2.h</p>
<pre>
<code>/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-01-23 Administrator the first version
*/
#ifndef _UART2_H_
#define _UART2_H_
int uart2_sample(void);
#endif /* APPLICATIONS_UART2_H_ */</code></pre>
<p>main.c</p>
<pre>
<code>/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-07-29 Arda.Fu first implementation
*/
#include <stdint.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "uart2.h"
/* defined the LED1 pin: PB5 */
#define LED1_PIN 91
int main(void)
{
uint32_t Speed = 200;
int i;
/* set LED1 pin mode to output */
rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
i = uart2_sample();
while (1)
{
rt_pin_write(LED1_PIN, PIN_LOW);
rt_thread_mdelay(Speed);
rt_pin_write(LED1_PIN, PIN_HIGH);
rt_thread_mdelay(Speed);
}
}
</code></pre>
<p>下载到开发板,与串口2的交互如下:</p>
<p> 是不是很容易吧,其实感觉RT_Thread开发起来相比要配置一系列的寄存器等要简单很多。</p>
<p>串口DMA的使用:</p>
<p>uartdma.c</p>
<pre>
<code>/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-01-23 Administrator the first version
*/
#include <rtthread.h>
#include "uartdma.h"
#define UART2_NAME "uart2" /* 串口设备名称 */
/* 串口接收消息结构体 */
struct rx_msg
{
rt_device_t dev;
rt_size_t size;
};
/* 串口设备句柄 */
static rt_device_t serial2;
/* 消息队伍控制块 */
static struct rt_messagequeue rx_mq;
/*接收数据回调函数 */
static rt_err_t uart2_input(rt_device_t dev, rt_size_t size)
{
struct rx_msg msg;
rt_err_t result;
msg.dev = dev;
msg.size = size;
result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
if(result == -RT_EFULL)
{
/* 消息队伍满 */
rt_kprintf("message queue full!\r\n");
}
return result;
}
static void serial2_thread_entry(void *parameter)
{
struct rx_msg msg;
rt_err_t result;
rt_uint32_t rx_length;
static char rx_buffer;
while(1)
{
rt_memset(&msg, 0, sizeof(msg));
/* 从消息队列中读取消息 */
result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
if(result == RT_EOK)
{
/* 从串口读取数据 */
rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
rx_buffer = '\0';
/* 通过串品设备输出读取到的消息息 */
rt_device_write(msg.dev, 0, rx_buffer, rx_length);
/*打印数据 */
rt_kprintf("%s\n", rx_buffer);
}
}
}
int uart2_dma_sample(void)
{
rt_err_t ret = RT_EOK;
char uart_name;
static char msg_pool;
char str[] = "Hello RT-Thread!\r\n";
rt_strncpy(uart_name, UART2_NAME, RT_NAME_MAX);
/* 查找串口设备 */
serial2 = rt_device_find(uart_name);
if(!serial2)
{
rt_kprintf("Find %s failed!\r\n", uart_name);
return RT_ERROR;
}
/* 初始化消息队列 */
rt_mq_init(&rx_mq,
"rx_mq",
msg_pool,
sizeof(struct rx_msg),
sizeof(msg_pool),
RT_IPC_FLAG_FIFO);
/* 以DMA接收及轮询发送方式打开串口设备 */
rt_device_open(serial2, RT_DEVICE_FLAG_DMA_RX);
/* 设置接收回调函数 */
rt_device_set_rx_indicate(serial2, uart2_input);
/* 发送字符串 */
rt_device_write(serial2, 0, str, (sizeof(str) - 1));
/* 创建serial2 线程 */
rt_thread_t thread_uart2 = rt_thread_create("serial2", serial2_thread_entry, RT_NULL, 1024, 25, 10);
if(thread_uart2 != RT_NULL)
{
rt_thread_startup(thread_uart2);
}
else {
ret = RT_ERROR;
}
return ret;
}
</code></pre>
<p>uartdma.h</p>
<pre>
<code>/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-01-23 Administrator the first version
*/
#ifndef _UART2DMA_H_
#define _UART2DMA_H_
int uart2_dma_sample(void);
#endif /* APPLICATIONS_UART2DMA_H_ */
</code></pre>
<p>串口2结果:</p>
<p> 至此 串口使用OK,国民技术与RT_Thread对这块芯片的移植与技术支持还是很好的。</p>
页:
[1]