嵌入式系统综合设计实习解读.docx
- 文档编号:27586338
- 上传时间:2023-07-03
- 格式:DOCX
- 页数:25
- 大小:43.28KB
嵌入式系统综合设计实习解读.docx
《嵌入式系统综合设计实习解读.docx》由会员分享,可在线阅读,更多相关《嵌入式系统综合设计实习解读.docx(25页珍藏版)》请在冰豆网上搜索。
嵌入式系统综合设计实习解读
嵌入式系统综合设计实习
题目:
串口通讯实现单片机播放视频
班级:
学号:
姓名:
组员:
指导老师:
目录
1引言
2嵌入式系统
2.1嵌入式系统概述
2.2嵌入式操作系统
3IAP15F2K61S2硬件平台
4μC/OS-II操作系统
5基于IAP15F2K61S2单片机的μC/OS-II移植
5.1修改OS_CPU.H文件
5.2修改OS_CPU_C.C文件
5.3修改OS_CPU_A.ASM文件
5.4修改OS_CFG.H文件
5.5修改STARTUP.ASM文件
6μC/OS-II应用程序设计
7系统调试
8总结
9参考文献
10附录
1、引言
嵌入式操作系统近年来备受人们的关注,其开发出来的产品应用到生活的各个角落,随着嵌入式技术的发展前景日益广阔,相信会有更多的嵌入式操作系统软件出现。
uC/OS-II作为嵌入式操作系统的一种,它以高可靠性、稳定性和实时性占有着一定的嵌入式系统市场。
其结构简洁,可剪裁,移植性强,源代码开放。
而STC15系列单片机加密性强,低功耗,超低价,高速,高可靠,强抗静电,强抗干扰等特点,占有51系列单片机一定的市场。
本次课题是移植C/OS-II到IAP15F2K61S2单片机上,并且设计一个程序利用串口通信来使IAP15F2K61S2单片机实现播放视频。
2、嵌入式系统
2.1嵌入式系统概述
嵌入式系统(Embeddedsystem),是一种“完全嵌入受控器件内部,为特定应用而设计的专用计算机系统”,根据英国电气工程师协会(U.K.InstitutionofElectricalEngineer)的定义,嵌入式系统为控制、监视或辅助设备、机器或用于工厂运作的设备。
与个人计算机这样的通用计算机系统不同,嵌入式系统通常执行的是带有特定要求的预先定义的任务。
由于嵌入式系统只针对一项特殊的任务,设计人员能够对它进行优化,减小尺寸降低成本。
嵌入式系统是用来控制或者监视机器、装置、工厂等大规模设备的系统。
国内普遍认同的嵌入式系统定义为:
以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计算机系统。
通常,嵌入式系统是一个控制程序存储在ROM中的嵌入式处理器控制板。
事实上,所有带有数字接口的设备,如手表、微波炉、录像机、汽车等,都使用嵌入式系统,有些嵌入式系统还包含操作系统,但大多数嵌入式系统都是由单个程序实现整个控制逻辑。
2.2嵌入式操作系统
嵌入式操作系统(EmbeddedOperatingSystem,简称:
EOS)是指用于嵌入式系统的操作系统。
嵌入式操作系统是一种用途广泛的系统软件,通常包括与硬件相关的底层驱动软件、系统内核、设备驱动接口、通信协议、图形界面、标准化浏览器等。
嵌入式操作系统负责嵌入式系统的全部软、硬件资源的分配、任务调度,控制、协调并发活动。
它必须体现其所在系统的特征,能够通过装卸某些模块来达到系统所要求的功能。
目前在嵌入式领域广泛使用的操作系统有:
嵌入式实时操作系统µC/OS-II、嵌入式Linux、WindowsEmbedded、VxWorks等,以及应用在智能手机和平板电脑的Android、iOS等。
嵌入式操作系统应用广泛,其中的uC/OS-II嵌入式实时操作系统以高可靠性、稳定性和实时性占有着一定的嵌入式系统市场。
由于其结构简洁,可剪裁,移植性强,源代码开放,故非常适合初次接触嵌入式实时操作系统的人员进行学习[1]。
3、IAP15F2K61S2硬件平台
芯片使用宏晶公司最新STC15系列IAP15F2K61S2芯片。
ISP/IAP在系统可编程/在应用可编程,无需编程器,无需仿真器。
增强型8051CPU,1T,单时钟/机器周期,速度比普通8051快8-12倍。
61K字节片内片内Flash程序存储器,擦写次数10万次以上。
片内大容量2048字节的SRAM。
大容量片内EEPROM,擦写次数10万次数以上。
共8通道10位高速ADC,速度可达30万次/秒,3路PWM还可当3路D/A使用。
共3通道捕获/比较单元(CCP/PWM/PCA)。
内部高可靠复位,8级可选复位门槛电压,彻底省掉外部复位电路。
内部高精度R/C时钟,内部时钟从5MHz~35MHz可选,相当于普通8051的60MHz~420MHz。
两组高速异步串行通信端口(可同时使用),可在5组管脚之间进行切换,分时复用可当5组串口使用。
一组高速异步串行通信端口SPI[2]。
IAP15F2K61S2系统板特点:
1)、保险电路:
自动保险丝,防止电流过大,损坏内部单片机电路。
2)、USB下载电路:
CH340T下载芯片,一条USB线就可以实现供电、下载、串口通讯,方便稳定。
3)、自动冷启动电路:
板子持续使用自动冷启动电路,不用来回拨动开关上电,下载方便,增加了开关的使用率。
4)1602/12864接口电路:
可以直接插接液晶模块,方便稳定[3]。
4、μC/OS-II操作系统
μC/OS-II的前身是μC/OS,最早出自于1992年美国嵌入式系统专家JeanJ.Labrosse在《嵌入式系统编程》杂志的5月和6月刊上刊登的文章连载,并把μC/OS的源码发布在该杂志的BBS上。
μC/OS和μC/OS-II是专门为计算机的嵌入式应用设计的,绝大部分代码是用C语言编写的。
CPU硬件相关部分是用汇编语言编写的、总量约200行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的CPU上。
用户只要有标准的ANSI的C交叉编译器,有汇编器、连接器等软件工具,就可以将μC/OS-II嵌人到开发的产品中。
μC/OS-II具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点,最小内核可编译至2KB。
μC/OS-II已经移植到了几乎所有知名的CPU上。
严格地说uC/OS-II只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。
没有提供输入输出管理,文件系统,网络等额外的服务。
但由于uC/OS-II良好的可扩展性和源码开放,这些非必须的功能完全可以由用户自己根据需要分别实现。
uC/OS-II目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量,邮箱,消息队列,内存管理,中断管理等。
μC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。
1)核心部分(OSCore.c)
是操作系统的处理核心,包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。
能够维持系统基本工作的部分都在这里。
2)任务处理部分(OSTask.c)
任务处理部分中的内容都是与任务的操作密切相关的。
包括任务的建立、删除、挂起、恢复等等。
因为μC/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。
3)时钟部分(OSTime.c)
μC/OS-II中的最小时钟单位是timetick(时钟节拍)。
任务延时等操作是在这里完成的。
4)任务同步和通信部分
为事件处理部分,包括信号量、邮箱、邮箱队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。
5)与CPU的接口部分
是指μC/OS-II针对所使用的CPU的移植部分。
由于μC/OS-II是一个通用性的操作系统,所以对于关键问题上的实现,还是需要根据具体CPU的具体内容和要求作相应的移植。
这部分内容由于牵涉到SP等系统指针,所以通常用汇编语言编写。
主要包括中断级任务切换的底层实现、任务级任务切换的底层实现、时钟节拍的产生和处理、中断的相关处理部分等内容[4]。
5、基于IAP15F2K61S2单片机的μC/OS-II移植
所谓移植,就是使一个实时内核能在某个微处理器或微控制器上运行。
为了方便移植,大部分的μC/OS-Ⅱ代码是用C语言写的;但仍需要用C和汇编语言写一些与处理器相关的代码,这是因为μC/OS-Ⅱ在读写处理器寄存器时只能通过汇编语言来实现。
由于μC/OS-Ⅱ在设计时就已经充分考虑了可移植性,所以μC/OS-Ⅱ的移植相对来说是比较容易的[5]。
μC/OS系统移植主要是要修改与处理器相关的文件:
OS_CPU.H,OS_CPU_C.C,OS_CPU_A.ASM。
由于是在keilC51下编译因此还需要将不需要的功能删减掉,因此还需要修改OS_CFG.H文件。
在这些文件中OS_CPU.H的内容是相关的数据类型、关中断、任务堆栈方向、任务切换宏定义等。
OS_CPU_C.C主要是关于OSTaskStkInit()函数和系统中断定时器的编写。
OS_CFG.H这个文件系统中相关功能的配置文件,如果要用到邮箱,信号等功能,都要在这个头文件中把相关宏设置为1。
5.1、修改OS_CPU.H文件
首先修改的是OS_CPU.H文件,根据IAP15F2K61S2单片机的信息这是一个16位处理器,并且堆栈为8bit,因此关于数据类型应该修改为以下这样:
typedefunsignedcharBOOLEAN;
typedefunsignedcharINT8U;/*无符号8位数*/
typedefsignedcharINT8S;/*有符号8位数*/
typedefunsignedintINT16U;/*无符号16位数*/
typedefsignedintINT16S;/*有符号16位数*/
typedefunsignedlongINT32U;/*无符号32位数*/
typedefsignedlongINT32S;/*有符号32位数*/
typedeffloatFP32;/*单精度浮点数*/
typedefdoubleFP64;/*双精度浮点数*/
typedefunsignedcharOS_STK;/*栈单元宽度为8比特*/
μC/OS-Ⅱ代码从不使用C的short,int和long等数据类型,因为它们是与编译器相关的,不可移植。
相反的,INT16U、INT16S这些都是可移植而且很直观的数据类型,例如INT16U数据类型总是代表16位的无符号整数。
在移植过程中不同的处理器有不同字长,例如在16位处理器上unsignedint代表的是16位无符号整型,但是在32位处理器上unsignedint确实代表32位无符号整型。
因此在移植过程中就需要对这些数据类型进行相应的修改。
用户必须将任务堆栈的数据类型告诉给μC/OS-Ⅱ。
这个过程是通过OS_STK声明正确的C数据类型来完成的。
如果用户的处理器上的堆栈成员是8位的,并且用户的编译文件指定字符型为8位数,那么就应该将OS_STK声明位无符号字符型数据类型。
所有的任务堆栈都必须用OS_STK来声明数据类型。
定义好数据类型后,还有两点需要定义好。
一是堆栈的成长方向,如果是由下往上成长则OS_STK_GROWTH置0,如果是由上往下成长则OS_STK_GROWTH置1。
二是关于中断的设置,与所有的实时内核一样,μC/OS-Ⅱ需要先禁止中断再访问代码的临界段,并且在访问完毕后重新允许中断。
这就使得μC/OS-Ⅱ能够保护临界段代码免受多任务或中断服务例程的破坏。
这次使用的IAP15F2K61S2单片机堆栈成长方式为由下往上成长,而中断允许总控位为EA,EA=0表示关所有中断,EA=1表示开所有中断。
因此相应代码修改如下:
#defineOS_ENTER_CRITICAL()EA=0/*关中断*/
#defineOS_EXIT_CRITICAL()EA=1/*开中断*/
#defineOS_STK_GROWTH0/*STC-15堆栈从下往上增长1=向下,0=向上*/
最后,由于IAP15F2K61S2单片机是没有软中断指令的,因此任务切换宏OS_TASK_SW()的定义如下:
#defineOS_TASK_SW()OSCtxSw()/*因为没有软中断指令,所以用程序调用代替。
*/
5.2、修改OS_CPU_C.C文件
接下来是修改OS_CPU_C.C文件,这个文件要求用户编写六个简单的C函数:
OSTaskStkInit()、OSTaskCreateHook()、OSTaskDelHook()、OSTaskSwHook()、OSTaskStatHook()、OSTimeTickHook(),其中只需修改任务堆栈初始化函数OSTaskStkInit(),其它函数是对系统内核扩展时用的,必须声明但没必要包含代码。
用户堆栈初始化时从下向上依次保存:
硬件栈大小15,即两个任务返回地址和13个寄存器、任务的地址低8位和高8位以及13个寄存器。
不用保存SP,任务切换时根据用户堆栈长度计算得出。
相应的代码编写如下:
voidDT_XDATA*OSTaskStkInit(void(DT_CODE*task)(voidDT_XDATA*pd),voidDT_XDATA*ppdata,voidDT_XDATA*ptos,INT16Uopt)REENTRANT
{
OS_STKDT_XDATA*stk;
ppdata=ppdata;
opt=opt;
stk=(OS_STKDT_XDATA*)ptos;/*ptos指向的为用户栈的栈底,向上生长,依次存储*/
*stk++=(0xFF+1);/*仿真栈栈顶指针C_IBP*/
/*simulatedstacksize==0*/
*stk++=2+13;/*硬件栈大小15,两个任务返回地址和13个寄存器*/
*stk++=(INT16U)task&0xFF;/*任务地址低8位*/
*stk++=(INT16U)task>>8;/*任务地址高8位*/
*stk++=0x0A;/*ACC*/
*stk++=0x0B;/*B*/
*stk++=0xD1;/*DPH*/
*stk++=0xD0;/*DPL*/
*stk++=0x00;/*PSW*/
*stk++=0x00;/*R0*/
*stk++=0x01;/*R1*/
*stk++=0x02;/*R2*/
*stk++=0x03;/*R3*/
*stk++=0x04;/*R4*/
*stk++=0x05;/*R5*/
*stk++=0x06;/*R6*/
*stk++=0x07;/*R7*/
return((voidDT_XDATA*)ptos);/*notereturnptos,notstk*/
}
另外5个函数为钩挂函数,在需要添加附加功能时可以编写相应的代码。
μC/OS-II中每个任务都有自己的任务堆栈,在任务创建初期由函数OSTaskStkInit()初始化。
任务堆栈中保存了任务代码的起始地址和一些与CPU寄存器相关的内容,这样一旦满足任务的运行条件就可以从起始的状态“无缝”地执行该任务。
除此之外还要编写一个时钟节拍中断函数OSTickISR(),将其定义为定时器0中断函数,具体代码如下:
voidOSTickISR()interrupt1/*定时器0中断函数*/
{
TL0=TIMER_24M_25MS_L;
TH0=TIMER_24M_25MS_H;
OSIntEnter();
OSTimeTick();/*维持操作系统内部的时钟*/
OSIntExit();/*使高优先级的任务就绪*/
}
5.3、修改OS_CPU_A.ASM文件
接下来是修改OS_CPU_A.ASM文件,这里需要改写四个汇编语言函数:
OSStartHighRdy(),OSCtxSw(),OSIntCtxSw(),OSTickISR()。
其中OSStartHighRdy()功能为使就绪态任务中优先级最高的任务开始运行,即获取当前就绪的最高优先级任务的堆栈指针。
OSCtxSw()功能为完成任务级切换。
先保存当前任务堆栈的内容,然后恢复最高优先级任务的系统堆栈。
OSIntCtxSw()功能为完成中断级切换,该函数由OSIntExit()调用。
在调用函数OSIntCtxSw()之前,已经保存了被终止运行程序相关寄存器的值到中断的任务堆栈中,此处只需恢复待运行任务的系统堆栈。
OSTickISR()功能是为系统提供一个时钟源,实现时间的延迟和超时功能,该函数已在OS_CPU_C.C中定义具体实现方法。
关于OS_CPU_A.ASM文件的内容详情见附录。
5.4、修改OS_CFG.H文件
为了尽可能地缩短代码的大小,因此除必要功能外将其他的功能屏蔽掉,
其中需要屏蔽的功能有:
OS_TASK_STAT_EN、OS_MBOX_EN、OS_MEM_EN、OS_Q_EN、OS_SEM_EN、OS_TASK_CHANGE_PRIO_EN、OS_TASK_CREATE_EXT_EN、OS_TASK_DEL_EN、OS_TASK_SUSPEND_EN。
即:
#defineXXXX0//XXXX为需要屏蔽的功能
具体代码如下:
#defineOS_CPU_HOOKS_EN1/*为1时,使用系统提供的函数*/
#defineOS_TASK_STAT_EN0/*统计任务使能,不需要设为0*/
#defineOS_MBOX_EN0 /*设置为0,禁止产生邮箱代码*/
#defineOS_MEM_EN0 /*设置为0,禁止产生内存关系代码*/
#defineOS_Q_EN0 /*设置为0,禁止使用消息队列*/
#defineOS_SEM_EN0 /*设置为0,禁止使用信号量功能*/
#defineOS_TASK_CHANGE_PRIO_EN0
#defineOS_TASK_CREATE_EN1
#defineOS_TASK_CREATE_EXT_EN0
#defineOS_TASK_DEL_EN0
#defineOS_TASK_SUSPEND_EN0
另外,将最大任务数修改为5,为以后扩展任务预留空间,即:
#defineOS_MAX_TASKS5
修改任务最低优先级为20,即:
#defineOS_LOWEST_PRIO20
因为定时器设定为20毫秒,所以修改系统时钟节拍为50:
#defineOS_TICKS_PER_SEC50
5.5、修改STARTUP.ASM文件
设置小模式仿真栈允许,即设置IBPSTACK为1;设置小模式下的仿真栈的栈顶指针为0xFF+1。
6、μC/OS-II应用程序设计
这次实习的程序设计我们小组是打算通过串口通讯连续发送图片实现播放视频的功能,其中我主要是负责12864显示模块的程序编写。
通过查询12864的中文手册,我发现12864显示图形时水平方向X是以字节为单位,而垂直方向Y是以位为单位。
12864显示时将屏幕分为上下两部分,上部分由左往右分为0X80~0X87八个块,其中每个块是两个字节,由上往下分为0~31行;而下部分由左往右分为0X88~0X8F八个块,其中每个块是两个字节,由上往下分为0~31行。
下图为12864显示时的坐标定义
因此当把图片写进12864时,需要将上下两部分分开写,而且每一行写16个字节,具体代码如下:
voidlcdwpic(char*pic_addr)
{
chari,j;
for(i=0;i<32;i++)//上部分写图片
{
lcdwc(0x80+i);//先写入垂直坐标值
lcdwc(0x80);//写入水平坐标值
for(j=0;j<16;j++)//再写入16字节的数据
lcdwd(*pic_addr++);
}
for(i=0;i<32;i++)//下部分写图片
{
lcdwc(0x80+i);//先写入垂直坐标值
lcdwc(0x88);//写入水平坐标值
for(j=0;j<16;j++)//再写入16字节的数据
lcdwd(*pic_addr++);}}
另外由于需要传输很多张图片进行显示,因此需要定义一个可以修改数据的数组来充当图片的临时存放数组,因为需要显示的图片是128*64分辨率,每一张图片是1024字节,所以数组大小为1024。
即:
ucharxdatapictmp[1024]={0};
因为一张图片是1024字节,因此需要让pictmp[]数组存满才将图片显示出来,所以定义一个计数的变量当传完1024字节在调用写图片函数,而且存数据进pictmp[]中时需要先将串口中断关闭,具体代码如下:
voidISP_Check(unsignedchartmp)
{
ES=0;
pictmp[count]=tmp;
count++;
if(count==1024)
{
count=0;
lcdwpic(pictmp);
}
ES=1;
}
因为是串口通讯,所以编写一个串行中断函数用来处理数据的接收,函数中定义一个变量负责将SBUF寄存器中的数据取出,并且将数据存进图片临时存放数组pictmp[],具体代码如下:
voidSerial_int(void)interrupt4using1/*函数为串行中断,使用寄存器组1*/
{
unsignedchartmp;
if(RI)
{
tmp=SBUF;
ISP_Check(tmp);
RI=0;
}
}
本次串口通讯需要在晶振为11.0592MHz,波特率为115200bps下执行,因此需要定义一个初始化函数设定波特率并且将串口中断以及总中断打开,代码如下:
voidUartInit(void)//115200bps@11.0592MHz
{
PCON&=0x7F;//波特率不倍速
SCON=0x50;//8位数据,可变波特率
AUXR|=0x40;//定时器1时钟为Fosc,即1T
AUXR&=0xFE;//串口1选择定时器1为波特率发生器
TMOD&=0x0F;//清除定时器1模式位
TMOD|=0x20;//设定定时器1为8位自动重装方式
TL1=0xFD;//设定定时初值
TH1=0xFD;//设定定时器重装值
ET1=0;//禁止定时器1中断
TR1=1;//启动定时器1
ES=1;//开串口中断
EA=1;//开总中断
}
7、系统调试
关于μC/OS-II系统经过编写两个小任务测试可以正常运行,但是串口通讯显示视频程序经同组人员测试,由于程序实时性过高加到μC/OS-II系统后无法正常运行,经过与老师商量决定放弃将程序加进μC/OS-I
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式 系统 综合 设计 实习 解读
![提示](https://static.bdocx.com/images/bang_tan.gif)