PSoc™62开发板之串口通信

实验目的

1.使用串口和PC机通信:接收和发送信息

2.接收GNSS模块定位信息

实验准备

  • PSoc62™开发板
  • CH340 USB转TTL模块
  • ATGM332D GNSS模块
  • 公母头杜邦线x4

板载资源

板载有多少uart

创建工程例程,在libraries/HAL_Drivers/uart_config.h中查看BSP支持的uart数量及对应的GPIO,可以看到一共有7组uart

/*
 * Copyright (c) 2006-2023, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-07-08     Rbb666       first version
 */

#ifndef __UART_CONFIG_H__
#define __UART_CONFIG_H__

#include <rtthread.h>
#include "board.h"

#ifdef __cplusplus
extern "C"
{
#endif

#ifdef BSP_USING_UART0
    /* UART0 device driver structure */
    cy_stc_sysint_t UART0_SCB_IRQ_cfg =
        {
            .intrSrc = (IRQn_Type)scb_0_interrupt_IRQn,
            .intrPriority = (7u),
    };
#endif
#ifdef BSP_USING_UART1
    /* UART1 device driver structure */
    cy_stc_sysint_t UART1_SCB_IRQ_cfg =
        {
            .intrSrc = (IRQn_Type)scb_1_interrupt_IRQn,
            .intrPriority = (7u),
    };
#endif
#ifdef BSP_USING_UART2
    /* UART2 device driver structure */
    cy_stc_sysint_t UART2_SCB_IRQ_cfg =
        {
            .intrSrc = (IRQn_Type)scb_2_interrupt_IRQn,
            .intrPriority = (7u),
    };
#endif
#ifdef BSP_USING_UART3
    /* UART3 device driver structure */
    cy_stc_sysint_t UART3_SCB_IRQ_cfg =
        {
            .intrSrc = (IRQn_Type)scb_3_interrupt_IRQn,
            .intrPriority = (7u),
    };
#endif
#ifdef BSP_USING_UART4
    /* UART4 device driver structure */
    cy_stc_sysint_t UART4_SCB_IRQ_cfg =
        {
            .intrSrc = (IRQn_Type)scb_4_interrupt_IRQn,
            .intrPriority = (7u),
    };
#endif
#ifdef BSP_USING_UART5
    /* UART5 device driver structure */
    cy_stc_sysint_t UART5_SCB_IRQ_cfg =
        {
            .intrSrc = (IRQn_Type)scb_5_interrupt_IRQn,
            .intrPriority = (7u),
    };
#endif

#ifdef BSP_USING_UART6
    /* UART6 device driver structure */
    cy_stc_sysint_t UART6_SCB_IRQ_cfg =
        {
            .intrSrc = (IRQn_Type)scb_6_interrupt_IRQn,
            .intrPriority = (7u),
    };
#endif
#if defined(BSP_USING_UART0)
#ifndef UART0_CONFIG
#define UART0_CONFIG                            \
    {                                           \
        .name = "uart0",                        \
        .tx_pin = P0_3,                         \
        .rx_pin = P0_2,                         \
        .usart_x = SCB0,                        \
        .intrSrc = scb_0_interrupt_IRQn,        \
        .userIsr = uart_isr_callback(uart0),    \
        .UART_SCB_IRQ_cfg = &UART0_SCB_IRQ_cfg, \
    }
    void uart0_isr_callback(void);
#endif /* UART0_CONFIG */
#endif /* BSP_USING_UART0 */

#if defined(BSP_USING_UART1)
#ifndef UART1_CONFIG
#define UART1_CONFIG                            \
    {                                           \
        .name = "uart1",                        \
        .tx_pin = P10_1,                        \
        .rx_pin = P10_0,                        \
        .usart_x = SCB1,                        \
        .intrSrc = scb_1_interrupt_IRQn,        \
        .userIsr = uart_isr_callback(uart1),    \
        .UART_SCB_IRQ_cfg = &UART1_SCB_IRQ_cfg, \
    }
    void uart1_isr_callback(void);
#endif /* UART1_CONFIG */
#endif /* BSP_USING_UART1 */

#if defined(BSP_USING_UART2)
#ifndef UART2_CONFIG
#if defined(SOC_CY8C6244LQI_S4D92)
#define UART2_CONFIG                            \
    {                                           \
        .name = "uart2",                        \
        .tx_pin = P3_1,                         \
        .rx_pin = P3_0,                         \
        .usart_x = SCB2,                        \
        .intrSrc = scb_2_interrupt_IRQn,        \
        .userIsr = uart_isr_callback(uart2),    \
        .UART_SCB_IRQ_cfg = &UART2_SCB_IRQ_cfg, \
    }
#else
#define UART2_CONFIG                            \
    {                                           \
        .name = "uart2",                        \
        .tx_pin = P9_1,                         \
        .rx_pin = P9_0,                         \
        .usart_x = SCB2,                        \
        .intrSrc = scb_2_interrupt_IRQn,        \
        .userIsr = uart_isr_callback(uart2),    \
        .UART_SCB_IRQ_cfg = &UART2_SCB_IRQ_cfg, \
    }
#endif /* SOC_CY8C6244LQI_S4D92 */
    void uart2_isr_callback(void);
#endif /* UART2_CONFIG */
#endif /* BSP_USING_UART2 */

#if defined(BSP_USING_UART3)
#ifndef UART3_CONFIG
#define UART3_CONFIG                            \
    {                                           \
        .name = "uart3",                        \
        .tx_pin = P6_1,                         \
        .rx_pin = P6_0,                         \
        .usart_x = SCB3,                        \
        .intrSrc = scb_3_interrupt_IRQn,        \
        .userIsr = uart_isr_callback(uart3),    \
        .UART_SCB_IRQ_cfg = &UART3_SCB_IRQ_cfg, \
    }
    void uart3_isr_callback(void);
#endif /* UART3_CONFIG */
#endif /* BSP_USING_UART3 */

#if defined(BSP_USING_UART4)
#ifndef UART4_CONFIG
#define UART4_CONFIG                            \
    {                                           \
        .name = "uart4",                        \
        .tx_pin = P7_1,                         \
        .rx_pin = P7_0,                         \
        .usart_x = SCB4,                        \
        .intrSrc = scb_4_interrupt_IRQn,        \
        .userIsr = uart_isr_callback(uart4),    \
        .UART_SCB_IRQ_cfg = &UART4_SCB_IRQ_cfg, \
    }
    void uart4_isr_callback(void);
#endif /* UART4_CONFIG */
#endif /* BSP_USING_UART4 */

#if defined(BSP_USING_UART5)
#ifndef UART5_CONFIG
#define UART5_CONFIG                            \
    {                                           \
        .name = "uart5",                        \
        .tx_pin = P5_1,                         \
        .rx_pin = P5_0,                         \
        .usart_x = SCB5,                        \
        .intrSrc = scb_5_interrupt_IRQn,        \
        .userIsr = uart_isr_callback(uart5),    \
        .UART_SCB_IRQ_cfg = &UART5_SCB_IRQ_cfg, \
    }
    void uart5_isr_callback(void);
#endif /* UART5_CONFIG */
#endif /* BSP_USING_UART5 */

#if defined(BSP_USING_UART6)
#ifndef UART6_CONFIG
#define UART6_CONFIG                            \
    {                                           \
        .name = "uart6",                        \
        .tx_pin = P6_5,                         \
        .rx_pin = P6_4,                         \
        .usart_x = SCB6,                        \
        .intrSrc = scb_6_interrupt_IRQn,        \
        .userIsr = uart_isr_callback(uart6),    \
        .UART_SCB_IRQ_cfg = &UART6_SCB_IRQ_cfg, \
    }
    void uart6_isr_callback(void);
#endif /* UART6_CONFIG */
#endif /* BSP_USING_UART6 */
#ifdef __cplusplus
}
#endif

#endif

uart0-uart6和GPIO对应关系表

uart2是比较特殊的,两组不同的GPIO都可以使用它

分组 RXD TXD
uart0 P0.2 P0.3
uart1 P10.0 P10.1
uart2 P3.0 / P9.0 P3.1 / P9.1
uart3 P6.0 P6.1
uart4 P7.0 P7.1
uart5 P5.0 P5.1
uart6 P6.4 P6.5

电路图

串口IO

这里以uart0为例,P0.2对应MCU_ARD_PWM11P0.3对应MCU_ARD_PWM12

模块连接图

右侧排母从上往下第6、7引脚分别对应uart0 TXD、RXD

状态指示灯

板子有两个自主控制的绿色LED,通过上拉方式接入GPIO,MCU_USER_LED1对应P0.0,本次实验使用它来指示uart0的数据接收状态

使能串口

在创建的RT-Thread串口工程中打开RT-Thread Settings,点击右边的箭头<<进入详细页,使用前先使能uart0,如下图所示

程序设计

和PC机通信

通过CH340 USB转TTL模块连接PC和uart0,实物连接图如下

编码实现

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

#define LED_PIN     GET_PIN(0, 1)
#define UART_DEVICE_NAME       "uart0"
#define BSP_UART4_RX_BUFSIZE 1024

static rt_device_t serial;

struct rx_msg
{
    rt_device_t dev;
    rt_size_t size;
};

static struct rt_messagequeue rx_mq;

static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    rt_pin_write(LED_PIN, PIN_LOW);
    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!\n");
    }
    return result;
}

static void serial_thread_entry(void *parameter)
{
    struct rx_msg msg;
    rt_err_t result;
    rt_uint32_t rx_length;
    static char rx_buffer[BSP_UART4_RX_BUFSIZE + 1];
    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[rx_length] = '\0';
            rt_device_write(serial, 0, rx_buffer, rx_length);
            rt_pin_write(LED_PIN, PIN_HIGH);
//            rt_kprintf("%s\n",rx_buffer);
        }
    }
}

static int uart0_setup(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    char uart_name[RT_NAME_MAX];
    static char msg_pool[256];
    char str[] = "uart0 setup successfully!\r\n";

    if (argc == 2)
    {
        rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
    }
    else
    {
        rt_strncpy(uart_name, UART_DEVICE_NAME, RT_NAME_MAX);
    }

    serial = rt_device_find(uart_name);
    if (!serial)
    {
        rt_kprintf("find %s failed!\n", uart_name);
        return RT_ERROR;
    }

    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = BAUD_RATE_9600;
    config.data_bits = DATA_BITS_8;
    config.stop_bits = STOP_BITS_1;
    config.bufsz     = 1024;
    config.parity    = PARITY_NONE;
    rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);

    rt_mq_init(&rx_mq, "rx_mq", msg_pool, sizeof(struct rx_msg), sizeof(msg_pool), RT_IPC_FLAG_FIFO);
    rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
    rt_device_set_rx_indicate(serial, uart_input);
    rt_device_write(serial, 0, str, (sizeof(str) - 1));
    rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        ret = RT_ERROR;
    }

    return ret;
}

MSH_CMD_EXPORT(uart0_setup, uart0 setup example);


int main(void)
{
    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);

    while (1)
    {
        rt_thread_mdelay(500);
    }
}

打开串口调试工具,打开对应的COM口,串口设置和上面的代码保持一致:波特率115200、数据位8位、停止位为1位、奇偶校验位为无

在RT-Thread Studio初始化uart0,使用msh终端输入uart0_setup命令

初始化成功,可以在串口调试工具看到以下信息

自定义串口消息,点击发送按钮,可以看到发出去的消息被开发板转发了回来,而LED也随即闪了一下

接收GPS模块定位数据

通过uart0连接ATGM332D GNSS模块,实物连接图如下

编码实现uart0串口通信,注意GNSS模块的波特率默认为9600,其它跟上面的example保持一致

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

#define LED_PIN     GET_PIN(0, 1)
#define UART_DEVICE_NAME       "uart0"
#define BSP_UART4_RX_BUFSIZE 1024

static rt_device_t serial;

struct rx_msg
{
    rt_device_t dev;
    rt_size_t size;
};

static struct rt_messagequeue rx_mq;

static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
    rt_pin_write(LED_PIN, PIN_LOW);
    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!\n");
    }
    return result;
}

static void serial_thread_entry(void *parameter)
{
    struct rx_msg msg;
    rt_err_t result;
    rt_uint32_t rx_length;
    static char rx_buffer[BSP_UART4_RX_BUFSIZE + 1];
    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[rx_length] = '\0';
            rt_device_write(serial, 0, rx_buffer, rx_length);
            rt_pin_write(LED_PIN, PIN_HIGH);
            rt_kprintf("%s\n",rx_buffer);
        }
    }
}

static int uart0_setup(int argc, char *argv[])
{
    rt_err_t ret = RT_EOK;
    char uart_name[RT_NAME_MAX];
    static char msg_pool[256];
    char str[] = "uart0 setup successfully!\r\n";

    if (argc == 2)
    {
        rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
    }
    else
    {
        rt_strncpy(uart_name, UART_DEVICE_NAME, RT_NAME_MAX);
    }

    serial = rt_device_find(uart_name);
    if (!serial)
    {
        rt_kprintf("find %s failed!\n", uart_name);
        return RT_ERROR;
    }

    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
    config.baud_rate = BAUD_RATE_9600;
    config.data_bits = DATA_BITS_8;
    config.stop_bits = STOP_BITS_1;
    config.bufsz     = 1024;
    config.parity    = PARITY_NONE;
    rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);

    rt_mq_init(&rx_mq, "rx_mq", msg_pool, sizeof(struct rx_msg), sizeof(msg_pool), RT_IPC_FLAG_FIFO);
    rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
    rt_device_set_rx_indicate(serial, uart_input);
    rt_device_write(serial, 0, str, (sizeof(str) - 1));
    rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        ret = RT_ERROR;
    }

    return ret;
}

MSH_CMD_EXPORT(uart0_setup, uart0 setup example);


int main(void)
{
    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);

    while (1)
    {
        rt_thread_mdelay(500);
    }
}

在msh终端输入uart0_setup后GNSS数据读取结果如下

运行效果如下,可以看到GNSS报文以1Hz的频率打印,LED灯在不停地闪烁

阅读剩余
THE END