串口通信(USART)程序代码

本文是STM32F103RCT6与上位机进行串口通信(USART)时的程序代码的笔记总结。文中的代码是从芯片STM32F103ZET6的代码中移植过来的,已经过实验验证,可以正常运行。

一、usart.h 文件

#ifndef __USART_H
#define __USART_H
#include "stdio.h"    
#include "sys.h"

#define USART_REC_LEN        200             //声明最大接收字节数 200
#define EN_USART1_RX             1              //使能(1)/禁止(0)串口1接收
          
extern u8  USART_RX_BUF[USART_REC_LEN];     //声明接收缓冲数组,最大200个字节
extern u16 USART_RX_STA;                       //接收状态标记    
extern UART_HandleTypeDef   UART1_Handler;     //UART句柄

#define RXBUFFERSIZE   1                         //声明缓存大小
extern u8 aRxBuffer[RXBUFFERSIZE];        //声明HAL库的USART接收Buffer


void uart_init(u32 bound);
#endif

二、usart.c 文件

#include "sys.h"
#include "usart.h"    

#if 1
#pragma import(__use_no_semihosting)             //标准库需要的支持函数                 
struct __FILE 

    int handle; 

}; 

FILE __stdout;                                                       //定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 

    x = x; 
}                                                                            //重定义fputc函数 
int fputc(int ch, FILE *f)
{      
    while ((USART1->SR & 0X40) == 0);               //循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
    return ch;
}
#endif 


#if EN_USART1_RX                                              //如果使能了接收 
u8 USART_RX_BUF[USART_REC_LEN];            //接收缓冲,最大USART_REC_LEN个字节.
u16 USART_RX_STA=0;                                       //接收状态标记      

u8 aRxBuffer[RXBUFFERSIZE];                           //HAL库使用的串口接收缓冲
UART_HandleTypeDef UART1_Handler;             //UART句柄

//串口1 通信层初始化

void uart_init(u32 bound)

{    
    //UART 初始化设置
    UART1_Handler.Instance=USART1;                        //USART1
    UART1_Handler.Init.BaudRate=bound;                    //波特率
    UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
    UART1_Handler.Init.StopBits=UART_STOPBITS_1;        //一个停止位
    UART1_Handler.Init.Parity=UART_PARITY_NONE;        //无奇偶校验位
    UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
    UART1_Handler.Init.Mode=UART_MODE_TX_RX;        //收发模式
    HAL_UART_Init(&UART1_Handler);                               //HAL_UART_Init()会使能UART1
    HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);    
}

//串口1 底层初始化,包括时钟使能,引脚配置,中断配置

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    GPIO_InitTypeDef GPIO_Initure;


    if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
    {
        __HAL_RCC_GPIOA_CLK_ENABLE();            //使能GPIOA时钟
        __HAL_RCC_USART1_CLK_ENABLE();            //使能USART1时钟
        __HAL_RCC_AFIO_CLK_ENABLE();
    
        GPIO_Initure.Pin=GPIO_PIN_9;                              //PA9
        GPIO_Initure.Mode=GPIO_MODE_AF_PP;           //复用推挽输出
        GPIO_Initure.Pull=GPIO_PULLUP;                        //上拉
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;   //高速
        HAL_GPIO_Init(GPIOA,&GPIO_Initure);                //初始化PA9

        GPIO_Initure.Pin=GPIO_PIN_10;                          //PA10
        GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;    //模式要设置为复用输入模式!    
//        GPIO_Initure.Mode=GPIO_MODE_AF_PP;
        HAL_GPIO_Init(GPIOA,&GPIO_Initure);               //初始化PA10
        
#if EN_USART1_RX
        HAL_NVIC_EnableIRQ(USART1_IRQn);                //使能USART1中断通道
        HAL_NVIC_SetPriority(USART1_IRQn,3,3);           //抢占优先级3,子优先级3
#endif    
    }
}

//串口1 回调函数,用于编写控制逻辑

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance==USART1)                                       //如果是串口1
    {
        if((USART_RX_STA&0x8000)==0)                           //接收未完成
        {
            if(USART_RX_STA&0x4000)                               //接收到了0x0d
            {
                if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;    //接收错误,重新开始
                else USART_RX_STA|=0x8000;                    //接收完成了 
            }
            else                                                                    //还没收到0X0D
            {    
                if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
                else
                {
                    USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
                    USART_RX_STA++;
                    if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;

                                                                                      //接收数据错误,重新开始接收      
                }         
            }
        }
    }
}

//串口1 中断服务程序

void USART1_IRQHandler(void)                    

#if SYSTEM_SUPPORT_OS         //使用OS
    OSIntEnter();    
#endif


    u32 timeout=0;
    HAL_UART_IRQHandler(&UART1_Handler);            //调用HAL库中断处理公用函数
    
    timeout=0;
    while (HAL_UART_GetState(&UART1_Handler) != HAL_UART_STATE_READY)
    {
     timeout++;超时处理
     if(timeout>HAL_MAX_DELAY) break;        
    }
     
    timeout=0;
    while(HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)                                     //一次处理完成之后,重新开启中断并设置RxXferCount为1
    {
     timeout++; //超时处理
     if(timeout>HAL_MAX_DELAY) break;    
    }
#if SYSTEM_SUPPORT_OS         //使用OS
    OSIntExit();                                               
#endif

#endif    

三、main.c 文件

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"

int main(void)
{
    u8 len;    
    u16 times=0;
    
    HAL_Init();                             //初始化HAL库    
    Stm32_Clock_Init(RCC_PLL_MUL9);       //设置时钟,72M
    delay_init(72);                       //初始化延时函数
    uart_init(115200);                  //初始化串口
    LED_Init();                            //初始化LED    

while(1)
    {
       if(USART_RX_STA&0x8000)
        {                       
            len=USART_RX_STA&0x3fff;                        //得到此次接收到的数据长度
            printf("\r\n您发送的消息为:\r\n");
            HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000);  

                                                                                   //发送接收到的数据
            while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET);                                                                                         //等待发送结束
            printf("\r\n\r\n");//插入换行
            USART_RX_STA=0;
        }
        else
        {
            times++;
            if(times%5000==0)
            {
                printf("\r\n 串口实验\r\n");
                printf("wait receive\r\n\r\n\r\n");
            }
            if(times%200==0)printf("请输入数据,以回车键结束\r\n");  
            if(times%30==0)
                LED0=!LED0;                                               //闪烁LED,提示系统正在运行.
            delay_ms(10);   
        } 
    }
}

注意:本文是针对串口(USART)通信的程序代码,本文中没有关于LED程序代码,因此如果直接运行编译器会报错。需要在工程中添加LED的头文件和源文件才可以直接运行。在main.c文件中调用了LED的头文件和源文件,主要是为了指示程序正在运行,有关LED的代码在其他文中总结

备注:欢迎各位同学指正,有关串口通信的问题欢迎评论区留言,一起讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值