RISC-V MCU应用教程之赤菟V307多UART通信
本文章介绍使用CH32V307单片机实现主机轮回接收从机传输的数据,并在串口软件显示。
您需要的资料:CH32V307单片机数据手册及例程
一、单片机串口部分简介
由上图可知,CH32V307有8个串口(USART+UART)。
由数据手册可知,USART有3个,USART1挂接在APB2总线上,USART2和USART2以及7个UART挂接在APB1总线上。
为了方便插拔引脚转接线,将数据手册中有关串口引脚陈列如下表格中。
防止原有映射引脚被其它外设占用,手册中定义的串口复用引脚陈列如下。
二、通讯原理及实现
1.Master程序为采集数据单片机烧录,Slave程序为数据发送单片机烧录;
2.主程序使6个串口中断周期性的开关,达到每次只接受一个Slave数据,达到周期性采集6个Slave数据的目的。最多可外接8路串口,本例程中USART1用来与PC串口通讯,UART8因器件不够暂未使用到。Slave均使用USART2,分别连接到Master剩余的6串口上。
3.若Master指定采集第x个Slave数据,则需先发送一个数据0作为启动Slave发送数据的请求命令,Slave判定请求命令正确后,在进行数据的发送。这种协议的约定,保证了Master接收Slave数据的完整性。(在Master接收到Slave数据后,可将原数据返回Slave做校验,本程序暂未实现,请读者自行尝试)
4.硬件连接如下,因为没有足够的usb供电,Slave取电为板载级联杜邦线方式。中间一块为Master采集板,周边六块为Slave数据发送板。
5. 程序如下
//双机通讯,使用USART
#include "debug.h"
/* Global define */
#define TxSize1 (size(TxBuffer1))
/* Global Variable */
u8 RxBuffer1 = 0; /* Send by UART2 */
u8 RequestData=0;//请求发送数据
u8 Rxfinish1 = 2;//先给个初始值,进入case 2,启动接收
//void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void UART4_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void UART5_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void UART6_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void UART7_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
//void UART8_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
/*********************************************************************
* @fn USARTx_CFG
*
* @brief Initializes the USART2 & USART3 peripheral.
*
* @return none
*/
void USARTx_CFG(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
USART_InitTypeDef USART_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2|RCC_APB1Periph_USART3|RCC_APB1Periph_UART4|RCC_APB1Periph_UART5|RCC_APB1Periph_UART6|RCC_APB1Periph_UART7|RCC_APB1Periph_UART8, ENABLE);
// RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
// /* USART1 TX-->A.9 RX-->A.10 */
// 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_Mode = GPIO_Mode_IN_FLOATING;
// GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USART2 TX-->A.2 RX-->A.3 */
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_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USART3 TX-->B.10 RX-->B.11 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* UART4 TX-->C.10 RX-->C.11 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
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_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* UART5 TX-->C.12 RX-->D.12 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
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_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* UART6 TX-->C.0 RX-->C.1 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
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_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* UART7 TX-->C.2 RX-->C.3 */
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_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// /* UART8 TX-->C.4 RX-->C.5 */
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
// 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_5;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
// GPIO_Init(GPIOC, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
// USART_Init(USART1, &USART_InitStructure);
// USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);//初始化全部关闭
USART_Init(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);
USART_Init(UART4, &USART_InitStructure);
USART_ITConfig(UART4, USART_IT_RXNE, DISABLE);
USART_Init(UART5, &USART_InitStructure);
USART_ITConfig(UART5, USART_IT_RXNE, DISABLE);
USART_Init(UART6, &USART_InitStructure);
USART_ITConfig(UART6, USART_IT_RXNE, DISABLE);
USART_Init(UART7, &USART_InitStructure);
USART_ITConfig(UART7, USART_IT_RXNE, DISABLE);
// USART_Init(UART8, &USART_InitStructure);
// USART_ITConfig(UART8, USART_IT_RXNE, DISABLE);
// NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = UART6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = UART7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// NVIC_InitStructure.NVIC_IRQChannel = UART8_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
// USART_Cmd(USART1, ENABLE);
USART_Cmd(USART2, ENABLE);
USART_Cmd(USART3, ENABLE);
USART_Cmd(UART4, ENABLE);
USART_Cmd(UART5, ENABLE);
USART_Cmd(UART6, ENABLE);
USART_Cmd(UART7, ENABLE);
// USART_Cmd(UART8, ENABLE);
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
USARTx_CFG(); /* USART2 & USART3 INIT */
printf("DATA RECEIVED START! \r\n");
//USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
while(1)
{
switch (Rxfinish1)
{
// case 1:
// printf("DATA RECEIVED FROM USART1 :%s\r\n",RxBuffer1);
// Rxfinish1=0;
// USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
// break;
case 2:
printf("DATA RECEIVED FROM SLAVE_2 :%p\r\n",RxBuffer1);//打印Slave发送来的数据
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启下一个Slave中断,准备接受数据
USART_SendData(USART3, RequestData);//发送准备好接受命令请求,Slave收到校验后,就开启发送
while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
Delay_Ms(100);//给slave时间组织发送,时间太短会重新进入case 2.
break;
case 3:
printf("DATA RECEIVED FROM SLAVE_3 :%p\r\n",RxBuffer1);
USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);
USART_SendData(UART4, RequestData);
while(USART_GetFlagStatus(UART4, USART_FLAG_TXE) == RESET);
Delay_Ms(100);
break;
case 4:
printf("DATA RECEIVED FROM SLAVE_4 :%p\r\n",RxBuffer1);
USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);
USART_SendData(UART5, RequestData);
while(USART_GetFlagStatus(UART5, USART_FLAG_TXE) == RESET);
Delay_Ms(100);
break;
case 5:
printf("DATA RECEIVED FROM SLAVE_5 :%p\r\n",RxBuffer1);
USART_ITConfig(UART6, USART_IT_RXNE, ENABLE);
USART_SendData(UART6, RequestData);
while(USART_GetFlagStatus(UART6, USART_FLAG_TXE) == RESET);
Delay_Ms(100);
break;
case 6:
printf("DATA RECEIVED FROM SLAVE_6 :%p\r\n",RxBuffer1);
USART_ITConfig(UART7, USART_IT_RXNE, ENABLE);
USART_SendData(UART7, RequestData);
while(USART_GetFlagStatus(UART7, USART_FLAG_TXE) == RESET);
Delay_Ms(100);
break;
case 7:
printf("DATA RECEIVED FROM SLAVE_7 :%p\r\n",RxBuffer1);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_SendData(USART2, RequestData);
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
Delay_Ms(100);
break;
// case 8:
// printf("DATA RECEIVED FROM UART8 :%p\r\n",RxBuffer1);
// Rxfinish1=0;
// Delay_Ms(500);
// USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
// USART_SendData(USART3, RequestData);
// while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
// break;
default:
printf("DATA RECEIVED error%p\r\n");
Delay_Ms(500);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
break;
}
}
}
/*********************************************************************
* @fn USART3_IRQHandler
*
* @brief This function handles USART3 global interrupt request.
*
* @return none
*/
//void USART1_IRQHandler(void)
//{
// if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
// {
// RxBuffer1 = USART_ReceiveData(USART1);
// USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
// Rxfinish1 = 1;
// }
//}
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
RxBuffer1 = USART_ReceiveData(USART2);
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);//关闭此中断
Rxfinish1 = 2;
}
}
void USART3_IRQHandler(void)
{
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
RxBuffer1 = USART_ReceiveData(USART3);
USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);
Rxfinish1 = 3;
}
}
void UART4_IRQHandler(void)
{
if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)
{
RxBuffer1 = USART_ReceiveData(UART4);
USART_ITConfig(UART4, USART_IT_RXNE, DISABLE);
Rxfinish1 = 4;
}
}
void UART5_IRQHandler(void)
{
if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)
{
RxBuffer1 = USART_ReceiveData(UART5);
USART_ITConfig(UART5, USART_IT_RXNE, DISABLE);
Rxfinish1 = 5;
}
}
void UART6_IRQHandler(void)
{
if(USART_GetITStatus(UART6, USART_IT_RXNE) != RESET)
{
RxBuffer1= USART_ReceiveData(UART6);
USART_ITConfig(UART6, USART_IT_RXNE, DISABLE);
Rxfinish1 = 6;
}
}
void UART7_IRQHandler(void)
{
if(USART_GetITStatus(UART7, USART_IT_RXNE) != RESET)
{
RxBuffer1 = USART_ReceiveData(UART7);
USART_ITConfig(UART7, USART_IT_RXNE, DISABLE);
Rxfinish1 = 7;
}
}
//void UART8_IRQHandler(void)
//{
// if(USART_GetITStatus(UART8, USART_IT_RXNE) != RESET)
// {
// RxBuffer1 = USART_ReceiveData(UART8);
// USART_ITConfig(UART8, USART_IT_RXNE, DISABLE);
// Rxfinish1 = 8;
// }
//
//}
6.Slave程序
//双机通讯,使用USART
#include "debug.h"
/* Global Variable */
u8 TxBuffer2 = 6;//这是发送的数据,可以分别配置Slave为不同的值
u8 RequestData=0;//检测请求命令是否正确
u8 RxBuffer2=0;
u8 Rxfinish2;
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
/*********************************************************************
* @fn USARTx_CFG
*
* @brief Initializes the USART2 & USART3 peripheral.
*
* @return none
*/
void USARTx_CFG(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
USART_InitTypeDef USART_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
/* USART2 TX-->A.2 RX-->A.3 */
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_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART2, ENABLE);
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
USARTx_CFG(); /* USART2 & USART3 INIT */
while(1)
{
if(RxBuffer2==RequestData)//校验数据请求命令
{
USART_SendData(USART2, TxBuffer2);//向Master发送数据
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
}
}
}
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//等待接受Master数据请求命令
{
RxBuffer2 = USART_ReceiveData(USART2);
}
}
————————————————
版权声明:本文为CSDN博主「付小熊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44845994/article/details/123548420