MAXQ610微控制器提供兩個標準的USART串行端口。異步模式1是MAXQ610串行端口支持的模式之一,可用于與PC COM端口和許多其他類型的傳統設備通信。本應用筆記解釋了MAXQ610為串行端口發送和接收操作提供的中斷處理支持如何允許應用在接收到新字符或字符完成傳輸時快速響應串行端口。
概述
MAXQ610微控制器包括外設,允許與外部設備或系統通信。這些外設包括一個主/從串行外設接口(SPI?);用于紅外(IR)通信的載波生成/調制系統;和兩個獨立的通用同步/異步接收器/發射器 (USART),通常稱為串行端口。
本應用筆記演示了在610位異步模式下使用MAXQ10上的串行端口。此模式通常用于與 PC 上的標準 COM 端口通信和/或將調試輸出發送到 PC。此模式允許兩個設備或系統通過簡單地商定通用位格式和波特率進行通信,而不管通信通道兩端的實際工作頻率如何。
本應用筆記的演示代碼為MAXQ610和MAXQ610評估(評估)板編寫,采用基于匯編的MAX-IDE環境。本應用筆記中介紹的演示應用的代碼和項目文件可供下載。
運行演示代碼需要以下硬件和軟件。
MAXQ610評估板
MAXQJTAG板(串口到JTAG接口)
JTAG編程電纜(2 x 5母頭對母頭0.100“接頭,10連接器帶狀電纜)
DB9 直通公對母串行電纜
最大集成環境
終端仿真器(例如在啞終端模式下運行的 MTK、超級終端或 TeraTerm)
MAX-IDE環境的最新安裝包和文檔可免費下載。
最大集成開發臺安裝
MAXQ磁芯組裝指南
開發工具指南
要運行 C 版本的演示代碼,必須安裝 IAR 嵌入式工作臺?。該軟件的評估副本在MAXQ610評估板的光盤上提供。
設置MAXQ610評估板
本應用筆記介紹的演示代碼工作在MAXQ610評估板上。但是,為了使代碼正常運行并啟用代碼中的功能,必須正確配置評估板上的跳線。在運行演示的兩個步驟(即加載代碼和執行代碼)中,套件板上使用相同的跳線配置。
配置MAXQ610評估板上的跳線。
JH1:連接引腳 2 和 3。
JH2:連接引腳 2 和 3。
JH3:連接引腳 2 和 3。
連接以下跳線(引腳 1 和 2):JH14、JH20、JH22、JH23、JH24、JH25 和 JH26。
正確配置MAXQ610評估板后,設置硬件以編譯和加載演示代碼。
連接串行至JTAG板上的跳線JH1、JH2和JH3。
將 5VDC 電源連接到串行轉 JTAG 板上的 J2 插頭。
將 DB9 電纜從 PC 上的 COM1 端口連接到串行到 JTAG 板上的 J1 連接器。
將JTAG編程電纜從串行轉JTAG板上的P2連接到MAXQ5評估板上的P610。JTAG電纜上的紅線應通向兩個連接器上的引腳1(TCK)。
打開 5VDC 電源的電源。
串口模式和初始化
MAXQ610上的兩個USART外設都可以在同步或異步模式下工作。當工作在同步模式(模式0)時,MAXQ610作為總線主控器處理所有事務。它將 TXD 線路配置為發送和接收操作的移位時鐘,而 RXD 用作雙向數據線。在這種安排下,數據一次只能在一個方向上傳輸(半雙工),并且只能在主站的要求下傳輸。
在異步操作模式(模式 1、2 和 3)中,有兩條單向數據線:TXD 和 RXD。TXD線將異步數據從MAXQ610的串行端口傳輸至外部器件,RXD線將異步數據從外部器件傳輸回MAXQ610。MAXQ610和外部器件必須商定通用格式(數據位數、奇偶校驗位和停止位)和公共波特率(總線頻率),以便通信。這些模式允許以全雙工方式傳輸數據,因為 TXD 和 RXD 線路上的傳輸可以獨立進行,不需要相互同步。MAXQ610可以隨時向TXD線路上的外部設備發送數據,無論外部設備當前是否在RXD上傳輸,反之亦然。
在本演示中,我們將選擇具有以下特征的模式 1。
串行數據的異步傳輸(在 TXD 上)和接收(在 RXD 上)
波特時鐘由專用波特時鐘發生器提供(使用 PR 寄存器編程)
1 個數據位,1 個起始位,<> 個停止位
無奇偶校驗
模式1中串行端口使用的波特率(每秒發送/接收的位數)由以下兩個公式確定(如
MAXQ系列用戶指南所述):
波特時鐘頻率 (BAUD) = 系統時鐘頻率 × PR/217 | (公式1) |
波特率 = 波特率 × 2(SMOD × 2)/26 | (公式2) |
公式1描述了波特時鐘發生器的輸出。生成的輸出頻率由16位PR(相位)寄存器的內容控制。將較高的值加載到 PR 寄存器中會導致更高頻率的波特時鐘。
公式2考慮SMD或串行端口模式寄存器中控制位(SMOD)的影響。將此位設置為 1 會將最終波特率提高 4 倍。這意味著公式2也可以用以下任一方式編寫,具體取決于SMOD的值:
當 SMOD=0 時,波特率 = 波特/64 | (公式3) |
當 SMOD=1 時,波特率 = 波特/16 | (公式4) |
對于大多數晶體速度和波特率組合,可以使用SMOD的任一設置。請注意,SMOD 的設置會影響要加載到 PR 寄存器中的值。對于我們的應用程序,我們將選擇 SMOD=1,這意味著波特率方程簡化為以下內容:
波特率 =(系統時鐘頻率 × PR/217)/16 | (公式5) |
藝術
波特率 =(系統時鐘頻率× PR)/221 | (公式6) |
求解 PR 值為我們提供了我們最感興趣的方程式。通常,波特率和系統時鐘頻率是固定的,我們只想知道產生預期波特率所需的PR寄存器設置。因此:
PR = 波特率 × 221/(系統時鐘頻率) | (公式7) |
例如,使用MAXQ12評估板上的標準610MHz晶體,選擇9600波特率。PR 寄存器的所需設置為 (9600 × 221/12000000),大約是 1677 或 068Dh。
計算出 PR 和 SMOD 的值后,初始化串行端口只需將 USART 設置為正確的模式并寫入 PR 和 SMOD 值即可。由于我們使用串行端口 0,因此代碼將寫入該串行端口(SCON0、SMD0、PR0 和 SBUF0)的相應寄存器集。
;============================================================================== ;= ;= InitSerial0 ;= ;= Set up serial port 0 to run in 10-bit asynchronous mode at ;= 9600 baud. ;= InitSerial0: move SCON0.6, #1 ; Set to mode 1 (10-bit asynchronous). move SCON0.4, #1 ; Enable receiver. move SMD0.1, #1 ; Baud rate = 1/16 of baud clock move PR0, #0068Dh ; P = 2^21 × 9600/12.000MHz move SCON0.0, #0 ; Clear received character flag. move SCON0.1, #0 ; Clear transmit character flag. move SMD0.2, #1 ; Enable receive/transmit interrupt. ret
發送和接收字符
正確配置串行端口后,即可發送和接收字符。在模式 1 中,字符由 1 個起始位、8 個數據位和 1 個停止位組成。開始位和停止位用于同步目的,由 USART 硬件處理。其余8位攜帶實際數據,這意味著串行端口可以一次發送或接收單個8位字節。
通過串行端口傳輸字符涉及以下三個步驟。
將要傳輸到 SBUF 寄存器的字節值寫入。
等待SCON寄存器中的TI(發送中斷)位變為高電平(設置為1)。這表示硬件已完成通過串行端口傳輸字符。
將 TI 位清除為 0。
在開始新的傳輸之前,始終需要等待每次傳輸完成。與指令執行周期時間相比,串行端口傳輸所需的時間很長。因此,可以在等待串行端口傳輸完成的同時執行步驟 2 中的其他操作。例如,當使用115200MHz晶體以12波特率傳輸時,傳輸所需的總時間約為10×(1/115200)或87μs。在同一時間范圍內,MAXQ610可以執行多達1041條指令(87μs/(1/12MHz))。
通過串行端口接收字符以類似的方式完成。
等待 RI(接收中斷)位變為高電平,表示串行端口已接收到新字符。
從 SBUF 寄存器讀取以獲取數據字節。
將 RI 位清除為 0。
在任何給定時間,串行端口硬件中僅存儲(緩沖)一個接收的字符。這意味著,如果硬件將 RI 位設置為 1(表示已接收到字符),則必須通過讀取 SBUF 寄存器來獲取該字符;在串行端口接收下一個字符之前,必須清除 RI 位。如果串口接收到新字符,并且RI位仍然很高,則新字符將丟失。
處理串行端口中斷
操作串行端口的一種簡單方法是根據需要簡單地輪詢(重復檢查)每個發送或接收操作的 RI 和 TI 位的值。例如,寫入字符時,應用程序代碼會將數據字節寫入 SBUF,然后輪詢 TI 位,直到硬件將其設置為 1。在傳輸完成之前,不會發生其他操作。同樣,要接收新字節,應用程序只需輪詢 RI 位,直到硬件將其設置為高,然后通過讀取 SBUF 卸載接收的字節。
這種輪詢 RI 和 TI 位的方法為了簡單起見犧牲了性能,因為等待發送或接收字符需要花費大量時間。此外,應用程序必須提前知道何時需要來自外部設備的新字符,并且應用程序不能同時發送和接收字符。
一種更靈活(但稍微復雜)的方法利用了 TI 和 RI 不僅是狀態位,而且還是同步中斷源的事實。當TI或RI從610變為0時,MAXQ1無需連續輪詢TI和RI位的狀態來確定發送或接收操作何時完成。此方法允許應用程序更有效地花費時間,因為它僅在需要時響應串行端口。
此過程的第一步是通過將 IGE 位 (IC.0) 設置為 1 來啟用所有中斷。這樣就可以對整個MAXQ610進行全局級別的中斷處理。
接下來,必須安裝中斷處理例程。MAXQ610采用多固定中斷矢量系統,為每個中斷源或中斷源組分配不同的(不可編程)矢量地址。出于我們的目的,我們對串行端口中斷向量感興趣,它被分配給字地址 0040h。
下面的中斷處理程序例程執行以下功能。
通過臨時將 IC.0 設置為 0 來防止發生其他中斷(優先級較高)。
將 PSF 和 Acc 寄存器推送到堆棧以保存其值。由于可以隨時觸發中斷,因此中斷處理程序必須始終保存和還原其他應用程序代碼使用的任何寄存器。
由于串行端口中斷可以由 TI(傳輸)或 RI(接收)標志觸發,因此處理程序代碼必須檢查觸發中斷的原因。
如果觸發了傳輸中斷,請清除 TI 位并設置一個標志值(存儲在 A[15] 中),以向應用程序指示傳輸已完成。這只是為了演示目的;中斷處理程序還可以通過將新值加載到 SBUF 中來傳輸下一個字符來對此情況做出反應。
如果觸發了接收中斷,請清除 RI 位;讀取從 SBUF 收到的字符;并根據收到的字符采取適當的操作。
通過從堆棧中彈出 Acc 和 PSF 寄存器值來恢復它們。
通過將 IC.0 設置為 1 來重新啟用中斷。
使用 RETI 指令退出中斷處理程序。
org 0040h serialInt: move IC.0, #0 ; Block any other interrupts from triggering. push PSF push Acc move C, SCON0.0 ; Check for receive character interrupt. jump C, serialInt_Rx serialInt_Tx: move SCON0.1, #0 ; Clear transmit complete interrupt flag. move A[15], #1 ; Set flag to indicate transmit complete. serialInt_done: move IC.0, #1 ; Re-enable interrupts. pop Acc pop PSF reti serialInt_Rx: move SCON0.0, #0 ; Clear receive character interrupt flag. move Acc, SBUF0 ; Get character from serial port. cmp #'0' jump E, serialInt_Rx0 cmp #'1' jump E, serialInt_Rx1 cmp #'2' jump E, serialInt_Rx2 cmp #'3' jump E, serialInt_Rx3 cmp #'4' jump E, serialInt_Rx4 jump serialInt_done serialInt_Rx0: move Acc, PO3 or #0Fh ; Turn all LEDs off. move PO3, Acc jump serialInt_done .... serialInt_Rx3: move Acc, PO3 xor #04h ; Toggle P3.2 state. move PO3, Acc jump serialInt_done serialInt_Rx4: move Acc, PO3 xor #08h ; Toggle P3.3 state. move PO3, Acc jump serialInt_done
構建演示應用程序
串行演示應用程序的整體框架如下。
初始化端口引腳和串行端口。
啟用中斷。
通過串行端口傳輸以下橫幅文本。
MAXQ610 Serial Port Demo Type characters "1"-"4" to toggle LEDs or '0' to turn all LEDs off.
收到字符“1”、“2”、“3”、“4”或“0”時,請相應地更改 LED 狀態。
如上面的中斷處理程序代碼所示,應用程序通過更改端口引腳 P3.0、P3.1、P3.2 和 P3.3 的輸出狀態來響應收到的字符。在MAXQ610評估板上(跳線JH22、JH23、JH24和JH25閉合),這些端口引腳驅動DS4、DS1、DS2和DS3個LED。端口引腳 (4) 上的低狀態會導致 LED 亮起(亮起),而端口引腳上的高狀態會導致 LED 熄滅。 橫幅文本使用從單詞地址 0h 開始的數據庫語句進行存儲。該常量數據與其余程序代碼一起加載到MAXQ0800的閃存中,可以使用CP代碼指針進行檢索,如上所示(printLoop)。由于每次使用 CP 從程序存儲器中獲取都會檢索一個字的數據,因此在讀取每個字后,會通過串行端口傳輸兩個字符。
main: move WDCN, #0 move PD3.0, #1 ; Set P3.0 to output mode. move PO3.0, #1 ; Drive P3.0 high (LED off). move PD3.1, #1 ; Set P3.1 to output mode. move PO3.1, #0 ; Drive P3.1 low (LED on). move PD3.2, #1 ; Set P3.2 to output mode. move PO3.2, #1 ; Drive P3.2 high (LED off). move PD3.3, #1 ; Set P3.3 to output mode. move PO3.3, #0 ; Drive P3.3 low (LED on). move PD0.2, #1 ; Set P0.2 (TXD) to output mode. move PO0.2, #1 ; Idle high when not transmitting. call InitSerial0 move IC.0, #1 ; Enable interrupts. move LC[0], #12000 ; Give transceiver time to power on. djnz LC[0], $ ; Print string to serial port. move CP, #0800h printLoop: move Acc, @CP++ nop jump Z, printLoop_done move GR, Acc move Acc, GRL call TxChar0 move Acc, GRH call TxChar0 jump printLoop printLoop_done: nop mainLoop: nop jump mainLoop ;============================================================================== ;= ;= TxChar0 ;= ;= Outputs a character to serial port 0. ;= ;= Inputs : Acc - Character to send. ;= TxChar0: push Acc move SBUF0, Acc ; Send character. move A[15], #0 ; Clear interrupt service routine flag. TxChar0_Loop: nop nop nop move Acc, A[15] ; Check flag. jump Z, TxChar0_Loop move SCON0.1, #0 ; Clear the transmit flag. pop Acc ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 800h db 0Dh, 0Ah, 0Dh, 0Ah db "MAXQ610 Serial Port Demo", 0Dh, 0Ah, 0Dh, 0Ah db "Type characters '1'-'4' to toggle LEDs or '0' to turn all LEDs off" db 0Dh, 0Ah, 0Dh, 0Ah dw 0000h
使用MAX-IDE編譯演示代碼并加載到MAXQ610評估板后,可以按如下方式執行。
關閉電源并斷開JTAG、電源和串行電纜。
將PC上COM1的串行電纜連接到MAXQ1評估板上的J610。
將電源線插入MAXQ3評估板上的J610。
打開電源。
在PC上打開終端仿真程序。將其配置為通過 COM1 以 9600 波特進行通信,具有 8 個數據位、1 個停止位且無奇偶校驗。
按下并釋放MAXQ1評估板上的復位(SW610)。橫幅文本(MAXQ610串行端口演示...)應顯示在終端仿真器屏幕上。如果沒有,請檢查您的連接和跳線設置。
鍵入字符以切換 LED 狀態,如下所示:鍵入“1”以切換 DS1;鍵入“2”以切換DS2;鍵入“3”以切換DS3;鍵入“4”以切換DS4;或鍵入“0”以關閉所有 LED。字符不回顯。
C 語言演示代碼
下面的演示代碼顯示了相同的應用程序,用于IAR的?嵌入式工作臺IDE,用C實現。為簡單起見,已刪除中斷處理代碼。請注意,已實現 putchar 函數以通過串行端口 0 輸出字符。這允許使用標準的I / O庫函數,如puts()和printf()。
int putchar(int c) { SBUF0 = c; while ((SCON0 & 0x02) == 0); SCON0 = (SCON0 ^ 0x02); return c; } void initUSART0(void) { int i2; PD0_bit.bit2 = 1; // Hold Tx0 line High. PO0_bit.bit2 = 1; // Hold Tx0 line High. SMD0 = 2; // Set baud rate select bit. SCON0 = 0x50; // Set mode 1 and receive enable for UART 0. PR0 = 0x068D; // 9600 baud: PR0 = 2^21 * 9600 / 12.000MHz for (i2 = 1; i2 < 10000; i2++); // Give transceiver time to power on. SCON0 = 0x50; } void main( void ) { int c; IC_bit.IGE = 0; WDCN = 0; PD3 = 0x0F; PO3 = 0x05; // Default - DS2 and DS4 on, DS1 and DS3 off initUSART0(); puts("MAXQ610 Serial Port Demo"); puts("Type characters "1"-"4" to toggle LEDs or "0" to turn all LEDs off\n"); while (1) { while ((SCON0 & 0x01) == 0); // Wait for RI flag to go high. c = SBUF0; // Receive character. SCON0 = (SCON0 ^ 0x01); // Clear RI flag. switch (c) { case '0' : PO3 = 0x0F; break; case '1' : PO3 = (PO3 ^ 0x01); // Toggle P3.0 break; case '2' : PO3 = (PO3 ^ 0x02); // Toggle P3.1 break; case '3' : PO3 = (PO3 ^ 0x04); // Toggle P3.2 break; case '4' : PO3 = (PO3 ^ 0x08); // Toggle P3.3 break; default : break; } } }
結論
MAXQ610提供了許多MAXQ微控制器上標準USART串行端口的兩個實例。MAXQ610串行端口支持的模式之一,異步模式1,可用于與PC COM端口和許多其他類型的傳統設備通信。MAXQ610為串行端口發送和接收操作提供中斷處理支持,允許應用在接收新字符或字符完成傳輸時快速響應串行端口。
審核編輯:郭婷
-
微控制器
+關注
關注
48文章
7552瀏覽量
151426 -
適配器
+關注
關注
8文章
1952瀏覽量
68029 -
USART
+關注
關注
1文章
195瀏覽量
30858
發布評論請先 登錄
相關推薦
評論