RISC-V MCU应用教程之赤菟V307多UART通信

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值