STM32CubeIDE LL庫實現串口收發

接之前的HAL庫串口篇:https://blog.csdn.net/u010779035/article/details/103764852 

目錄

前言

一、MX配置

二、生成的代碼

三、用戶代碼

小結


前言

在某次實踐中,使用HAL庫中斷接收,會出現不少毛病,查了硬件軟件看起來都沒問題,考慮了一下可能是HAL庫函數的操作耗時過長等原因。無奈之下,嘗試使用了LL庫,問題不再復現。LL庫的使用其實就相當於直接操作寄存器,沒有過多的自定義狀態變量使用。另外,MX中,可以爲多個串口分別選配HAL庫和LL庫驅動。

一、MX配置

串口參數

使能全局中斷

選擇LL庫

二、生成的代碼

由於我同時選擇了LL庫的GPIO,所以GPIO的配置同樣也使用了LL庫。

在初始化函數中,已經配置好串口1、中斷向量表、使能串口1。接下來需要用戶自己使能中斷。

三、用戶代碼

1、<usart.h> 自定義接收緩存

/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */

/* USER CODE BEGIN Private defines */
#define USART_REC_LEN  			200  		//定義最大接收字節數 200
extern uint8_t  USART_RX_BUF[USART_REC_LEN]; 	//接收緩衝
/* USER CODE END Private defines */

/* USER CODE BEGIN Prototypes */
void Uart1_SendStr(char*SendBuf);
void uart1_revice_my_data(void);
/* USER CODE END Prototypes */

2、<usart.c> 實現printf、字符串發送、消息頭接收

/* USER CODE BEGIN 0 */
uint8_t USART_RX_BUF[USART_REC_LEN];     //接收緩衝

uint8_t flag;
uint8_t state;
uint8_t recv_cnt;
uint16_t header;
uint8_t pkt_len;
/* USER CODE END 0 */

/* USER CODE BEGIN 1 */
#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  //HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
  LL_USART_TransmitData8(USART1,(uint8_t)ch);
  return ch;
}


//#define USR_USE_HAL
#ifdef USR_USE_HAL
void Uart1_SendStr(char*SendBuf)//串口1發送字符串
{
  while(*SendBuf)
  {
    while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=1);//等待發送完成
    HAL_UART_Transmit(&huart1,(uint8_t*)SendBuf,1,1000);//發送數據
    SendBuf++;
  }
}
#else
void Uart1_SendStr(char*SendBuf)//串口1發送字符串
{
  while(*SendBuf)
  {
    while(LL_USART_IsActiveFlag_TC(USART1)!=1);//等待發送完成
    LL_USART_TransmitData8(USART1,(uint8_t)(*SendBuf & (uint8_t)0xff));//發送數據
    SendBuf++;
  }
}
#endif

void uart1_revice_my_data(void)
{
  uint8_t Res = LL_USART_ReceiveData8(USART1);
  if(flag!=1)
  {
    if(state==0)
      {//未收到包頭
	if(Res == 0xfc)
	  {
	    header = 0x00fc;
	  }
	else if(Res ==0xfe)
	  {
	    header=(header<<8)|Res;
	    if(header==0xfcfe)
	    {//收到包頭
	      state=1;
	      USART_RX_BUF[0]=0xfc;
	      USART_RX_BUF[1]=0xfe;
	      recv_cnt=2;
	    }
	  }
	else
	  {
	    header=0;
	  }
      }
    else if(state==1)
      {//收到包頭未收到長度
	pkt_len=Res;
	USART_RX_BUF[recv_cnt++]=pkt_len;
	state=2;
      }
    else if(state==2)
      {//收到包頭且收到長度
	USART_RX_BUF[recv_cnt++]=Res;
	if(recv_cnt==pkt_len)
	  {
	    flag=1;
	    state=0;
	    recv_cnt=0;
	  }
      }
  }
}
/* USER CODE END 1 */

3、<stm32f1xx_it.c> 串口中斷響應

/* USER CODE BEGIN Includes */
#include "usart.h"
/* USER CODE END Includes */

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  /* USER CODE BEGIN USART1_IRQn 1 */

  uart1_revice_my_data();//在此加入這段函數,分析接收到的數據

  /* USER CODE END USART1_IRQn 1 */
}

4、<main.c> 使能接收中斷、分析接收到的數據

int main(void)
{

...

LL_USART_EnableIT_RXNE(USART1);//使能串口接收中斷

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    if(flag == 1)
    {
	massage_analysis();//自定義協議分析
	flag = 0;
    }
  }
  /* USER CODE END 3 */
}

小結

發送數據:LL_USART_TransmitData8(USART1,(uint8_t)ch);

接收數據:uint8_t Res = LL_USART_ReceiveData8(USART1);//阻塞模式和中斷模式或者DMA都適用

開啓接收中斷:LL_USART_EnableIT_RXNE(USART1);

判斷髮送完成:LL_USART_IsActiveFlag_TC(USART1) //返回值1爲完成,0爲未完成。

 

使能串口:LL_USART_Enable(USART1);

使能串口中斷:NVIC_EnableIRQ(USART1_IRQn);

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章