簡體   English   中英

在4位數據模式下時,是否可以將其他4位用於其他內容?

[英]When on 4 bit data mode, is it possible to use the other 4 bits for other stuff?

因此,我正在編寫一個C程序以4位數據模式連接LCD。 但是,我想知道是否可以使用其他4位來做其他事情,例如外部中斷。 更具體地說,我將PORTD用於arduino上的數據線,但是我還需要引腳PD2才能使用INT0中斷(按鈕)。 在我的程序中,我注意到在發送命令時,我一直將低4位設置為0:

PORTD = cmd & 0xf0;
flashLCD();
PORTD = (cmd & 0x0f) << 4;

這可以正常工作,但是將其他位設置為0。這在計時器上調用,這意味着Im反復發送命令。 因此,我嘗試保存寄存器的先前值,並通過一些按位操作將其附加:

uint8_t initial_state = PORTD;
PORTD = (cmd & 0xf0) | (initial_state & 0x0f);
flashLCD();
PORTD = ((cmd & 0x0f) << 4) | (initial_state & 0x0f)

它在LCD上發送cmd,但是它仍然不會響應中斷。 我想知道我是否沒有考慮到某些問題,或者我的邏輯不正確。 謝謝。

編輯:Nvm我想通了。 我的LCD庫即使在4位模式下也總是將端口寄存器重置為0,因此其他未使用的端口也被重置了。 我只是更改了庫,以便在4位模式下可以使用其他端口。

我不知道在Arduino上使用的控制器(ATmega / AVR或其他控制器),甚至都沒有指定使用哪個控制器。

但是通常,端口和端口引腳可以配置為具有輸入或輸出模式。 由於您通過PORTD分配了4位,因此我假設整個8位端口(所有端口引腳)都配置為輸出。

如果整個端口的某些引腳可以同時用作輸出引腳,而其他端口可以同時用作輸入引腳,則應考慮使用手冊。

小心地在兩個端口之間切換整個端口的輸入/輸出,這可能會產生副作用,例如不必要的HL / LH轉換。 我曾經用8255輸出芯片進行過一次操作,由於LCD的復位線連接,導致圖形LCD復位。

您正確地注意到,通過使用按位運算可以保留其他位

PORTD = (PORTD & 0x0F) | (high_bits << 4);

但! 該行將被編譯成一些機器指令:

  1. 將PORTD值加載到寄存器中
  2. 對寄存器執行按位與
  3. 將high_bits裝入另一個寄存器
  4. 執行其他計算(高位等左移)
  5. 執行按位或
  6. 將結果存儲回PORTD

假設在1到6之間的某個位置觸發了中斷,它會停止執行代碼,並更改PORTD的低位。 中斷例程完成后,程序將繼續執行,它將用中斷之前寄存器中存儲的內容重寫PORTD的所有第8位,從而覆蓋PORTD的低位,並丟棄中斷例程中進行的所有更改。

因此,有兩種方法可以對PORTx進行原子操作。

第一:只是在PORTx寄存器更新時禁用中斷:

uint8_t old_sreg = SREG; // save SREG register (including I flag)
cli(); // clear I flag, thus prohibiting interrupts
PORTD = (PORTD & 0x0F) | (high_bits << 4); // perform the operation
SREG = old_sreg; // restoring SREG and I flag, if it was set before

第二種方法僅適用於新的AVR內核(例如ATmega328、1284、2560等),而不適用於較舊的內核(ATmega8、32等)。 請參考數據表中的“ I / O端口->端口作為通用數字I / O->切換引腳”部分。 將1寫入PINx的位將反轉PORTx的相應位。 使用它,可以僅更新PORTx寄存器的所需位,而保持其他狀態不變,從而無需鎖定中斷。 在時間緊迫的環境中,中斷應盡快觸發,這可能很有用。

PIND = (PORTD ^ (high_bits << 4)) & 0xF0;

當然,如果保證中斷只能更改PORTD的其他位(在本例中為低位),它將起作用。 如果該中斷也可以寫入相同的位,則可能會導致意外的結果,因此請小心。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM