前言
本工程是在之前新建工程的基础上增加了串口通讯实验,如果不会建立工程的请参考[工程建立](【沁恒微CH32V307评估板试用体验】RT-Thread应用开发(一)——工程建立 - 单片机/MCU论坛 - 电子技术论坛 - 广受欢迎的专业电子论坛! (elecfans.com))。
程序开发
1.双击打开RT_Thread settings文件,在硬件栏中打开“Enable UART2”,FIFO默认填写10,可根据自己的需求自行修改。修改好记得保存。
2.在Application 文件夹下新建usart2.c和usart2.h文件
修改usart2.c内容如下
#include <rtthread.h>
#define SAMPLE_UART_NAME "uart2"
static struct rt_semaphore rx_sem;
static rt_device_t serial;
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&rx_sem);
return RT_EOK;
}
static void serial_thread_entry(void *parameter)
{
char ch;
while (1)
{
while (rt_device_read(serial, -1, &ch, 1) != 1)
{
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
}
ch = ch + 1;
rt_device_write(serial, 0, &ch, 1);
}
}
static int uart_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
char uart_name[RT_NAME_MAX];
char str[] = "hello RT-Thread!\r\n";
if (argc == 2)
{
rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
}
serial = rt_device_find(uart_name);
if (!serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return RT_ERROR;
}
rt_sem_init(&rx_sem, "rx_sem", 0, 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(uart_sample, uart device sample);
3.修改drv_usart.c文件
drv_usart.c文件在工程libraries/hal_drivers里。默认创建的工程中只初始化了串口1引脚,所以需要在ch32_configure函数里添加串口2的引脚。修改后的函数如下。
static rt_err_t ch32_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
struct ch32_uart *uart;
RT_ASSERT(serial != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
uart = (struct ch32_uart *) serial->parent.user_data;
uart->Init.USART_BaudRate = cfg->baud_rate;
uart->Init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
uart->Init.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
switch (cfg->data_bits)
{
case DATA_BITS_8:
uart->Init.USART_WordLength = USART_WordLength_8b;
break;
case DATA_BITS_9:
uart->Init.USART_WordLength = USART_WordLength_9b;
break;
default:
uart->Init.USART_WordLength = USART_WordLength_8b;
break;
}
switch (cfg->stop_bits)
{
case STOP_BITS_1:
uart->Init.USART_StopBits = USART_StopBits_1;
break;
case STOP_BITS_2:
uart->Init.USART_StopBits = USART_StopBits_2;
break;
default:
uart->Init.USART_StopBits = USART_StopBits_1;
break;
}
switch (cfg->parity)
{
case PARITY_NONE:
uart->Init.USART_Parity = USART_Parity_No;
break;
case PARITY_ODD:
uart->Init.USART_Parity = USART_Parity_Odd;
break;
case PARITY_EVEN:
uart->Init.USART_Parity = USART_Parity_Even;
break;
default:
uart->Init.USART_Parity = USART_Parity_No;
break;
}
if(uart->config->Instance==USART1)
{
GPIO_InitTypeDef GPIO_InitStructure={0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_Init(uart->config->Instance,&uart->Init);
USART_Cmd(uart->config->Instance, ENABLE);
}
if(uart->config->Instance==USART2)
{
GPIO_InitTypeDef GPIO_InitStructure={0};
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_Init(uart->config->Instance,&uart->Init);
USART_Cmd(uart->config->Instance, ENABLE);
}
if(uart->config->Instance==USART3)
{
}
if(uart->config->Instance==UART4)
{
}
if(uart->config->Instance==UART5)
{
}
if(uart->config->Instance==UART6)
{
}
if(uart->config->Instance==UART7)
{
GPIO_InitTypeDef GPIO_InitStructure={0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART7, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
USART_Init(uart->config->Instance,&uart->Init);
USART_Cmd(uart->config->Instance, ENABLE);
}
if(uart->config->Instance==UART8)
{
}
return RT_EOK;
}
4.编译下载
按照上面步骤编译完成理论上是没有任何问题的,如果出现报错请按照提示自行解决。
运行测试
将开发板的PA2和PA3分别连接USB转串口模块的RX和TX。系统上电,在FinSH里输入“list_device+换行”命令,会发现uart2设备已经挂载。然后输入“uart_sample+换行”命令,串口2会发出“hello RT-Thread!”字样。如果串口2接收到数据“123”,则会返回“234”。