lugl4313820 发表于 2022-1-23 21:33

【国民技术N32G457评测】4、串口2 DMA 中断接收与发送

本帖最后由 lugl4313820 于 2022-1-23 22:36 编辑

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;由于rt_thread 串口默认为finsh使用,这里测试使用串口2:</span></p>

<p><span style="font-size:16px;">&nbsp; &nbsp; 打开《DS_N32G457系列数据手册V1.2.1.pdf》找到串口2的定义:USART2_TX 为PA2,USART2_RX为PA3。</span></p>

<p>&nbsp;新建工程UART2DEMO:</p>

<p>&nbsp; <span style="font-size:16px;">修改drv_gpio.c的GPIO管脚设置:#define N32F10X_PIN_NUMBERS 100 //</span></p>

<p>&nbsp; &nbsp; 打开RT_Thread Settins使能uar2:如图</p>

<p><span style="font-size:16px;">&nbsp;然后关闭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: &#39;NULL&#39; undeclared (first use in this function)<br />
&nbsp; &nbsp; &nbsp;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 &#39;strlen&#39; [-Wimplicit-function-declaration]<br />
&nbsp; &nbsp; &nbsp;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&lt;stdlib.h&gt;<br />
#include&lt;string.h&gt;</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 &lt;rtthread.h&gt;

#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(&amp;rx_sem);
    return RT_EOK;
}

static void serial2_thread_entry(void *parameter)
{
    char ch;
    while(1)
    {
      /*从串口2读取一个字节的数据,没有读取到则等待接收信号量 */
      while(rt_device_read(serial2, -1, &amp;ch, 1) != 1)
      {
            /* 阻塞等待接收信号量,等到信号接收后再次读取数据 */
            rt_sem_take(&amp;rx_sem, RT_WAITING_FOREVER);
      }
      /*读取到的数据通过串口输出*/
      rt_device_write(serial2, 0, &amp;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(&amp;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 &lt;stdint.h&gt;
#include &lt;rtthread.h&gt;
#include &lt;rtdevice.h&gt;
#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>&nbsp;是不是很容易吧,其实感觉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 &lt;rtthread.h&gt;
#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(&amp;rx_mq, &amp;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(&amp;msg, 0, sizeof(msg));
      /* 从消息队列中读取消息 */
      result = rt_mq_recv(&amp;rx_mq, &amp;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(&amp;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>&nbsp;至此 串口使用OK,国民技术与RT_Thread对这块芯片的移植与技术支持还是很好的。</p>
页: [1]
查看完整版本: 【国民技术N32G457评测】4、串口2 DMA 中断接收与发送