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


USART电路说明



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


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

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

编写代码

  • 复制上节工程文件夹打开(这个方法比较方便)
  • 新建源文件usart.c,添加usart.c到BSP(Grounp),并编辑
    ​​​​​​​/**********************************************************************************
    
    * 文件名  :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-07  Lojam Fan  Fisrt Created
      
    
    * (C) Sunshine Silicon Corporation
    
    *  Website: http://www.sunsili.com  http://sunsili.taobao.com http://bbs.sunsili.com
    
    *  E-Mail : fan@sunsili.com
    
    **********************************************************************************/
    
    
    #include "usart.h"    
    
    vu8 Usart1_R_Buff[USART1_REC_MAXLEN];        //串口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_InitTypeDef  GPIO_InitStructure;
            USART_InitTypeDef USART_InitStructure;
            NVIC_InitTypeDef  NVIC_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[i]);   
            }
    }
    
    
    
    /*******************************************************************************
    
    * 函数名  : 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[Usart1_R_Count++] = 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[USART1_REC_MAXLEN-2] != 0x0d) || (Usart1_R_Buff[USART1_REC_MAXLEN-1] != 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-07  Lojam Fan  Fisrt Created
      
    
    * (C) Sunshine Silicon Corporation
    
    *  Website: http://www.sunsili.com  http://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[USART1_REC_MAXLEN];        //串口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适用标准库函数

 



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

工程下载

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

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值