在CubeMx生成代碼時,預設為 HAL 庫,但也可以指定為 LL庫,LL庫基本是直接操作寄存器,功能較為單一,但是效率更高。序列槽使用HAL如果每次接收一個字次,由于HAL庫的效率,容易丢包,若一次性接收多個位元組,又需要固定的位元組數。
于是這次使用了 LL 庫,在LL庫中:
LL_USART_TransmitData8();
為發送一個位元組函數,通過檢視定義可知,它直接操作了DR寄存器,是以效率很高。
這次想設計一個簡單的程式:當收到字元A的時,發送字元E,但是發現居然有丢包的現象,這是由于程式邏輯問題導緻的,這也是庫函數使用者對寄存器操作不熟悉的原因,最後調整程式如下:
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
static uint8_t recv;
if(USART1->SR&(1<<5)) //如果接受到資料
{
recv = LL_USART_ReceiveData8(USART1); //讀取資料
if(recv == 'A') //如果是字元A
{
LL_USART_TransmitData8(USART1,'E'); //發送字元E
while((USART1->SR&0X40)==0); //等待資料發送完成
}
}
/* USER CODE BEGIN 3 */
}
上文程式不斷的輪詢,判斷是否接受到資料,再進行值的讀取,将資料發送出去以後,等待資料發送完成,經測試效果穩定:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL4lFVNhXV610MFpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4EjM0ATNwIjMyAzNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
可以看到,100B/s 的速度發送了近4萬個位元組,也接到同樣的資料,說明程式未丢包。
如果把
recv = LL_USART_ReceiveData8(USART1)
,移出
if
語句,如下:
// !!錯誤代碼示例
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
static uint8_t recv;
recv = LL_USART_ReceiveData8(USART1); //讀取資料
if(USART1->SR&(1<<5)) //如果接受到資料
{
if(recv == 'A') //如果是字元A
{
LL_USART_TransmitData8(USART1,'E'); //發送字元E
while((USART1->SR&0X40)==0); //等待資料發送完成
}
}
/* USER CODE BEGIN 3 */
}
即未接收到新的資料,也不斷的讀取DR的值,程式測試會出現比較頻繁的丢包。
可以看到,同樣的資料發送,241個位元組,才收到92個位元組,丢包嚴重。原因可能是頻繁的調用
LL_USART_ReceiveData8()
(讀取DR的值),導緻序列槽外設一直忙碌,最後導緻了丢包。