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_PWM11
,P0.3
对应MCU_ARD_PWM12
模块连接图
右侧排母从上往下第6、7引脚分别对应uart0 TXD、RXD
状态指示灯
板子有两个自主控制的绿色LED,通过上拉方式接入GPIO,MCU_USER_LED1
对应P0.0,本次实验使用它来指示uart0的数据接收状态
使能串口
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灯在不停地闪烁