实验目的
①了解RTC应用及其概念
②了解ARM串口通信的工作机制
③了解串口驱动程序的编写方法
④掌握实际控制RTC的方法,显示系统时间
⑤了解uCOS II的基本结构
⑥分析uCOS II源码
⑦掌握uCOS II的移植过程
⑧掌握uCOS II应用程序设计技巧
实验内容
①熟悉PXA270提供的实时时钟控制器
②熟悉PXA270提供的通用异步串行收发口
③参照提供的串口驱动程序,将RTC的当前值由串口输出
④结合LCD驱动程序,将RTC的值显示在LCD中,完成一个功能基本完备的数字时钟
⑤完成程序的编译和调试,并观察运行结果
⑥阅读uCOS II源代码,重点分析与硬件相关的文件内容
⑦熟悉PXA270的资源配置,掌握uCOS II必须使用资源的配置技巧
⑧掌握uCOS II的移植方法
⑨参照示例代码完成自己的多任务程序
⑩编译正确后,将映像下载到Flash中运行
实验原理
①RTC的控制
RTC的控制很简单,主要是初始化的一些配置,初始化后直接读写相应的寄存器就可以完成对时间的读取和重设操作。本实验为了方便起见,没有使用到RTC的中断,直接读取RTC的日期和时间寄存器。
对RTC进行初始化时,要对如下RTSR、RCNR、RYCR及RDCR寄存器进行初始化,其中各个寄存器的作用如下:
RTC状态寄存器——RTSR
RTSR寄存器包括了两个中断允许位和两个状态位。当RTSR[HZE]为1时并且检测到1-HZ时钟信号上升沿到来时,RTSR[HZ]便被自动设为1。当RTSR[ALE]为1时并检测到RCNR和RTAR相同时,RTSR[AL]便被自动设为1。RTSR[HZ]或RTSR[AL]为1时都会发送到中断控制器。
RTC计数寄存器——RCNR
RCNR是一个在1-HZ时钟脉冲信号上升沿触发下实现自动加1的32位可读写寄存器,该寄存器在系统复位后为0.
RTC年计数寄存器——RYCR
通过对该寄存器赋值,可以设置系统的起始时的年月日等日期参数。复位后自动设置的日期是2000年1月1日。该寄存器的数值变化与RTC天计数寄存器RDCR相关,当RDCR产生进位时,RYCR便会按照年月日的相应位实现变化。
RTC天数计数寄存器——RDCR
RDCR是一个计算系统一天时间变化的寄存器,该寄存器除了包含时分秒之外,还包括每月中的第几个星期以及摩天在该星期中的位置。秒计数位在1-Hz时钟脉冲信号的计时下自动增1,增加到59后就会向分计数位进位。依次按照七日与时间格式方式类推进位。
②uCOS应用程序编写
1)任务创建
OSTaskCreate(void (*task)(void *pd), void*pdata, OS_STK *ptos, INT8U proi);
基本的任务创建函数,入口参数分别为指向任务代码的函数指针pd,传递给任务的数据指针pdata,指向任务栈栈顶的指针ptos,任务的优先级proi。返回OS_NO_ERR表示任务创建成功;返回OS_PRIO_EXIT表示指定优先级的已经存在;返回OS_PRIO_INVALD表示指定的优先级比用户定义的最低优先级还低。
OSTaskCreate(void (*task)(void *pd), void*pdata, OS_STK *ptos, INT8U proi, INT16U id, OS_STK *pbos, INT32U stk_size,void *pext, INT16U opt);
扩展的任务创建函数,入口参数前四个与基本任务创建函数相同,扩展的入口参数包括:任务的ID号id;指向任务栈栈底的指针pbos;任务的栈的大小stk_size(以元素计,非字节);指向用户自定义任务控制块扩展的指针pext;额外的任务行为控制的标识符opt。
2)信号量实现任务同步
OSSemCreate(INT16U cnt);
创建一个信号量,输入参数包括信号量的初始值cnt。返回值:成功时返回一个指向与该信号量关联的事件控制块的指针;失败时返回0。
OSSemPend(OS_ENENT *pevent, INT16U timeout,INT8U *err);
获取一个信号量,入口参数包括:指向时间控制块的指针pevent;超时时间值timeout;传入的等待被填写的错误信息的指针err。
OSSemPost(OS_EVENT *pevent);
释放一个信号量,输入参数包括:指向事件控制块的指针。
实验步骤
第一步 分析代码
结合以上说明,对本实验提供的示例代码分析,深入理解针对具体的硬件实现,软件是如何配合工作的。
第二步 程序的编译和下载
利用ADS打开示例工程文件,执行Project→Make,编译、链接生成可执行映像文件
第三步 将生成的二进制.bin文件用H-Flasher下载到实验板中NOR Flash的0地址处,重启实验板。
程序说明
本次实验主要使用前几次实验的代码完成一个综合性的包括一个实时操作系统的实验,其中按键驱动和LCD显示部分做了少许修改,剩下主要工作是如何在操作系统下完成整个实验。
程序源代码、注释
- 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)
- {
- //普通数字键
- 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;
- }
- //确认键
- 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);
- }
复制代码
总结
本次实验完成了一个基本的基于实时操作系统的可以通过矩阵键盘设置时间的实时时钟的设计。实验中遇到了各种各样的问题,究其根本还是对C语言掌握的不踏实,很多想当然认为的问题实际并不是那么回事。通过本次实验,提高了调试代码的能力,也对嵌入式系统有了进一步的认识。
|