[RISC-V MCU 应用开发] 【RISC-V MCU CH32V103测评】03:打通交互功能之串口

[复制链接]
 楼主| 天意无罪 发表于 2020-12-5 22:07 | 显示全部楼层 |阅读模式
本帖最后由 天意无罪 于 2020-12-5 22:12 编辑

(一)硬件熟悉
USART全称为Universal Synchronous/Asynchronous Receiver/Transmitter(通用同步/异步串行接收/发送器),是一个全双工通用同步/异步串行收发模块,是一个高度灵活的串行通信设备。


CH32V103的USART外设主要特性如下:


226065fcb930f46712.png
CH32V103的USART外设系统框图如下:
7455fcb93229b37b.png

此次评测的开发板使用的MCU型号为CH32V103C8T6,从数据手册得知,该芯片共有3个USART外设:USART1、USART2、USART3;其中USART1被用于开发板的Debug映射,所以这里使用USART2进行试验,USART2的发收引脚分布在PA2和PA3上。
483275fcb9333e5695.png


(二)程序设计
实现功能:通过串口调试助手向USART2发送点亮和熄灭开发板上的两个LED命令,USART2接收到相应命名后进行判断,并执行命令。
1.在BSP/src目录下新建一个usart.c文件,在BSP/inc目录下新建一个usart.h文件。

542165fcb935674567.png

2.在usart.h文件里面编写相关宏定义、变量及函数声明等。

  1. #ifndef BSP_INC_USART_H_
  2. #define BSP_INC_USART_H_

  3. #include "ch32v10x_conf.h"

  4. #define     RXNUM   20
  5. #define     YES     1
  6. #define     NO      0

  7. volatile uint8_t        RXFLAG;
  8. uint8_t     USART_RXBUFF[RXNUM];

  9. void WCH_USART_Configure(void);
  10. void WCH_USART_SendByte(USART_TypeDef* pUSARTx, uint8_t data);
  11. void WCH_USART_SendString(USART_TypeDef* pUSARTx, char *str);
  12. void USART2_IRQHandler(void);

  13. #endif /* BSP_INC_USART_H_ */

3.在usart.c文件里面编写相关IO、时钟、usart外设、中断等的配置和初始化函数等。

  1. #include "usart.h"
  2. #include "led.h"

  3. void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

  4. void WCH_USART_Configure(void)
  5. {
  6.     GPIO_InitTypeDef  GPIO_InitStructure;
  7.     USART_InitTypeDef USART_InitStructure;
  8.     NVIC_InitTypeDef  NVIC_InitStructure;

  9.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); //使能串口2时钟
  10.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能GPIOA时钟

  11.     USART_DeInit(USART2);

  12.     /* USART2 TX-->A.2   RX-->A.3 */
  13.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  14.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  15.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;              //设置PA2为复用推挽输出
  16.     GPIO_Init(GPIOA, &GPIO_InitStructure);
  17.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  18.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //设置PA3为浮空输入
  19.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  20.     USART_InitStructure.USART_BaudRate = 115200;                 //设置串口波特率为115200
  21.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //字长为8位数据格式
  22.     USART_InitStructure.USART_StopBits = USART_StopBits_1;       //1个停止位
  23.     USART_InitStructure.USART_Parity = USART_Parity_No;          //无奇偶校验位
  24.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制
  25.     USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //发送和接收模式
  26.     USART_Init(USART2, &USART_InitStructure);                    //初始化串口

  27.     NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  28.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;      //抢占优先级为1
  29.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;           //子优先级为1
  30.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //IRQ通道使能
  31.     NVIC_Init(&NVIC_InitStructure);                              //中断优先级初始化

  32.     USART_Cmd(USART2, ENABLE);                                   //使能串口
  33.     USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);               //开启中断
  34. }

  35. void WCH_USART_SendByte(USART_TypeDef* pUSARTx, uint8_t data)
  36. {
  37.     USART_SendData(pUSARTx, data);

  38.     while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
  39. }

  40. void WCH_USART_SendString(USART_TypeDef* pUSARTx, char *str)
  41. {
  42.     uint8_t i = 0;

  43.     do
  44.     {
  45.         WCH_USART_SendByte(pUSARTx, *(str+i));
  46.         i++;
  47.     }while(*(str+i) != '\0');

  48.     while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
  49. }

  50. void USART2_IRQHandler(void)
  51. {
  52.     static uint8_t i=0;
  53.     uint8_t RxTemp;

  54.     if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //中断产生
  55.     {
  56.         USART_ClearITPendingBit(USART2, USART_IT_RXNE);    //清除中断标志
  57.         RxTemp = USART_ReceiveData(USART2);               //接收数据
  58.         USART_SendData(USART2, RxTemp);                   //发送数据

  59.         if(RxTemp == '\r')
  60.         {
  61.             WCH_USART_SendString(USART2, "\r\n");
  62.             USART_RXBUFF[i] = '\0';
  63.             RXFLAG = YES;
  64.             i = 0;
  65.         }
  66.         else
  67.         {
  68.             USART_RXBUFF[i++] = RxTemp;
  69.         }
  70.         if(i == RXNUM) i = 0;
  71.     }
  72. }

4.在Main函数中循环判断USART2接收的命令并执行

  1. #include <stdio.h>
  2. #include <string.h>

  3. #include "debug.h"
  4. #include "led.h"
  5. #include "usart.h"
  6. /* Global typedef */

  7. /* Global define */

  8. /* Global Variable */


  9. /*******************************************************************************
  10. * Function Name  : main
  11. * Description    : Main program.
  12. * Input          : None
  13. * Return         : None
  14. *******************************************************************************/
  15. int main(void)
  16. {
  17.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  18.         Delay_Init();
  19.         LED_Init();
  20.         WCH_USART_Configure();

  21.         RXFLAG = NO;

  22.         WCH_USART_SendString(USART2, "This is LED Test!\r\n");

  23.         while(1)
  24.         {
  25.             if(RXFLAG == YES)
  26.             {
  27.                 if(strcmp(USART_RXBUFF,"LED1_ON") == 0)
  28.                     LED1_ON();
  29.                 else if(strcmp(USART_RXBUFF,"LED1_OFF") == 0)
  30.                 LED1_OFF();
  31.                 else if(strcmp(USART_RXBUFF,"LED2_ON") == 0)
  32.                 LED2_ON();
  33.                 else if(strcmp(USART_RXBUFF,"LED2_OFF") == 0)
  34.                 LED2_OFF();
  35.                 else WCH_USART_SendString(USART2, "The Command is Fault!\r\n");

  36.             RXFLAG = NO;
  37.             }
  38.         }
  39. }






12165165 发表于 2023-4-14 10:12 | 显示全部楼层
工程文件方便分享一下吗,2635246872@qq.com,非常感谢
mikewalpole 发表于 2023-5-5 13:16 | 显示全部楼层
单片机与多个传感器如何用串口连接
wangdezhi 发表于 2023-5-5 18:24 | 显示全部楼层
在进行串口通信时,要确保单片机和PC使用相同的波特率、数据位、停止位和校验位等参数,否则会造成通信错误。
usysm 发表于 2023-5-5 20:03 | 显示全部楼层
单片机的串口通信可以通过配置串口模块来实现。一般来说,需要设置波特率、数据位、停止位和校验位等参数。
backlugin 发表于 2023-5-5 20:42 | 显示全部楼层
单片机串口扩展方法是什么              
1988020566 发表于 2023-5-5 21:15 | 显示全部楼层
由于串口通信是异步的,因此在单片机代码中也需要考虑处理数据丢失或重复接收等异常情况。
updownq 发表于 2023-5-10 20:25 | 显示全部楼层
如何移植freemodebus过来呢?
bestwell 发表于 2023-5-10 21:48 | 显示全部楼层
串口通信的端口标准有哪几种              
alvpeg 发表于 2023-5-10 21:56 | 显示全部楼层
能够dma+串口接收数据吗              
albertaabbot 发表于 2023-5-11 16:05 | 显示全部楼层
单片机的处理的速度可以。              
primojones 发表于 2023-5-11 16:11 | 显示全部楼层
这个最大的波特率可以设置多少              
lmn2005 发表于 2023-5-11 16:23 | 显示全部楼层
这个可改串口1吗?我怎么改不成?
claretttt 发表于 2023-5-11 16:44 | 显示全部楼层
这个可以自己编写上位机吗?              
pl202 发表于 2023-6-10 12:12 | 显示全部楼层
常见的串口通信软件包括TeraTerm、SecureCRT、PuTTY等
macpherson 发表于 2023-6-10 12:49 | 显示全部楼层
CH32V103串口发送数据包进行解析
claretttt 发表于 2023-6-10 13:36 | 显示全部楼层
移植letter-shell  
youtome 发表于 2023-6-10 16:14 | 显示全部楼层
开源嵌入式shell工具移植CH32V103
i1mcu 发表于 2023-6-10 16:26 | 显示全部楼层
可以通过串口、Telnet或其他通信协议与设备进行通信,并执行一些操作,如读取和写入寄存器,配置外设等。
sesefadou 发表于 2023-6-10 16:33 | 显示全部楼层
串口是实现交互功能的重要手段之一,它能够使计算机与各种外部设备进行通信,并且可以通过编写代码来控制和监测这些设备的行为。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

3278

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部

61

主题

3278

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部