當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]在嵌入式軟件開發(fā)過程中,往往都會(huì)用到串口進(jìn)行打印信息以跟蹤調(diào)試代碼的運(yùn)行。只要在代碼的關(guān)鍵位置加入打印函數(shù),即可分析代碼在這一位置的關(guān)鍵參數(shù)是否正確,運(yùn)行狀態(tài)是否無誤以及相關(guān)的出錯(cuò)信息。通過串口線連接

在嵌入式軟件開發(fā)過程中,往往都會(huì)用到串口進(jìn)行打印信息以跟蹤調(diào)試代碼的運(yùn)行。只要在代碼的關(guān)鍵位置加入打印函數(shù),即可分析代碼在這一位置的關(guān)鍵參數(shù)是否正確,運(yùn)行狀態(tài)是否無誤以及相關(guān)的出錯(cuò)信息。通過串口線連接PC端COM口與開發(fā)板的UART即可實(shí)現(xiàn)開發(fā)板與PC機(jī)的通信。在代碼調(diào)試階段,開始板的狀態(tài)信息通過串口打印顯示在PC端屏幕,可以一目了然,是一種非常重要的調(diào)試手段。筆者此處就s3c2416的串口打印使用作一個(gè)簡(jiǎn)單的介紹。

1. UART模塊實(shí)現(xiàn)1.1. UART初始化

在使用任何外設(shè)前,一般都是需要對(duì)外設(shè)初始化。UART也不例外,使用前需設(shè)置波特率、通信控制、通信的處理方式(中斷還是查詢)等。設(shè)置波特率為115200,8位數(shù)據(jù),1位停止位,沒有奇偶檢驗(yàn)(uboot默認(rèn)設(shè)置),對(duì)于慢速外設(shè),高速cpu一般不應(yīng)通過查詢的方式去確定外設(shè)發(fā)送完數(shù)據(jù)或接收到數(shù)據(jù),這會(huì)讓cpu處于空等的狀態(tài),cpu效率很低,對(duì)于外設(shè)需發(fā)送或接收大量數(shù)據(jù)的情況更是如此。因此筆者此處主要講解s3c2416串口中斷方式去發(fā)送和接收數(shù)據(jù)的情況。由于s3c2416的UART發(fā)送和接收均有64字節(jié)的FIFO,通過中斷的方式可以連續(xù)裝載發(fā)送的數(shù)據(jù)到FIFO中或從FIFO中連續(xù)讀出接收的數(shù)據(jù),應(yīng)用只需通過Uart0中斷請(qǐng)求告知需發(fā)送或接收的數(shù)據(jù)長(zhǎng)度及數(shù)據(jù)保存位置,即可進(jìn)行等待掛起(如ucos中等待信號(hào)量標(biāo)志等函數(shù)OSSemPend),cpu可轉(zhuǎn)而處理其它的事情,當(dāng)Uart0中斷發(fā)送或接收完應(yīng)用請(qǐng)求的所有數(shù)據(jù),即可發(fā)送相關(guān)的信號(hào)量或標(biāo)志喚醒之前等待掛起的應(yīng)用(如ucos中發(fā)送信號(hào)量標(biāo)志等函數(shù)OSSemPost),cpu再轉(zhuǎn)而繼續(xù)處理之前的應(yīng)用。Uart0_Init()函數(shù)如下:

voidUart0_Init()

{

// 設(shè)置GPH0,GPH1為TX和RX

rGPHCON &= ~((3<<0)|(3<<2));

rGPHCON |= (2<<0)|(2<<2);

// 8位數(shù)據(jù),一個(gè)停止位,沒有奇偶檢驗(yàn)

rULCON0 = 0x3;

// UART0 FIFO使能,Tx發(fā)送空時(shí)中斷,Rx 16bytes中斷

rUFCON0 = (0<<6) | (2<<4) | 0x7;

// 流控制禁止

rUMCON0 = 0;

// 發(fā)送接收中斷使能,使用PCLK時(shí)鐘66M

rUCON0 = 0x5 | (1<<7) | (2<<10);

// 設(shè)置波特率

rUBRDIV0 = 66000000/(16*Baudrate)-1;

rUDIVSLOT0 = 0x0888;

// 注冊(cè)UART0 IRQ中斷

IRQ_Register(INT_UART0, Uart0_IRQ);

// UART0 IRQ

rINTMOD1 &= ~(1 << INT_UART0);

// 開啟RX子中斷

// 在寫入FIFO之前,TX必須關(guān)閉中斷,不然FIFO空引發(fā)中斷

rINTSUBMSK |= 0x7;

rINTSUBMSK &= ~(1 <<0);

// UART0開啟中斷

rINTMSK1 &= ~(1 <

}

1.2. 格式化打印函數(shù)

C語言的一些庫函數(shù)功能很強(qiáng)大,沒有必要再自己去實(shí)現(xiàn)。軟件調(diào)試時(shí),可能用的最多的函數(shù)就是printf。由于printf格式化輸出是面向控制臺(tái)的,在arm目標(biāo)中是通過一種半主機(jī)的方式,把printf函數(shù)輸出請(qǐng)求傳送至運(yùn)行調(diào)試器的主機(jī)。如果不對(duì)printf進(jìn)行重定向是不能在目標(biāo)板中使用printf等函數(shù)的(fputc和 fgetc重定向到串口或目標(biāo)板屏幕)。筆者此處為了通用,不重定向改寫printf,而是使用vsnprintf函數(shù)進(jìn)行格式化輸出到字符串中,再把字符串發(fā)送到串口,實(shí)現(xiàn)與printf類似的串口打印輸出。串口格式化打印函數(shù)Uart0_Printf()如下:

// 串口打印函數(shù),替換庫函數(shù)printf函數(shù)功能

// printf是向控制臺(tái)輸出信息,通過vsnprintf格式化數(shù)據(jù)輸出

// 到字符串,并通過串口發(fā)送字符串函數(shù)進(jìn)行串口打印

voidUart0_Printf(char *fmt, ...)

{

va_list ap;

char String[1024];

va_start(ap, fmt);

vsnprintf(String, sizeof(String), fmt, ap);

va_end(ap);

Uart0_SendString(String);

}

1.3. 串口字符串輸出

Uart0_Printf()通過vsnprintf()格式化輸出到字符串后,即可用Uart0_SendString()進(jìn)行字符串發(fā)送,Uart0_SendString()會(huì)確定出字符串的長(zhǎng)度,即確定串口發(fā)送的數(shù)據(jù)長(zhǎng)度,再調(diào)用Uart0_SendData()進(jìn)行發(fā)送一定長(zhǎng)度的字節(jié)數(shù)據(jù)到串口。

// 通過串口發(fā)送字符串

voidUart0_SendString(char *String)

{

unsigned int Len;

char *Temp = String;

if (String == 0) {

return;

}

Len = 0;

// 獲得字符串的長(zhǎng)度

while (*Temp++) {

Len++;

}

Uart0_SendData((unsigned char *)String,Len);

}

1.4. 任意長(zhǎng)度字節(jié)輸出

Uart0_SendData()會(huì)最終向uart0請(qǐng)求發(fā)送一定長(zhǎng)度的數(shù)據(jù),以及數(shù)據(jù)所在的位置,之后會(huì)進(jìn)入等待,直到uart0中斷發(fā)送完所有請(qǐng)求的數(shù)據(jù)。由于Uart對(duì)外發(fā)送數(shù)據(jù)是很慢的,如果有操作系統(tǒng)或狀態(tài)機(jī)實(shí)現(xiàn)中,在while等待中,可改成類似信號(hào)量等待,把Uart0_SendData()函數(shù)掛起(如OSSemPend(ucos)),直到uart0中斷完成請(qǐng)求后,發(fā)送信號(hào)量或標(biāo)志再喚醒執(zhí)行(如OSSemPost(ucos))。Uart0_SendData()函數(shù)實(shí)現(xiàn)如下:

// 通過串口發(fā)送任意長(zhǎng)度的數(shù)據(jù)

voidUart0_SendData(unsigned char *pBuffer, unsigned int Len)

{

if (pBuffer == 0 || Len == 0) {

return;

}

TxLen = Len; // 向中斷請(qǐng)求發(fā)送的數(shù)據(jù)字節(jié)長(zhǎng)度

pTxData = pBuffer; // 發(fā)送數(shù)據(jù)的位置

TxLen--; // 發(fā)送了一字節(jié),發(fā)送數(shù)據(jù)長(zhǎng)度減1

// 發(fā)送第一個(gè)字節(jié)完后會(huì)產(chǎn)生中斷,之后數(shù)據(jù)在中斷函數(shù)中連續(xù)發(fā)送

rUTXH0 = *pTxData++;

rINTSUBMSK &= ~(1 <<1); // 數(shù)據(jù)寫入FIFO后開啟TX發(fā)送完中斷

while(TxLen != -1) {

// 等待UART0數(shù)據(jù)發(fā)送完

// 可改成操作系統(tǒng)信號(hào)量等待函數(shù),提高cpu效率,如OSSemPend(ucos)

}

}

1.5. 發(fā)送字節(jié)函數(shù)

Uart0_SendByte()用來向串口發(fā)送一字節(jié)的數(shù)據(jù)(字符),其向uart0請(qǐng)求一字節(jié)的數(shù)據(jù)發(fā)送。

// 通過串口發(fā)送一字節(jié)數(shù)據(jù)

voidUart0_SendByte(unsigned char Byte)

{

TxLen = 0; // 發(fā)送1字節(jié)后,發(fā)送數(shù)據(jù)長(zhǎng)度為0

rUTXH0 = Byte; // 1字節(jié)數(shù)據(jù)裝載進(jìn)FIFO中

rINTSUBMSK &= ~(1 <<1); // 數(shù)據(jù)寫入FIFO后開啟TX中斷

while (TxLen != -1) { // 等待中斷中發(fā)送完標(biāo)志

// 等待UART0數(shù)據(jù)發(fā)送完

// 可改成操作系統(tǒng)信號(hào)量等待函數(shù),提高cpu效率,如OSSemPend(ucos)

}

}

1.6. 字符串接收函數(shù)

Uart0_ReceiveString()用來請(qǐng)求通過串口接收字符串,其會(huì)調(diào)用Uart0_ReceiveByte()來向uart0請(qǐng)求接收一個(gè)字節(jié)的數(shù)據(jù),根據(jù)接收到的字符數(shù)據(jù)判斷是否字符串結(jié)束或者回車結(jié)束。

// 通過串口接收字符串,指定緩存長(zhǎng)度為L(zhǎng)en

voidUart0_ReceiveString(char *pBuffer, unsigned int Len)

{

char *Temp;

unsigned int i;

if (pBuffer == 0 || Len == 0) {

return;

}

Temp = pBuffer;

for (i=0; i

*Temp = Uart0_ReceiveByte();

if (*Temp == 0 || *Temp == 'r') {

break; // 字符串結(jié)束或回車則結(jié)束輸入

}

Temp++;

}

if (i < Len) {

pBuffer[i] = 0; // 字符串末尾加入結(jié)束字符0

} else {

pBuffer[Len-1] = 0;

}

}

1.7. 字節(jié)接收函數(shù)

Uart0_ReceiveByte()會(huì)通過uart0請(qǐng)求接收一個(gè)字節(jié)的數(shù)據(jù),阻塞直到接收到數(shù)據(jù)返回。

// 通過串口接收一字節(jié)數(shù)據(jù)

charUart0_ReceiveByte(void)

{

unsigned char Value;

pRxData = &Value; // 中斷中接收的1字節(jié)數(shù)據(jù)放在Value中

RxLen = 1; // 接收長(zhǎng)度為1字節(jié)

while(RxLen != 0) {

// 等待UART0數(shù)據(jù)接收

// 可改成操作系統(tǒng)信號(hào)量等待函數(shù),提高cpu效率,如OSSemPend(ucos)

}

return ((char)Value);

}

1.8. 中斷請(qǐng)求處理

Uart0_IRQ()中斷處理函數(shù)用來處理應(yīng)用的發(fā)送請(qǐng)求以及接收請(qǐng)求。如果請(qǐng)求的發(fā)送數(shù)據(jù)長(zhǎng)度或請(qǐng)求的接收數(shù)據(jù)長(zhǎng)度過大,將會(huì)分多個(gè)中斷請(qǐng)求來分包發(fā)送數(shù)據(jù)或接收數(shù)據(jù),直到所有的數(shù)據(jù)請(qǐng)求均完成后,通過發(fā)送信號(hào)量(如OSSemPost(ucos))或完成標(biāo)志告知請(qǐng)求的應(yīng)用。

// 請(qǐng)求通過串口發(fā)送的字節(jié)數(shù)

static volatile int TxLen = 0;

// 請(qǐng)求通過串口接收的

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉