本文章介绍使用CH32V307单片机实现主机轮回接收从机传输的数据,并在串口软件显示。
您需要的资料:CH32V307单片机数据手册及例程
一、单片机串口部分简介
由上图可知,CH32V307有8个串口(USART+UART)。
由数据手册可知,USART有3个,USART1挂接在APB2总线上,USART2和USART2以及7个UART挂接在APB1总线上。
为了方便插拔引脚转接线,将数据手册中有关串口引脚陈列如下表格中。
串口引脚号 | 串口名称 |
---|---|
PA8 | USART1_CK |
PA9 | USART1 _TX |
PA10 | USART1_RX |
PA11 | USART1_CTX |
PA12 | USART1 _RTX |
PA4 | USART2_CK |
PA2 | USART2_TX |
PA3 | USART2_RX |
PA0 | USART2_CTX |
PA1 | USART2_RTX |
PB12 | USART3_CK |
PB10 | USART3 _TX |
PB11 | USART3_RX |
PB13 | USART3_CTX |
PB14 | USART3 _RTX |
PC10 | UART4_TX |
PC11 | UART4_RX |
PC12 | UART5_TX |
PD2 | UART5_RX |
PC0 | UART6_TX |
PC1 | UART6_RX |
PC2 | UART7_TX |
PC3 | UART7_RX |
PC4 | UART8_TX |
PC5 | UART8_RX |
防止原有映射引脚被其它外设占用,手册中定义的串口复用引脚陈列如下。
串口引脚号(复用) | 串口名称 |
---|---|
PA5/PA10 | USART1_CK |
PB6/PB15 | USART1 _TX |
PB7 | USART1_RX |
无 | USART1_CTX |
PC5/PA9 | USART1 _RTX |
PD7 | USART2_CK |
PD5 | USART2_TX |
PD6 | USART2_RX |
PD3 | USART2_CTX |
PD4 | USART2_RTX |
PD10/PC12 | USART3_CK |
PD8/PC10 | USART3 _TX |
PD9/PC11 | USART3_RX |
PD11 | USART3_CTX |
无 | USART3 _RTX |
PB0 | UART4_TX |
PB1 | UART4_RX |
PE8 | UART5_TX |
PE9/PB4 | UART5_RX |
PE10 | UART6_TX |
PE11 | UART6_RX |
PE12/PA6 | UART7_TX |
PE13 /PA7 | UART7_RX |
PE14/PA14 | UART8_TX |
PE15/PA15 | UART8_RX |
二、通讯原理及实现
- Master程序为采集数据单片机烧录,Slave程序为数据发送单片机烧录;
- 主程序使6个串口中断周期性的开关,达到每次只接受一个Slave数据,达到周期性采集6个Slave数据的目的。最多可外接8路串口,本例程中USART1用来与PC串口通讯,UART8因器件不够暂未使用到。Slave均使用USART2,分别连接到Master剩余的6串口上。
- 若Master指定采集第x个Slave数据,则需先发送一个数据0作为启动Slave发送数据的请求命令,Slave判定请求命令正确后,在进行数据的发送。这种协议的约定,保证了Master接收Slave数据的完整性。(在Master接收到Slave数据后,可将原数据返回Slave做校验,本程序暂未实现,请读者自行尝试)
- 硬件连接如下,因为没有足够的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;
// }
//
//}
- 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);
}
}
注:主机先上电,从机再上电,否则数据接收混乱,正在处理这个问题。