stm32F103 串口中断接收和发送(不定长度)

       上一篇“stm32L431 串口中断接收和发送(不定长度)”文章写后,想想还是把“stm32F103 串口中断接收和发送(不定长度)”也写一下,想法和做法与上一篇完全一致,只是“stm32L431” 与“stm32F103”串口相关寄存器略有差异

      主导思想是:

         1、用STM32CubeMX完成IO口串口初始化。

         2、用串口相关寄存器直接操作替代HAL库(本人不喜欢也不太懂HAL库)调用。

         3、支持printf()函数

         4、串口中断

         接收中断:只负责将接收到的数据存入“接收输入指针”指向的接收缓冲区数组,同时置“接收完成标志”“接收输入指针”加1。在主程序中从接收缓冲区数组读接收数据时“接收输出指针”加1,当“接收输出指针”等于“接收输入指针”时清“接收完成标志”

         发送中断:如果“发送输出指针”指向的发送缓冲区数组有待发送数据就发送,同时清”接收完成标志““发送输出指针”加1 。没有待发送数据(“发送输出指针”等于“发送输入指针”)置“发送完成标志"。在主程序中发送数据时,将待发送数据写入“发送输入指针”指向的发送缓冲区,同时”清”发送完成标志“同时允许发送中断。

    具体操作:

 1、由STM32CubeMX生成Keil工程“STM32F103_TEST”

 

2、新建“STM32F103_Uart.H、STM32F103_Uart.C”两个文件,添加“STM32F103_Uart.C"至工程。“STM32F103_Uart.H、STM32F103_Uart.C”两个文件的代码7、代码8(在后边)  

 

 

3、在STM32CubeMX生成文件中添加代码

***所有添加的代码均放在    /* USER CODE BEGIN  ---------- */和/* USER CODE END  ---------- */之间,以防止STM32CubeMX生成文件时修改***

在“main.c”中添加代码1、2、3、4、5

代码1 :增加所需的头文件

/* USER CODE BEGIN Includes */
#include "stdio.H"
#include "STM32F103_Uart.H"
/* USER CODE END Includes */

代码2: 变量定义

  /* USER CODE BEGIN 1 */
    unsigned char Temp_Data;
  /* USER CODE END 1 */

代码3:初始化中断收发服务程序所需的收、发缓冲区数组及全局变量 

  /* USER CODE BEGIN 2 */
    Init_Serial_Port();
  /* USER CODE END 2 */

代码4:简单的测试程序。收什么发什么,ASC字符、汉字、控制字符均可。

  /* USER CODE BEGIN WHILE */

    printf("HelloWorld!\n");
    while (1)
    {
        if (Recv_End == 1)
        {
            Temp_Data = Serial_In();
            Serial_Out(Temp_Data);
        }
	  
	  /* USER CODE END WHILE */

代码5:支持printf()函数;

/* USER CODE BEGIN 4 */
int fputc(int ch, FILE *f)
{
    Serial_Out(ch);
    return ch;
}
int fgetc(FILE *f)
{
    unsigned char Temp_Data;
    Temp_Data = Serial_In();
    return Temp_Data;
}
/* USER CODE END 4 */

在“stm32f1xx_it.c”中添加代码6、7

代码6:增加 包含void USART1_IRQHandler(void)所需”数组及全局变量“的头文件 

/* USER CODE BEGIN Includes */
#include "STM32F103_Uart.H"
/* USER CODE END Includes */

代码7:串口1中断收发服务程序。

 其中“HAL_UART_IRQHandler(&huart1);”由STM32CubeMX生成,由于在其前面有”return ;"存在,永远不会被调用,会产生本工程编译时唯一的警告“../Core/Src/stm32f1xx_it.c(233): warning:  #111-D: statement is unreachable“,不用理会(管也没用,STM32CubeMX还改回来)。

  /**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
    if(USART1->SR&USART_SR_RXNE)//接收到数据
    {  

       Recv_Buf[Recv_In_Pointer]=USART1->DR;
       Recv_In_Pointer=(Recv_In_Pointer+1)%RECV_BUF_LEN;
       Recv_End=1;                                         //置串行口接收完成标志
    }

    if(USART1->SR&USART_SR_TC)// 发送中断
    {             
       USART1->SR&=(~USART_SR_TC);                              //清中断发送完成中断标志(TC)
       Trans_Out_Pointer=(Trans_Out_Pointer+1)%TRANS_BUF_LEN;
       if (Trans_In_Pointer==Trans_Out_Pointer)            //发送缓冲区中没有数据
       {                                                                            
           Trans_End=1;                                    //置串行口发送完成标志
           USART1->CR1&=(~USART_CR1_TCIE);                 //关闭发送完成中断允许(TCIE)     
       }
       else                                                //发送缓冲区中有数据
       {
           USART1->DR=Trans_Buf[Trans_Out_Pointer];            //发送缓冲区中的数据
           Trans_End=0;                                        //清串行口发送完成标志
       }
    }
   return   ;
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

新建“STM32F103_Uart.H”

代码8:STM32F103_Uart.H

#ifndef __STM32F103_Uart_H
#define __STM32F103_Uart_H


//***************************用户设置串行口参数开始****************************
#define RECV_BUF_LEN	512		//设置接收缓冲器长度 
#define TRANS_BUF_LEN	512		//设置发送缓冲器长度 
//***************************用户设置串行口参数结束****************************

//函数定义
extern void Init_Serial_Port(void);
extern unsigned char Serial_In(void);
extern void Serial_Out(unsigned char Serial_Out_Data);

extern unsigned char Recv_Buf[RECV_BUF_LEN];        	//串行口1环形接收数据缓冲区
extern unsigned char Trans_Buf[TRANS_BUF_LEN];      	//串行口1环形发送数据缓冲区
extern unsigned int  Recv_In_Pointer, Recv_Out_Pointer;        	//串行口1环形接收缓冲区输入、输出指针。全局变量
extern unsigned int  Trans_In_Pointer, Trans_Out_Pointer;      	//串行口1环形发送缓冲区输入、输出指针。全局变量

//串行口工作标志
extern unsigned char Recv_End;                          //串行口1接收完成标志。全局变量
extern unsigned char Trans_End;                         //串行口1发送完成标志。全局变量

#endif

新建“STM32F103_Uart.C”

代码9:STM32F103_Uart.C

#include "STM32F103_Uart.H"
#include "main.h"

unsigned char Recv_Buf[RECV_BUF_LEN];        				//串行口1环形接收数据缓冲区
unsigned char Trans_Buf[TRANS_BUF_LEN];      				//串行口1环形发送数据缓冲区
unsigned int  Recv_In_Pointer, Recv_Out_Pointer;        	//串行口1环形接收缓冲区输入、输出指针。全局变量
unsigned int  Trans_In_Pointer, Trans_Out_Pointer;      	//串行口1环形发送缓冲区输入、输出指针。全局变量

//串行口工作标志
unsigned char Recv_End, Trans_End;                         //串行口1接收、发送完成标志。全局变量

void Init_Serial_Port(void);
unsigned char Serial_In(void);
void Serial_Out(unsigned char Serial_Out_Data);
//*****************************************************************************
void Init_Serial_Port(void)	//串行口初始化函数
{
    Trans_End = 1;
    Recv_End = 0;
    Recv_In_Pointer = 0;				//接收缓冲区输入、输出指针
    Recv_Out_Pointer = Recv_In_Pointer;
    Trans_In_Pointer = 0;				//发送缓冲区输入、输出指针
    Trans_Out_Pointer = Trans_In_Pointer;
    USART1->CR1 |= USART_CR1_RXNEIE;	//允许接收中断
    USART1->CR1 &= (~USART_CR1_TCIE); 	//关闭发送中断
    USART1->SR |= USART_SR_TC; 			//置发送完成标志
}
//*****************************************************************************
unsigned char Serial_In(void)
{
    unsigned char Temp_Data;
    while ( Recv_Out_Pointer == Recv_In_Pointer )
    {
    }
    //没有数据等待。
    Temp_Data = Recv_Buf[Recv_Out_Pointer];                  //从接收缓冲区中取数据
    Recv_Out_Pointer = (Recv_Out_Pointer + 1) % RECV_BUF_LEN; //
    if ( Recv_Out_Pointer == Recv_In_Pointer )
    {
        Recv_End = 0;
    }
    return Temp_Data;
    //返回接收数据
}
//*****************************************************************************
void Serial_Out(unsigned char Serial_Out_Data)
{
    while ( ((Trans_In_Pointer + 1) % TRANS_BUF_LEN) == Trans_Out_Pointer )//发送缓冲区满时等待
    {
    }
    if (Trans_End == 1)
    {
        USART1->DR = Serial_Out_Data;
        USART1->CR1 |= USART_CR1_TCIE;    			//使能发送中断(TCIE)

        Trans_Buf[Trans_In_Pointer] = Serial_Out_Data;  			//发送数据进入发送缓冲区(在中断程序发送数据)
        Trans_In_Pointer = (Trans_In_Pointer + 1) % TRANS_BUF_LEN; //发送缓冲区输入指针加1
        Trans_End = 0;                                  			//清发送结束标志
    }
    else
    {
        Trans_Buf[Trans_In_Pointer] = Serial_Out_Data;    			//发送数据进入发送缓冲区(在中断程序发送数据)
        Trans_In_Pointer = (Trans_In_Pointer + 1) % TRANS_BUF_LEN; //发送缓冲区输入指针加1
    }
}

编译

4、编译后下载

 

 对不对请您试试,我试是对的,谢谢!!!

STM32L431微控制器是一款基于Arm Cortex-M4F内核的32位微控制器,它集成了USART (通用同步/异步收发器)功能,可用于串行通信。串口中断接收发送不定长度的数据通常涉及以下几个步骤: 1. **配置USART**: 首先,你需要在STM32L4的HAL库中初始化USART,设置波特率、数据位数、停止位以及校验模式等参数。 ```c HAL_UART_Init(&huart1); ``` 2. **开启中断**: 激活USART接收发送中断,以便在有数据传输时响应。 ```c HAL_NVIC_EnableIRQ(UARTx_IRQn); // x替换为你使用的USART端口号 ``` 3. **设置中断处理函数**: 这里会定义一个处理USART中断的回调函数,例如`UARTRxHandler`,它会在接收到数据时被调用。 ```c void UARTRxHandler(void) { uint8_t received_data = HAL_UART_Receive(&huart1, &rx_buffer, 1, timeout); // 接收并保存数据 // 处理接收到的数据... } ``` 4. **中断服务程序** (`UARTx_IRQHandler`): 当串口接收到数据或发送完成时,会触发这个服务程序。你可以在这里检查接收到的数据长度,并相应地处理。 5. **发送数据**: 对于不定长度的数据发送,你需要先准备好数据,然后在适当的时候调用`HAL_UART_Transmit()`函数。 6. **错误处理**: 别忘了处理可能出现的错误,如超时、硬件故障等。 7. **设置接收缓冲区**: 如果数据长度不确定,可以使用环形缓冲区来存储接收到的数据,直到完整的帧到达。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值