|
實驗?zāi)康?/font>
①了解RTC應(yīng)用及其概念
②了解ARM串口通信的工作機制
③了解串口驅(qū)動程序的編寫方法
④掌握實際控制RTC的方法,顯示系統(tǒng)時間
⑤了解uCOS II的基本結(jié)構(gòu)
⑥分析uCOS II源碼
⑦掌握uCOS II的移植過程
⑧掌握uCOS II應(yīng)用程序設(shè)計技巧
實驗內(nèi)容
①熟悉PXA270提供的實時時鐘控制器
②熟悉PXA270提供的通用異步串行收發(fā)口
③參照提供的串口驅(qū)動程序,將RTC的當(dāng)前值由串口輸出
④結(jié)合LCD驅(qū)動程序,將RTC的值顯示在LCD中,完成一個功能基本完備的數(shù)字時鐘
⑤完成程序的編譯和調(diào)試,并觀察運行結(jié)果
⑥閱讀uCOS II源代碼,重點分析與硬件相關(guān)的文件內(nèi)容
⑦熟悉PXA270的資源配置,掌握uCOS II必須使用資源的配置技巧
⑧掌握uCOS II的移植方法
⑨參照示例代碼完成自己的多任務(wù)程序
⑩編譯正確后,將映像下載到Flash中運行
實驗原理
①RTC的控制
RTC的控制很簡單,主要是初始化的一些配置,初始化后直接讀寫相應(yīng)的寄存器就可以完成對時間的讀取和重設(shè)操作。本實驗為了方便起見,沒有使用到RTC的中斷,直接讀取RTC的日期和時間寄存器。
對RTC進行初始化時,要對如下RTSR、RCNR、RYCR及RDCR寄存器進行初始化,其中各個寄存器的作用如下:
RTC狀態(tài)寄存器——RTSR
RTSR寄存器包括了兩個中斷允許位和兩個狀態(tài)位。當(dāng)RTSR[HZE]為1時并且檢測到1-HZ時鐘信號上升沿到來時,RTSR[HZ]便被自動設(shè)為1。當(dāng)RTSR[ALE]為1時并檢測到RCNR和RTAR相同時,RTSR[AL]便被自動設(shè)為1。RTSR[HZ]或RTSR[AL]為1時都會發(fā)送到中斷控制器。
RTC計數(shù)寄存器——RCNR
RCNR是一個在1-HZ時鐘脈沖信號上升沿觸發(fā)下實現(xiàn)自動加1的32位可讀寫寄存器,該寄存器在系統(tǒng)復(fù)位后為0.
RTC年計數(shù)寄存器——RYCR
通過對該寄存器賦值,可以設(shè)置系統(tǒng)的起始時的年月日等日期參數(shù)。復(fù)位后自動設(shè)置的日期是2000年1月1日。該寄存器的數(shù)值變化與RTC天計數(shù)寄存器RDCR相關(guān),當(dāng)RDCR產(chǎn)生進位時,RYCR便會按照年月日的相應(yīng)位實現(xiàn)變化。
RTC天數(shù)計數(shù)寄存器——RDCR
RDCR是一個計算系統(tǒng)一天時間變化的寄存器,該寄存器除了包含時分秒之外,還包括每月中的第幾個星期以及摩天在該星期中的位置。秒計數(shù)位在1-Hz時鐘脈沖信號的計時下自動增1,增加到59后就會向分計數(shù)位進位。依次按照七日與時間格式方式類推進位。
②uCOS應(yīng)用程序編寫
1)任務(wù)創(chuàng)建
OSTaskCreate(void (*task)(void *pd), void*pdata, OS_STK *ptos, INT8U proi);
基本的任務(wù)創(chuàng)建函數(shù),入口參數(shù)分別為指向任務(wù)代碼的函數(shù)指針pd,傳遞給任務(wù)的數(shù)據(jù)指針pdata,指向任務(wù)棧棧頂?shù)闹羔榩tos,任務(wù)的優(yōu)先級proi。返回OS_NO_ERR表示任務(wù)創(chuàng)建成功;返回OS_PRIO_EXIT表示指定優(yōu)先級的已經(jīng)存在;返回OS_PRIO_INVALD表示指定的優(yōu)先級比用戶定義的最低優(yōu)先級還低。
OSTaskCreate(void (*task)(void *pd), void*pdata, OS_STK *ptos, INT8U proi, INT16U id, OS_STK *pbos, INT32U stk_size,void *pext, INT16U opt);
擴展的任務(wù)創(chuàng)建函數(shù),入口參數(shù)前四個與基本任務(wù)創(chuàng)建函數(shù)相同,擴展的入口參數(shù)包括:任務(wù)的ID號id;指向任務(wù)棧棧底的指針pbos;任務(wù)的棧的大小stk_size(以元素計,非字節(jié));指向用戶自定義任務(wù)控制塊擴展的指針pext;額外的任務(wù)行為控制的標(biāo)識符opt。
2)信號量實現(xiàn)任務(wù)同步
OSSemCreate(INT16U cnt);
創(chuàng)建一個信號量,輸入?yún)?shù)包括信號量的初始值cnt。返回值:成功時返回一個指向與該信號量關(guān)聯(lián)的事件控制塊的指針;失敗時返回0。
OSSemPend(OS_ENENT *pevent, INT16U timeout,INT8U *err);
獲取一個信號量,入口參數(shù)包括:指向時間控制塊的指針pevent;超時時間值timeout;傳入的等待被填寫的錯誤信息的指針err。
OSSemPost(OS_EVENT *pevent);
釋放一個信號量,輸入?yún)?shù)包括:指向事件控制塊的指針。
實驗步驟
第一步 分析代碼
結(jié)合以上說明,對本實驗提供的示例代碼分析,深入理解針對具體的硬件實現(xiàn),軟件是如何配合工作的。
第二步 程序的編譯和下載
利用ADS打開示例工程文件,執(zhí)行Project→Make,編譯、鏈接生成可執(zhí)行映像文件
第三步 將生成的二進制.bin文件用H-Flasher下載到實驗板中NOR Flash的0地址處,重啟實驗板。
程序說明
本次實驗主要使用前幾次實驗的代碼完成一個綜合性的包括一個實時操作系統(tǒng)的實驗,其中按鍵驅(qū)動和LCD顯示部分做了少許修改,剩下主要工作是如何在操作系統(tǒng)下完成整個實驗。
程序源代碼、注釋
- while(1)
- {
- OSTimeDly(1);
- OSSemPend(Keypad_Sem, 0, &err); /*wait for the Keypad_Sem from keypad intr handler*/
- //Tmp = (INT8U)KPAS_VALUE ;
- //CONSOL_Printf(" KPAS_VALUE value: 0x%x\r\n", Tmp);
- //Tmp = (INT8U)KPDK_VALUE ;
- //CONSOL_Printf(" KPDK_VALUE value: 0x%x\r\n", Tmp);
- //OSTimeDlyHMSM(0, 0, 0, 500);
- //j = KPAS_VALUE;
-
- keyValue = keyLUT[KPAS_VALUE];
- switch(keyValue)
- {
- //普通數(shù)字鍵
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- {
- tempDisp = tempDisp * 10 + keyValue - '0';
- if(tempDisp > 9999)
- tempDisp = 0;
-
- SegLedDispNum(tempDisp, DISP_BLANKING);
- break;
- }
-
- //退格鍵
- case '*':
- {
- tempDisp /= 10;
- SegLedDispNum(tempDisp, DISP_BLANKING);
- break;
- }
- //確認(rèn)鍵
- case '#':
- {
- switch(setWhat)
- {
- case 0:
- {
- get_date(&tempDate);
- set_date(tempDisp, tempDate.month, tempDate.day);
- get_time(&tempTime);
- set_time(tempTime.hour, tempTime.minute, tempTime.second);
- t=10;
- while(t>0)t--;
- get_date(&tempDate);
- //OSSemPost(LCD_Sem);
- break;
- }
- case 1:
- {
- get_date(&tempDate);
- set_date(tempDate.year, tempDisp / 100, tempDisp % 100);
- get_time(&tempTime);
- set_time(tempTime.hour, tempTime.minute, tempTime.second);
- t=10;
- while(t>0)t--;
- get_date(&tempDate);
- OSSemPost(LCD_Sem);
- break;
- }
- case 2:
- {
- get_time(&tempTime);
- set_time(tempDisp / 100, tempDisp % 100, tempTime.second);
- get_time(&tempTime);
- OSSemPost(LCD_Sem);
- break;
- }
- case 3:
- {
- get_time(&tempTime);
- set_time(tempTime.hour, tempTime.minute, tempDisp);
- get_time(&tempTime);
- OSSemPost(LCD_Sem);
- break;
- }
- }
- break;
- }
-
- //年
- case 'A':
- {
- setWhat++;
- if(setWhat > 3)
- setWhat = 0;
-
- print_3232((char *)(0xa1800000), word_null[0],0,300,0xffff);
- print_3232((char *)(0xa1800000), word_null[0],32,300,0xffff);
-
- print_3232((char *)(0xa1800000), word_dis[4][0],0,300,0x0);
- break;
- }
-
- //月日
- case 'B':
- {
- setWhat--;
- if(setWhat < 0)
- setWhat = 3;
-
- print_3232((char *)(0xa1800000), word_null[0],0,300,0xffff);
- print_3232((char *)(0xa1800000), word_null[0],32,300,0xffff);
-
- print_3232((char *)(0xa1800000), word_dis[5][0],0,300,0x0);
- print_3232((char *)(0xa1800000), word_dis[0][0],32,300,0x0);
- break;
- }
-
- //時分
- case 'C':
- {
- setWhat = 2;
-
- print_3232((char *)(0xa1800000), word_null[0],0,300,0xffff);
- print_3232((char *)(0xa1800000), word_null[0],32,300,0xffff);
-
- print_3232((char *)(0xa1800000), word_dis[2][0],0,300,0x0);
- print_3232((char *)(0xa1800000), word_dis[6][0],32,300,0x0);
- break;
- }
-
- //秒
- case 'D':
- {
- setWhat = 3;
-
- print_3232((char *)(0xa1800000), word_null[0],0,300,0xffff);
- print_3232((char *)(0xa1800000), word_null[0],32,300,0xffff);
- print_3232((char *)(0xa1800000), word_dis[7][0],0,300,0x0);
- break;
- }
-
- default:
- break;
- } //end of switch(keyValue)
-
-
- switch(setWhat)
- {
- case 0:
- {
- print_3232((char *)(0xa1800000), word_null[0],0,300,0xffff);
- print_3232((char *)(0xa1800000), word_null[0],32,300,0xffff);
- print_3232((char *)(0xa1800000), word_dis[4][0],0,300,0x0);
- break;
- }
-
- case 1:
- {
- print_3232((char *)(0xa1800000), word_null[0],0,300,0xffff);
- print_3232((char *)(0xa1800000), word_null[0],32,300,0xffff);
-
- print_3232((char *)(0xa1800000), word_dis[5][0],0,300,0x0);
- print_3232((char *)(0xa1800000), word_dis[0][0],32,300,0x0);
- break;
- }
-
- case 2:
- {
- print_3232((char *)(0xa1800000), word_null[0],0,300,0xffff);
- print_3232((char *)(0xa1800000), word_null[0],32,300,0xffff);
-
- print_3232((char *)(0xa1800000), word_dis[2][0],0,300,0x0);
- print_3232((char *)(0xa1800000), word_dis[6][0],32,300,0x0);
- break;
- }
-
- case 3:
- {
- print_3232((char *)(0xa1800000), word_null[0],0,300,0xffff);
- print_3232((char *)(0xa1800000), word_null[0],32,300,0xffff);
-
- print_3232((char *)(0xa1800000), word_dis[7][0],0,300,0x0);
- break;
- }
-
- }
-
- if(1==flag)
- {
- LED_CS3 =0x4040;
- LED_CS2 =0x4040;
-
- }
-
- else if(2==flag)
- {
- if((tm[3]==0)&&(tm[2]==0)&&(tm[1]==0)&&(tm[0]==0))
- {
- LED_CS2 = 0x8080;
- LED_CS3 = 0x8080;
- }
- else if((tm[3]==0)&&(tm[2]==0)&&(tm[1]==0))
- {
- LED_CS2 = 0x8080;
- LED_CS3 = (SEG_VALUE[tm[0]]<<8) | 0x80;
- }
- else if((tm[3]==0)&&(tm[2]==0))
- {
-
- LED_CS2 = 0x8080;
- LED_CS3 = (SEG_VALUE[tm[0]]<<8) | SEG_VALUE[tm[1]];
- }
-
- else if(tm[3]==0)
- {
- LED_CS2 = (SEG_VALUE[tm[2]]<<8) |0x80;
- LED_CS3 = (SEG_VALUE[tm[0]]<<8) | SEG_VALUE[tm[1]];
- }
- }
-
- else if(flag==3)
- {
- LED_CS3 = (SEG_VALUE[tm[0]]<<8) | SEG_VALUE[tm[1]];
- LED_CS2 = (SEG_VALUE[tm[2]]<<8) | SEG_VALUE[tm[3]];
- }
-
- //OSSemPost(Keypad_Sem);
- //OSTimeDly(50);
- }
復(fù)制代碼
總結(jié)
本次實驗完成了一個基本的基于實時操作系統(tǒng)的可以通過矩陣鍵盤設(shè)置時間的實時時鐘的設(shè)計。實驗中遇到了各種各樣的問題,究其根本還是對C語言掌握的不踏實,很多想當(dāng)然認(rèn)為的問題實際并不是那么回事。通過本次實驗,提高了調(diào)試代碼的能力,也對嵌入式系統(tǒng)有了進一步的認(rèn)識。
|
|