一、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);
}
}