sunsili 发表于 2021-11-7 22:36:14

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

本帖最后由 sunsili 于 2023-12-12 13:53 编辑

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


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

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

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


[*]复制上节工程文件夹打开(这个方法比较方便)
[*]新建源文件usart.c,添加usart.c到BSP(Grounp),并编辑

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


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


复制上节工程文件夹打开(这个方法比较方便)
新建源文件usart.c,添加usart.c到BSP(Grounp),并编辑
新建源文件SysTick.h,并编辑
编辑main.c
编译调试



/**********************************************************************************
* 文件名:usart.c
* 描述    :usart1 应用函数库         
* 实验平台:SUN_STM32F1板
* 硬件连接:TXD(PB9)-> USB转串口板RXD   
*         RXD(PB10) -> USB转串口T板XD      
*         GND         -> USB转串口板GND
* 库版本:ST_v3.5
* Version    Date       Auther      Reversed History
----------------------------------------------------------------------------
V1.0.0    2021-11-07Lojam FanFisrt Created

* (C) Sunshine Silicon Corporation
*Website: http://www.sunsili.comhttp://sunsili.taobao.com http://bbs.sunsili.com
*E-Mail : fan@sunsili.com
**********************************************************************************/

#include "usart.h"         
      
vu8 Usart1_R_Buff;      //串口1数据接收缓冲区
vu8 Usart1_R_State=0;                                        //串口1接收状态
vu16 Usart1_R_Count=0;                                        //当前接收数据的字节数         

/*******************************************************************************
* 函数名: USART1_Init_Config
* 描述    : USART1初始化配置
* 输入    : bound:波特率(常用:2400、4800、9600、19200、38400、115200等)
* 输出    : 无
* 返回    : 无
* 说明    : 无
*******************************************************************************/
void USART1_Init_Config(u32 bound)
{
    GPIO_InitTypeDefGPIO_InitStructure;
      USART_InitTypeDef USART_InitStructure;
      NVIC_InitTypeDefNVIC_InitStructure;
      
      /*使能USART1和GPIOA外设时钟*/
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);      

      /*复位串口1*/
         USART_DeInit(USART1);
      
      /*USART1_GPIO初始化设置*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                        //USART1_TXD(PA.9)   
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                //复用推挽输出
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //设置引脚输出最大速率为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);                              //调用库函数中的GPIO初始化函数,初始化USART1_TXD(PA.9)
   
   
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                              //USART1_RXD(PA.10)
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;      //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);                                        //调用库函数中的GPIO初始化函数,初始化USART1_RXD(PA.10)


   /*USART1 初始化设置*/
      USART_InitStructure.USART_BaudRate = bound;                                                                              //设置波特率
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;                                                //8位数据格式
      USART_InitStructure.USART_StopBits = USART_StopBits_1;                                                      //1个停止位
      USART_InitStructure.USART_Parity = USART_Parity_No;                                                                //无奇偶校验位
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;      //无硬件数据流控制
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                                        //工作模式设置为收发模式
    USART_Init(USART1, &USART_InitStructure);                                                                              //初始化串口1

   /*Usart1 NVIC配置*/
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;      //抢占优先级3
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                //从优先级3
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
      NVIC_Init(&NVIC_InitStructure);                                                      //根据指定的参数初始化VIC寄存器
         
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                        //使能串口1接收中断

    USART_Cmd(USART1, ENABLE);                                          //使能串口
      USART_ClearFlag(USART1, USART_FLAG_TC);                                        //清除发送完成标志
}


/*******************************************************************************
* 函数名: USART_SendData
* 描述    : USART1发送数据缓冲区数据
* 输入    : *buff:数据缓冲区指针,len:发送数据长度
* 输出    : 无
* 返回    : 无
* 说明    : 无
*******************************************************************************/
void USART1_SendData(u8* buff, u16 len)
{   
      u16 i;

      for(i=0; i<len; i++)
      {
                while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
            USART_SendData(USART1 ,buff);   
      }
}

/*******************************************************************************
* 函数名: USART1_IRQHandler
* 描述    : 串口1中断服务程序
* 输入    : 无
* 返回    : 无
* 说明    : 1)、只启动了USART1中断接收,未启动USART1中断发送。
*         2)、接收到0x0d 0x0a(回车、"\r\n")代表帧数据接收完成
*******************************************************************************/
void USART1_IRQHandler(void)                        
{
      u8 Res=0;

      if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
      {
                Res =USART_ReceiveData(USART1); //读取接收到的数据(USART1->DR)
               
                Usart1_R_Buff = Res;
                if(Usart1_R_State == 0)//数据接收未完成
                {
                        if(Res == 0x0d)//接收到0x0d,下一个字节接收到0x0a则接收完成
                        {
                              Usart1_R_State =2;
                        }
                }
                else if(Usart1_R_State == 2)
                {
                        if(Res == 0x0a)//上一个字节接收到0x0d,这个字节接收到oxoa则接收完成
                        {
                              Usart1_R_State =1;//数据接收完成
                        }
                        else//接收错误
                        {
                              Usart1_R_State =0;
                              Usart1_R_Count =0;
                        }
                }
                if(Usart1_R_Count >= USART1_REC_MAXLEN)//接收数据长度走出接收数据缓冲区
                {
                        if((Usart1_R_Buff != 0x0d) || (Usart1_R_Buff != 0x0a))
                        {
                              Usart1_R_Count =0;
                              Usart1_R_State =0;
                        }
                }                  
      }
}         


/******************* (C) COPYRIGHT SUNSHINE SILICON**************************
********************      END OF FILE usart.c      *******************/

[*]新建源文件usart.h,并编辑
#ifndef __USART_H
#define __USART_H

#include "stm32f10x.h"
#include <stdio.h>

#define USART1_REC_MAXLEN 200      //最大接收数据长度

void USART1_Init_Config(u32 bound);
void USART1_SendData(u8* buff, u16 len);
//int fputc(int ch, FILE *f);
//void USART1_printf(USART_TypeDef* USARTx, uint8_t *Data,...);

#endif



/******************* (C) COPYRIGHT SUNSHINE SILICON**************************
********************      END OF FILE usart.h      *******************/
[*]编辑main.c
/**********************************************************************************
* Sun STM32 mini Demo

*   Description
   
    Uart Demo

   
* Version    Date       Auther      Reversed History
----------------------------------------------------------------------------
V1.0.0    2021-11-07Lojam FanFisrt Created

* (C) Sunshine Silicon Corporation
*Website: http://www.sunsili.comhttp://sunsili.taobao.com http://bbs.sunsili.com
*E-Mail : fan@sunsili.com

**********************************************************************************/

#include "stm32f10x.h"
#include "usart.h"
#include "SysTick.h"
#include "led.h"
#include <stdio.h>

extern vu8 Usart1_R_Buff;      //串口1数据接收缓冲区
extern vu8 Usart1_R_State;                                                //串口1接收状态
extern vu16 Usart1_R_Count;                                                //当前接收数据的字节数         

/*******************************************************************************
* 函数名: main
* 描述    : 主函数,用户程序从main函数开始运行
* 输入    : 无
* 输出    : 无
* 返回值: int:返回值为一个16位整形数
* 说明    : 无
*******************************************************************************/
int main(void)
{
    SysTick_Init_Config();
      USART1_Init_Config(115200);//USART1初始化配置
    LED_GPIO_Config();
    printf ("*===================================================*\n");
    printf ("**Name: Sun STM32 mini Demo Code.    *************\n");
    printf ("** (C) Sunshine Silicon Corporation    *************\n");
    printf ("**Website: http://www.sunsili.com    *************\n");
    printf ("**   E-Mail : fan@sunsili.com          *************\n");
    printf ("*===================================================*\n");
    printf ("* Sun STM32 mini uart transmit the same data to PC .*\n");
      while (1)
      {
                if(Usart1_R_State == 1)//一帧数据接收完成
                {
                        USART1_SendData((u8 *)Usart1_R_Buff, Usart1_R_Count);   //USART1发送数据缓冲区数据(发送刚接收完成的一帧数据)
                        Usart1_R_State =0;
                        Usart1_R_Count =0;
                }
      
      printf("Hello Sunshine Silicon!\r");

      LED4_ON();
      Delay_nMs(500);
      LED4_OFF();
      Delay_nMs(500);
      }
}



/******************* (C) COPYRIGHT SUNSHINE SILICON**************************
********************      END OF FILE main.c      *******************/
[*]编译调试
方法不再重复,经过前两节练习,大家应该是会了.
但发现程序不跑了,单调试发现程序卡在printf不动了。为什么呢?因为MCU不像电脑只要添加stdio.h, 就能用printf。MCU要重定向c库函数printf到USART1(不一定USART1,实际用哪个定义到哪个),标准库代码内容还会被优化掉,编译时不输出。如何让它跑起来了呢。
在usart.c中添加函数
///重定向c库函数printf到USART1
int fputc(int ch, FILE *f)
{
                /* 发送一个字节数据到USART1 */
                USART_SendData(USART1, (uint8_t) ch);
               
                /* 等待发送完毕 */
                while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);               
      
                return (ch);
}

///重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
                /* 等待串口1输入数据 */
                while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

                return (int)USART_ReceiveData(USART1);
}
设置编译时,加入MCU适用标准库函数



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

工程源码(回复后可下载)
**** Hidden Message *****


微信用户 发表于 2024-1-20 13:07:40

支持一下

yangzs 发表于 2024-2-20 15:42:35

试一下                                                

rehuosheng 发表于 2024-3-12 11:13:02

谢谢分享!

零食 发表于 2024-3-28 08:41:16

感谢分享!

TiAmoXQ 发表于 2024-4-18 11:42:01

huoquyuanma

xl123 发表于 2024-4-19 09:49:46

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

寂然ing 发表于 2024-4-29 19:30:17

感谢分享
页: [1]
查看完整版本: STM32F103RCT6开发板M3单片机教程03--usart串口通信