[RISC-V MCU 应用开发] 【RISC-V MCU CH32V103测评4】+ 串口1接收bug的解决之串口小练

[复制链接]
 楼主| xyz549040622 发表于 2020-12-4 10:42 | 显示全部楼层 |阅读模式
本帖最后由 xyz549040622 于 2020-12-4 23:01 编辑

拿到一个开发板,在使得GPIO点亮LED闪烁成功,证明最小系统OK后,下一步要做的必然是打通USART接口,使得用户可以与开发板进行数据的交互。
MRS软件在自动创建工程后,会自动创建一个Debug的文件夹,里面包含Debug.c和Debug.h,这里面自动使能了USART1的串口功能,并使用了串口阻塞方式发送数据,并重定义了printf函数,使得程序中可以使用printf函数发送数据。
这里为了方便数据的交互,我们需要增加串口接收数据函数,使用阻塞方式发送数据,因此不使用官方的Debug.c中的函数,从而自己编写串口函数usart.c和usart.h。

友情提示,由于板子上国产SP232的影响,串口1TTL的接收是受影响的,必须把SP232拆掉才能使能串口1的接收,或者改为使用串口2、串口3的接收。如下图所示:
72795fca4d6527748.png

1.在workspace-RISC-V下新建一个文件夹CH32V103C8T6-USART1并将工程命名为CH32V103C8T6-USART1。
506765fca4cd67e7be.png 2.删除Debug里的关于串口的全部函数,只保留延时函数,把debug.h变为延时函数。
  1. /********************************** (C) COPYRIGHT  *******************************
  2. * File Name          : debug.c
  3. * Author             : WCH
  4. * Version            : V1.0.0
  5. * Date               : 2020/04/30
  6. * Description        : This file contains all the functions prototypes for UART
  7. *                      Printf , Delay functions.
  8. *******************************************************************************/
  9. #include "delay.h"

  10. static uint8_t  p_us=0;
  11. static uint16_t p_ms=0;

  12. /*******************************************************************************
  13. * Function Name  : Delay_Init
  14. * Description    : Initializes Delay Funcation.
  15. * Input          : None
  16. * Return         : None
  17. *******************************************************************************/
  18. void Delay_Init(void)
  19. {
  20.         p_us=SystemCoreClock/8000000;
  21.         p_ms=(uint16_t)p_us*1000;
  22. }

  23. /*******************************************************************************
  24. * Function Name  : Delay_Us
  25. * Description    : Microsecond Delay Time.
  26. * Input          : n:Microsecond number.
  27. * Return         : None
  28. *******************************************************************************/
  29. void Delay_Us(uint32_t n)
  30. {
  31.         uint32_t i;

  32.         SysTick->CTLR = 0;
  33.         i = (uint32_t)n*p_us;

  34.         SysTick->CNTL0 = 0;
  35.         SysTick->CNTL1 = 0;
  36.         SysTick->CNTL2 = 0;
  37.         SysTick->CNTL3 = 0;
  38.         SysTick->CTLR = 1;

  39.   while((*(__IO uint32_t*)0xE000F004) <= i);

  40. }

  41. /*******************************************************************************
  42. * Function Name  : Delay_Ms
  43. * Description    : Millisecond Delay Time.
  44. * Input          : n:Millisecond number.
  45. * Return         : None
  46. *******************************************************************************/
  47. void Delay_Ms (uint32_t n)
  48. {
  49.         uint32_t i;

  50.         SysTick->CTLR = 0;
  51.         i = (uint32_t)n*p_ms;

  52.         SysTick->CNTL0 = 0;
  53.         SysTick->CNTL1 = 0;
  54.         SysTick->CNTL2 = 0;
  55.         SysTick->CNTL3 = 0;
  56.         SysTick->CTLR = 1;

  57.   while((*(__IO uint32_t*)0xE000F004) <= i);
  58. }

3.增加usart.c的串口函数,配置串口1,使能发送和接收功能

  1. #include "usart.h"


  2. /*******************************************************************************
  3. * Function Name  : USARTx_CFG
  4. * Description    : Initializes the USART2  peripheral.
  5. * Input          : None
  6. * Return         : None
  7. *******************************************************************************/
  8. void USART1_Init(void)
  9. {
  10.   GPIO_InitTypeDef  GPIO_InitStructure;
  11.   USART_InitTypeDef USART_InitStructure;
  12.   NVIC_InitTypeDef  NVIC_InitStructure;

  13.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);  //使能GPIOA时钟

  14.   USART_DeInit(USART1);

  15.   /* USART2 TX-->A.2   RX-->A.3 */
  16.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  17.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;              //设置PA9为复用功能
  19.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  20.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  21.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //设置PA10为浮空输入
  22.   GPIO_Init(GPIOA, &GPIO_InitStructure);

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

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

  35.   USART_Cmd(USART1, ENABLE);                                   //使能串口
  36.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);               //开启中断
  37. }



  38. void USARTx_SendByte(USART_TypeDef* pUSARTx, uint8_t data)
  39. {

  40.     USART_SendData(pUSARTx, data);
  41.     while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
  42. }

  43. void USARTx_SendStr(USART_TypeDef* pUSARTx, char *str)
  44. {
  45.     uint8_t i = 0;
  46.     do
  47.     {
  48.        USARTx_SendByte(pUSARTx, *(str+i));
  49.        i++;
  50.     }while(*(str+i) != '\0');
  51.     while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
  52. }




4.添加led.c增加led的翻转闪烁函数

  1. #include "led.h"



  2. void User_Led_Init(void)
  3. {
  4.     GPIO_InitTypeDef GPIO_InitStructure;
  5.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  6.   /* USART1 TX-->PA9   RX-->PA10 */
  7.     GPIO_InitStructure.GPIO_Pin = User_LED1_Pin|User_LED2_Pin;
  8.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  9.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  10.     GPIO_Init(User_LED_Port, &GPIO_InitStructure);

  11.     GPIO_SetBits(User_LED_Port,User_LED1_Pin);
  12.     GPIO_SetBits(User_LED_Port,User_LED2_Pin);
  13. }

  14. void Toggle_User_Led(LED_LABEL LEDNAME)
  15. {
  16.     if(LEDNAME == User_LED1)
  17.     {
  18.         if(GPIO_ReadOutputDataBit(User_LED_Port,User_LED1_Pin) == Bit_SET)
  19.         {
  20.             GPIO_ResetBits(User_LED_Port,User_LED1_Pin);
  21.         }
  22.         else
  23.         {
  24.             GPIO_SetBits(User_LED_Port,User_LED1_Pin);
  25.         }
  26.     }
  27.     else if(LEDNAME == User_LED2)
  28.     {
  29.         if(GPIO_ReadOutputDataBit(User_LED_Port,User_LED2_Pin) == Bit_SET)
  30.         {
  31.             GPIO_ResetBits(User_LED_Port,User_LED2_Pin);
  32.         }
  33.         else
  34.         {
  35.             GPIO_SetBits(User_LED_Port,User_LED2_Pin);
  36.         }
  37.     }
  38. }
5.配置接收中断函数和main函数,接收到串口指令0x01后翻转LED1。
  1. /********************************** (C) COPYRIGHT *******************************
  2. * File Name          : main.c
  3. * Author             : WCH
  4. * Version            : V1.0.0
  5. * Date               : 2020/04/30
  6. * Description        : Main program body.
  7. *******************************************************************************/

  8. /*
  9. *@Note
  10. 串口打印调试例程:
  11. USART1_Tx(PA9)。
  12. 本例程演示使用 USART1(PA9) 作打印调试口输出。

  13. */

  14. #include "usart.h"
  15. #include "led.h"

  16. #include "../Delay/delay.h"
  17. /* Global typedef */

  18. /* Global define */

  19. /* Global Variable */
  20. void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

  21. #define RxBufferSize 1

  22. //定义一个字节的缓冲数组
  23. volatile uint8_t RxBuffer[RxBufferSize]={0};
  24. //接收OK标志
  25. volatile uint8_t RxOK = 0;


  26. /*******************************************************************************
  27. * Function Name  : USART2_IRQHandler
  28. * Description    : This function handles USART2 global interrupt request.
  29. * Input          : None
  30. * Return         : None
  31. *******************************************************************************/
  32. void USART1_IRQHandler(void)
  33. {
  34.     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //中断产生
  35.     {
  36.         RxBuffer[0] = USART_ReceiveData(USART1);               //接收数据
  37.         USART_ClearITPendingBit(USART1,USART_IT_RXNE);    //清除中断标志
  38.         RxOK = 1;
  39.         USARTx_SendByte(USART1,0x01);
  40.     }
  41. }
  42. /*******************************************************************************
  43. * Function Name  : main
  44. * Description    : Main program.
  45. * Input          : None
  46. * Return         : None
  47. *******************************************************************************/
  48. int main(void)
  49. {
  50.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  51.         Delay_Init();
  52.         User_Led_Init();
  53.     USART1_Init();
  54.     USARTx_SendStr(USART1, "This is a test data.\n");
  55.         while(1)
  56.         {
  57.             if(RxOK == 1)
  58.             {
  59.             if(RxBuffer[0] == 0x01)
  60.             {
  61.                 Toggle_User_Led(User_LED1);
  62.             }
  63.             RxOK = 0;
  64.             }
  65.         }
  66. }

将工程做了个打包,可以直接使用:
CH32V103-USART1.rar (446.25 KB, 下载次数: 16)

您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群: 嵌入式系统arm初学者 224636155←← +→→点击-->小 i 精品课全集,21ic公开课~~←←→→点击-->小 i 精品课全集,给你全方位的技能策划~~←←

2841

主题

19330

帖子

110

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