博客專欄

EEPW首頁 > 博客 > 這個寄存器多余了嗎?

這個寄存器多余了嗎?

發(fā)布人:魚鷹談單片機 時間:2021-06-17 來源:工程師 發(fā)布文章

上次寫過一篇筆記《介紹一個高效無隱患輸出 IO 的方法》,介紹了如何避免直接操作 ODR 導(dǎo)致的隱患問題,然后有道友留言對以下代碼提出了疑問:

void out_data(uint8_t byte)
{
  GPIOA->BSRR = ((uint16_t)byte << 8);  // set
  byte = ~byte;  // 打斷后續(xù)運行
  GPIOA->BRR = ((uint16_t)byte << 8);  // reset
}

那就是兩條操作寄存器的代碼間如果產(chǎn)生中斷或者任務(wù)切換了,會不會產(chǎn)生影響,它的電平是否處于不穩(wěn)定狀態(tài)。

這里魚鷹來解釋一下,并給出具體的解決方案。

首先中斷影響,因為中斷處理時間幾乎在微妙級別,如果你的中斷處理在毫秒級別,那么你的系統(tǒng)實時性一定不怎么高。

所以中斷在這里造成的影響比較小。

為什么明明分開操作了,影響還是比較小呢,這是因為如果你這個代碼用于并口總線驅(qū)動,那么總線驅(qū)動一般會用另外的 IO 變化來確定并口數(shù)據(jù)的穩(wěn)定性。

比如說 SPI 總線(非并口),會定義 CLK 上升沿或下降沿才開始采集數(shù)據(jù),并口一般也有這樣的規(guī)定,這樣就保證了即使并口數(shù)據(jù)沒有一次性輸出,因為另外的信號線沒有產(chǎn)生下降沿或下降沿,從機也不會對并口上的數(shù)據(jù)采樣的。

但是不能保證有些并口總線規(guī)范會定義最長的時間,但即使有,微秒級別也差不多沒什么問題。

但還有一種情況是系統(tǒng)使用了 RTOS 。

這樣會導(dǎo)致切換到另一個線程,而這個線程的執(zhí)行時間根本不確定,執(zhí)行毫秒級別是正常的事情,所以,這種情況該如何處理呢?

兩種方法,關(guān)中斷或關(guān)調(diào)度器。(關(guān)于這些內(nèi)容可以看歷史文章,比如《信號量保護之禁止中斷》,《嵌入式系統(tǒng)優(yōu)先級詳解》等)

但是對于幾行代碼就要使用這些代碼,還是太奢侈了一些,雖然對系統(tǒng)的效率影響不大,但畢竟還是不爽,那么是否有更好的辦法可以解決這個問題。

有個道友的留言提醒了魚鷹,就是有一個寄存器是可以同時操作 set 和 reset 的。

以前初學(xué) STM32 的時候,看到這個寄存器可以同時操作 set 和 reset,而另一個寄存器也可以操作 reset,以為功能重復(fù)了,誰知道在這里等著魚鷹呢。

這個寄存器就是 BSRR。

1.png

通過它,就能用一條語句完成多個 IO 的同步操作。

(這里有個錯誤,應(yīng)該是操作 32 bit,畢竟它在庫函數(shù)中可是 32 bit 數(shù)據(jù)。另外特別注意框出來的地方,不過除非你的代碼有問題,不然沒人會沒事同時操作一個 IO 的 BSy、BRy)。

在這里特別感謝這幾位道友的留言提醒。

上面的代碼可以改成這樣:

// 僅用于 8 位數(shù)據(jù) 假設(shè)使用 PA8~15
void out_data(uint8_t byte)
{
  GPIOA->BSRR = ((uint32_t)((uint8_t)~byte) << (0 + 16)) | ((uint32_t)byte << 0);
  // GPIOA->BSRR = ((uint32_t)(~byte) << (8 + 16)) | ((uint32_t)byte << 8); // 錯誤寫法
}
// 使用宏,更高效,任意位數(shù)
#define GPIOA_RESET_SET(data, offset, msk)  GPIOA->BSRR = ((uint32_t)(~(data) & (msk)) << ((offset) + 16)) | ((uint32_t)((data) & (msk)) << (offset)) 
// 等效代碼  PA8~PA15 輸出
#define GPIOA_RESET_SET_BYTE(byte)          GPIOA_RESET_SET(byte, 8, 0xff)

如果你的代碼對性能要求比較高,建議使用宏,但同時你需要知道里面還有一個 & 的計算,這個會在運行時計算,而對于固定的 8 bit 數(shù)據(jù),這個計算可以通過強制轉(zhuǎn)化去掉(就像前面的代碼一樣,并沒有 & 計算),這樣效率會更高,另一種方法是使用內(nèi)聯(lián)函數(shù),在使用上應(yīng)該會比宏更加安全(優(yōu)化級別提高的情況下)。

希望本期筆記對各位道友開發(fā)項目有所幫助,如有幫助,歡迎轉(zhuǎn)發(fā)支持魚鷹。

*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。

逆變器相關(guān)文章:逆變器原理


逆變器相關(guān)文章:逆變器工作原理


光伏發(fā)電相關(guān)文章:光伏發(fā)電原理


關(guān)鍵詞: 單片機

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉