STM32CubeIDE 利用自帶HAL庫 串口收發

 

一、MX的配置

1.選擇需要用的串口,模式Asynchronous,修改波特率爲115200;其他值默認即可。

2.配置中斷:2位搶佔優先級,2位優先級;全局中斷使能勾上。

另:最好設置一下不同外設單獨C文件

 

二、案例1(以 0x0d 0x0a結尾的 開源原子的做法)

2.1  <usart.c>

uint8_t aRxBuffer[1];

uint8_t temp=0;
uint8_t USART_RX_BUF[USART_REC_LEN];   //接收緩衝
//接收狀態位
//bit15接收完成標誌
//bit14接收了0x0d
//bit13~0接收到的有效字節數目
uint16_t USART_RX_STA=0;//接收狀態

另附實現printf的方法

#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.
  * @param  None
  * @retval None
  */
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);

  return ch;
}

2.2 <usart.h>

#define USART_REC_LEN  			200  		//定義最大接收字節數 200

extern uint8_t temp;

extern uint8_t  USART_RX_BUF[USART_REC_LEN]; 	//接收緩衝
extern uint16_t USART_RX_STA;         			//接收狀態

extern uint8_t aRxBuffer[1];			//HAL庫USART接收Buffer

2.3 <main.c>

HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);

while(1)
{
	if(USART_RX_STA&0x8000)
	{
	    len=USART_RX_STA&0x3fff;//計算長度
	    printf("\r\nsend:\r\n");
	    HAL_UART_Transmit(&huart1,(uint8_t*)USART_RX_BUF,len,1000);	//發送
	    while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);		//等待發送完成
	    USART_RX_STA=0;
	}
}


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{

  if(UartHandle == &huart1)//如果是串口1
  {
      //原子的協議 0d 0a結尾
    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;//接收數據錯誤,重新開始接收
			}
		}
	}
      

    HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
  }
}

三、案例2 上位機發啥就回啥

//代碼1中修改回調函數即可,while(1)內爲空
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 1,0xFFFF);
    HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
}

四、案例3 消息頭(0xfc 0xfe)+ 長度 + 消息內容

修改案例1的<main.c>,其他文件可以一致

//變量定義
uint8_t flag; //接收結束標誌
static uint8_t state; //消息接收狀態
static uint8_t recv_cnt; //從消息頭開始,消息已經接收的長度
static uint16_t header; //消息頭
static uint8_t pkt_len; //消息長度

//開啓接收中斷
HAL_UART_Receive_IT(&huart1,(uint8_t *)aRxBuffer, 1);//HAL庫中接收中斷函數,內部開啓了中斷,並將數據存儲在aRxBuffer,現在在aRxBuffer就緩存一個Byte,該函數只有接收完纔會調用回調函數

while(1)
{
  if(flag==1)
	{
	    HAL_Delay(5);//不可刪除  DO NOT DELET!!! 該延遲避免消息後的冗餘數據導致中斷響應錯誤
	    printf("\r\nsend:\r\n");
	    HAL_UART_Transmit(&huart1,(uint8_t*)USART_RX_BUF,pkt_len,1000);	//發送接收的數據
	    while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);		//等待發送完成
	    flag=0;
	}
}

//回調函數
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
  if(UartHandle == &huart1)//如果是串口1
  {
    if(flag!=1)//未按照長度接收結束
	{
	if(state==0)
	  {//未收到包頭
	    if(aRxBuffer[0] ==0xfc)
	      header = 0x00fc;
	    else if(aRxBuffer[0] ==0xfe)
	      {
		    header=(header<<8)|aRxBuffer[0];
		    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=aRxBuffer[0];
	    USART_RX_BUF[recv_cnt++]=pkt_len;
	    state=2;
	  }
	else if(state==2)
	  {//收到包頭且收到長�?
	    USART_RX_BUF[recv_cnt++]=aRxBuffer[0];
	    if(recv_cnt==pkt_len)
	      {//接收完畢,後面的數據都會丟棄直到收到新的頭
		    flag=1;
		    state=0;
		    recv_cnt=0;
	      }
	  }

    }
    HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
  }
}

 

 

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