当前位置:   article > 正文

STM32F103RCT6开发板M3单片机教程03--usart串口通信

stm32f103rct6


USART电路说明



首先了解编译调试硬件连接,查看原理图
 


STM32F103RCT6开发板用Jlink供电,USB转串口板电脑USB供电,那么连接只需3线

*          TXD(PB9)     ->   USB转串口板RXD     
*           RXD(PB10) -> USB转串口T板XD      
*           GND       -> USB转串口板GND
 

编写代码

  • 复制上节工程文件夹打开(这个方法比较方便)
  • 新建源文件usart.c,添加usart.c到BSP(Grounp),并编辑
    1. ​​​​​​​/**********************************************************************************
    2. * 文件名  :usart.c
    3. * 描述    :usart1 应用函数库         
    4. * 实验平台:SUN_STM32F1板
    5. * 硬件连接:TXD(PB9)  -> USB转串口板RXD     
    6. *           RXD(PB10) -> USB转串口T板XD      
    7. *           GND           -> USB转串口板GND
    8. * 库版本  :ST_v3.5
    9. * Version    Date       Auther      Reversed History
    10.   ----------------------------------------------------------------------------
    11.   V1.0.0    2021-11-07  Lojam Fan  Fisrt Created
    12.   
    13. * (C) Sunshine Silicon Corporation
    14. *  Website: http://www.sunsili.com  http://sunsili.taobao.com http://bbs.sunsili.com
    15. *  E-Mail : fan@sunsili.com
    16. **********************************************************************************/
    17. #include "usart.h"   
    18. vu8 Usart1_R_Buff[USART1_REC_MAXLEN];        //串口1数据接收缓冲区
    19. vu8 Usart1_R_State=0;     //串口1接收状态
    20. vu16 Usart1_R_Count=0;     //当前接收数据的字节数           
    21. /*******************************************************************************
    22. * 函数名  : USART1_Init_Config
    23. * 描述    : USART1初始化配置
    24. * 输入    : bound:波特率(常用:2400、4800、9600、19200、38400、115200等)
    25. * 输出    : 无
    26. * 返回    : 无
    27. * 说明    : 无
    28. *******************************************************************************/
    29. void USART1_Init_Config(u32 bound)
    30. {
    31.     GPIO_InitTypeDef  GPIO_InitStructure;
    32.         USART_InitTypeDef USART_InitStructure;
    33.         NVIC_InitTypeDef  NVIC_InitStructure;
    34.         /*使能USART1和GPIOA外设时钟*/  
    35.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
    36.         /*复位串口1*/
    37.          USART_DeInit(USART1);          
    38.         /*USART1_GPIO初始化设置*/
    39.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;    //USART1_TXD(PA.9)    
    40.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     //复用推挽输出
    41.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚输出最大速率为50MHz
    42.     GPIO_Init(GPIOA, &GPIO_InitStructure);   //调用库函数中的GPIO初始化函数,初始化USART1_TXD(PA.9)  
    43.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;    //USART1_RXD(PA.10)
    44.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //浮空输入
    45.     GPIO_Init(GPIOA, &GPIO_InitStructure);       //调用库函数中的GPIO初始化函数,初始化USART1_RXD(PA.10)
    46.    /*USART1 初始化设置*/
    47.         USART_InitStructure.USART_BaudRate = bound;      //设置波特率
    48.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;     //8位数据格式
    49.         USART_InitStructure.USART_StopBits = USART_StopBits_1;     //1个停止位
    50.         USART_InitStructure.USART_Parity = USART_Parity_No;         //无奇偶校验位
    51.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;        //无硬件数据流控制
    52.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;     //工作模式设置为收发模式
    53.     USART_Init(USART1, &USART_InitStructure);    //初始化串口1
    54.    /*Usart1 NVIC配置*/
    55.     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    56.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1//抢占优先级3
    57.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;      //从优先级3
    58.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        //IRQ通道使能
    59.         NVIC_Init(&NVIC_InitStructure);      //根据指定的参数初始化VIC寄存器         
    60.     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);           //使能串口1接收中断
    61.     USART_Cmd(USART1, ENABLE);                            //使能串口
    62.         USART_ClearFlag(USART1, USART_FLAG_TC);            //清除发送完成标志
    63. }
    64. /*******************************************************************************
    65. * 函数名  : USART_SendData
    66. * 描述    : USART1发送数据缓冲区数据
    67. * 输入    : *buff:数据缓冲区指针,len:发送数据长度
    68. * 输出    : 无
    69. * 返回    : 无
    70. * 说明    : 无
    71. *******************************************************************************/
    72. void USART1_SendData(u8* buff, u16 len)
    73. {   
    74.         u16 i;
    75.         for(i=0; i<len; i++)  
    76.         {
    77.                 while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
    78.             USART_SendData(USART1 ,buff[i]);   
    79.         }
    80. }
    81. /*******************************************************************************
    82. * 函数名  : USART1_IRQHandler
    83. * 描述    : 串口1中断服务程序
    84. * 输入    : 无
    85. * 返回    : 无
    86. * 说明    : 1)、只启动了USART1中断接收,未启动USART1中断发送。
    87. *           2)、接收到0x0d 0x0a(回车、"\r\n")代表帧数据接收完成
    88. *******************************************************************************/
    89. void USART1_IRQHandler(void)  
    90. {
    91.         u8 Res=0;
    92.         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    93.         {
    94.                 Res =USART_ReceiveData(USART1); //读取接收到的数据(USART1->DR)              
    95.                 Usart1_R_Buff[Usart1_R_Count++] = Res;
    96.                 if(Usart1_R_State == 0)//数据接收未完成
    97.                 {
    98.                         if(Res == 0x0d)//接收到0x0d,下一个字节接收到0x0a则接收完成
    99.                         {
    100.                                 Usart1_R_State =2;
    101.                         }
    102.                 }
    103.                 else if(Usart1_R_State == 2)
    104.                 {
    105.                         if(Res == 0x0a)//上一个字节接收到0x0d,这个字节接收到oxoa则接收完成
    106.                         {
    107.                                 Usart1_R_State =1;//数据接收完成
    108.                         }
    109.                         else//接收错误
    110.                         {
    111.                                 Usart1_R_State =0;
    112.                                 Usart1_R_Count =0;
    113.                         }
    114.                 }
    115.                 if(Usart1_R_Count >= USART1_REC_MAXLEN)//接收数据长度走出接收数据缓冲区
    116.                 {
    117.                         if((Usart1_R_Buff[USART1_REC_MAXLEN-2] != 0x0d) || (Usart1_R_Buff[USART1_REC_MAXLEN-1] != 0x0a))
    118.                         {
    119.                                 Usart1_R_Count =0;
    120.                                 Usart1_R_State =0;
    121.                         }
    122.                 }                 
    123.         }
    124. }         
    125. /******************* (C) COPYRIGHT SUNSHINE SILICON  **************************
    126. ********************        END OF FILE usart.c        *******************/

    复制代码
  • 新建源文件usart.h,并编辑
    1. #ifndef __USART_H
    2. #define __USART_H
    3. #include "stm32f10x.h"
    4. #include <stdio.h>
    5. #define USART1_REC_MAXLEN 200        //最大接收数据长度
    6. void USART1_Init_Config(u32 bound);
    7. void USART1_SendData(u8* buff, u16 len);
    8. //int fputc(int ch, FILE *f);
    9. //void USART1_printf(USART_TypeDef* USARTx, uint8_t *Data,...);
    10. #endif
    11. /******************* (C) COPYRIGHT SUNSHINE SILICON  **************************
    12. ********************        END OF FILE usart.h        *******************/

    复制代码
  • 编辑main.c
    1. /**********************************************************************************
    2. * Sun STM32 mini Demo
    3. *   Description   
    4.     Uart Demo   
    5. * Version    Date       Auther      Reversed History
    6.   ----------------------------------------------------------------------------
    7.   V1.0.0    2021-11-07  Lojam Fan  Fisrt Created
    8.   
    9. * (C) Sunshine Silicon Corporation
    10. *  Website: http://www.sunsili.com  http://sunsili.taobao.com http://bbs.sunsili.com
    11. *  E-Mail : fan@sunsili.com
    12. **********************************************************************************/
    13. #include "stm32f10x.h"
    14. #include "usart.h"
    15. #include "SysTick.h"
    16. #include "led.h"
    17. #include <stdio.h>
    18. extern vu8 Usart1_R_Buff[USART1_REC_MAXLEN];        //串口1数据接收缓冲区
    19. extern vu8 Usart1_R_State;                                                //串口1接收状态
    20. extern vu16 Usart1_R_Count;                                                //当前接收数据的字节数         
    21. /*******************************************************************************
    22. * 函数名  : main
    23. * 描述    : 主函数,用户程序从main函数开始运行
    24. * 输入    : 无
    25. * 输出    : 无
    26. * 返回值  : int:返回值为一个16位整形数
    27. * 说明    : 无
    28. *******************************************************************************/
    29. int main(void)
    30. {
    31.     SysTick_Init_Config();
    32.         USART1_Init_Config(115200);//USART1初始化配置
    33.     LED_GPIO_Config();
    34.     printf ("*===================================================*\n");
    35.     printf ("*  *  Name: Sun STM32 mini Demo Code.    *************\n");
    36.     printf ("*  * (C) Sunshine Silicon Corporation    *************\n");
    37.     printf ("*  *  Website: http://www.sunsili.com    *************\n");
    38.     printf ("*  *   E-Mail : fan@sunsili.com          *************\n");
    39.     printf ("*===================================================*\n");
    40.     printf ("* Sun STM32 mini uart transmit the same data to PC .*\n");
    41.         while (1)
    42.         {
    43.                 if(Usart1_R_State == 1)//一帧数据接收完成
    44.                 {
    45.                         USART1_SendData((u8 *)Usart1_R_Buff, Usart1_R_Count);   //USART1发送数据缓冲区数据(发送刚接收完成的一帧数据)
    46.                         Usart1_R_State =0;
    47.                         Usart1_R_Count =0;
    48.                 }
    49.         
    50.         printf("Hello Sunshine Silicon!\r");
    51.         LED4_ON();
    52.         Delay_nMs(500);
    53.         LED4_OFF();
    54.         Delay_nMs(500);
    55.         }
    56. }
    57. /******************* (C) COPYRIGHT SUNSHINE SILICON  **************************
    58. ********************        END OF FILE main.c        *******************/

    复制代码

编译调试

方法不再重复,经过前两节练习,大家应该是会了.
但发现程序不跑了,单调试发现程序卡在printf不动了。为什么呢?因为MCU不像电脑只要添加stdio.h, 就能用printf。MCU要重定向c库函数printf到USART1(不一定USART1,实际用哪个定义到哪个),标准库代码内容还会被优化掉,编译时不输出。如何让它跑起来了呢。
在usart.c中添加函数

  1. ///重定向c库函数printf到USART1
  2. int fputc(int ch, FILE *f)
  3. {
  4.                 /* 发送一个字节数据到USART1 */
  5.                 USART_SendData(USART1, (uint8_t) ch);
  6.                
  7.                 /* 等待发送完毕 */
  8.                 while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);               
  9.         
  10.                 return (ch);
  11. }
  12. ///重定向c库函数scanf到USART1
  13. int fgetc(FILE *f)
  14. {
  15.                 /* 等待串口1输入数据 */
  16.                 while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
  17.                 return (int)USART_ReceiveData(USART1);
  18. }

复制代码


设置编译时,加入MCU适用标准库函数

 



再次编译调试一切如愿。符合我们当初的设计。

工程下载

查看原文,可下载工程源码

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号