嵌入式系统设计课程设计.docx
《嵌入式系统设计课程设计.docx》由会员分享,可在线阅读,更多相关《嵌入式系统设计课程设计.docx(18页珍藏版)》请在冰豆网上搜索。
嵌入式系统设计课程设计
嵌入式理论及应用
设计题目:
基于μC/OS-II8*8点阵的设计与制作
嵌入式系统设计课程设计
一、概述
1.单片机介绍
单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
概括的讲:
一块芯片就成了一台计算机。
它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。
同时,学习使用单片机是了解计算机原理与结构的最佳选择。
2.单片机历史
单片机诞生于20世纪70年代末,经历了SCM、MCU、SoC三大阶段。
1.SCM即单片微型计算机(SingleChipMicrocomputer)阶段,主要是寻求最佳的单片形态嵌入式系统的最佳体系结构。
“创新模式”获得成功,奠定了SCM与通用计算机完全不同的发展道路。
在开创嵌入式系统独立发展道路上,Intel公司功不可没。
2.MCU即微控制器(MicroControllerUnit)阶段,主要的技术发展方向是:
不断扩展满足嵌入式应用时,对象系统要求的各种外围电路与接口电路,突显其对象的智能化控制能力。
它所涉及的领域都与对象系统相关,因此,发展MCU的重任不可避免地落在电气、电子技术厂家。
从这一角度来看,Intel逐渐淡出MCU的发展也有其客观因素。
在发展MCU方面,最著名的厂家当数Philips公司。
3.单片机是嵌入式系统的独立发展之路,向MCU阶段发展的重要因素,就是寻求应用系统在芯片上的最大化解决;因此,专用单片机的发展自然形成了SoC化趋势。
随着微电子技术、IC设计、EDA工具的发展,基于SoC的单片机应用系统设计会有较大的发展。
因此,对单片机的理解可以从单片微型计算机、单片微控制器延伸到单片应用系统。
3.单片机的应用领域
目前单片机渗透到我们生活的各个领域,几乎很难找到哪个领域没有单片机的踪迹。
导弹的导航装置,飞机上各种仪表的控制,计算机的网络通讯与数据传输,工业自动化过程的实时控制和数据处理,广泛使用的各种智能IC卡,民用豪华轿车的安全保障系统,录像机、摄像机、全自动洗衣机的控制,以及程控玩具、电子宠物等等,这些都离不开单片机。
更不用说自动控制领域的机器人、智能仪表、医疗器械了。
因此,单片机的学习、开发与应用将造就一批计算机应用与智能化控制的科学家、工程师。
单片机广泛应用于仪器仪表、家用电器、医用设备、航空航天、专用设备的智能化管理及过程控制等领域,在大型电路中,这种模块化应用极大地缩小了体积,简化了电路,降低了损坏、错误率,也方便于更换。
此外,单片机在工商,金融,科研、教育,国防航空航天等领域都有着十分广泛的用途。
二、单片机的结构与原理
1.AT89C55芯片
AT89C55单片机芯片内部结构框图如图1所示。
图1AT89C55单片机芯片内部结构
AT89C55,它是美国ATMEL公司生产的低电压,高性能CMOS8位单片机,片内含20kbytes的可反复擦写的Flash只读程序存储器(ROM)和256*8bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,与标准MCS-51指令系统及8052产品引脚兼容,片内置通用8位中央处理器(CPU)和Flash存储单元,功能强大AT89C55单片机适合于许多较为复杂控制应用场合。
主要性能参数:
·与MCS-51产品指令和引脚完全兼容
·20K字节可重擦写Flash闪速存储器
·1000次擦写周期
·全静态擦写周期:
0Hz—33Hz
·三级加密程序存储器
·256*8字节内部RAM
·32个可编程I/O口线
·三个16位定时/计数器
·8个中断源
·低功耗空闲和掉电模式
功能特性概述:
AT89C55是一种低功耗,高性能8位CMOS单片机,具有20K字节可重擦写Flash闪速存储器,该设备是采用Atmel的高密度非易失性内存技术,并与业界标准80C51指令集和引脚兼容,片上闪存程序存储器可重新编程的系统或由传统的非易失性内存编程通过将通用的8位CPU与Flash在monolithicchip芯片,AT89C55是一个强大的微型计算机提供了一个高度灵活和成本有效地解决许多嵌入式控制应用。
该AT89C55的标准提供了以下功能:
20,000字节的闪存,256内存,32个字节/O线,三个16位定时器/计数器,6向量两级中断结构,全双工串行端口,片上振荡器和时钟电路。
此外,AT89C55的目的是为降低到零频率静态逻辑,支持两种软件可选省电模式。
空闲模式停止的CPU,同时允许RAM工作,定时器/计数器,串行端口和中断系统继续运作。
运作。
在掉电模式保存RAM的内容,但冻结振荡器,禁用直到下一个硬件复位所有其他片上功能运作。
引脚说明:
Vcc:
电源供电
GND:
地
P0口:
P0口是一个8位漏极开路的双向I/O口。
作为输出口,每位能驱动8个TTL逻
辑电平。
对P0端口写“1”时,引脚用作高阻抗输入。
当访问外部程序和数据存储器时,P0口也被作为低8位地址/数据复用。
在这种模式下,
P0具有内部上拉电阻。
在flash编程时,P0口也用来接收指令字节;在程序校验时,输出指令字节。
程序校验
时,需要外部上拉电阻。
P1口:
P1口是一个具有内部上拉电阻的8位双向I/O口,p1输出缓冲器能驱动4个TTL逻辑电平。
对P1端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。
作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流(IIL)。
此外,P1.0和P1.2分别作定时器/计数器2的外部计数输入(P1.0/T2)和时器/计数器2的触发输入(P1.1/T2EX),
P2口:
P2口是一个具有内部上拉电阻的8位双向I/O口,P2输出缓冲器能驱动4个TTL逻辑电平。
对P2端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。
作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流(IIL)。
在访问外部程序存储器或用16位地址读取外部数据存储器(例如执行MOVX@DPTR)时,P2口送出高八位地址。
在这种应用中,P2口使用很强的内部上拉发送1。
在使用8位地址(如MOVX@RI)访问外部数据存储器时,P2口输出P2锁存器的内容。
在flash编程和校验时,P2口也接收高8位地址字节和一些控制信号。
P3口:
P3口是一个具有内部上拉电阻的8位双向I/O口,p2输出缓冲器能驱动4个TTL逻辑电平。
对P3端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。
作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流(IIL)。
RST:
复位输入。
关于这两个机器周期针高,而振荡器运行重置设备。
:
地址锁存控制信号(ALE)是访问外部程序存储器时,锁存低8位地址的输出脉冲。
在flash编程时,此引脚(
)也用作编程输入脉冲。
在一般情况下,ALE以晶振六分之一的固定频率输出脉冲,可用来作为外部定时器或时钟使用。
然而,特别强调,在每次访问外部数据存储器时,ALE脉冲将会跳过。
如果需要,通过将地址为8EH的SFR的第0位置“1”,ALE操作将无效。
这一位置“1”,ALE仅在执行MOVX或MOVC指令时有效。
否则,ALE将被微弱拉高。
这个ALE使能标志位(地址为8EH的SFR的第0位)的设置对微控制器处于外部执行模式下无效。
:
程序存储允许(
)输出是外部程序存储器的读选通信号,当AT89C52由外部程序存储器取指令(或数据)时,每个机器周期两次
有效,即输出两个脉冲。
在此期间,当访问外部数据存储器,将跳过两次
信号。
:
外部访问允许。
欲使CPU仅访问外部程序存储器(地址为0000H—FFFFH),
端必须保持低电平(接地)。
需注意的是:
如果加密位被编程,复位时内部会锁存EA端状态。
如EA端为高电平(接Vcc端),CPU则执行内部程序存储器中的指令。
Flash存储器编程时,该引脚加上+12V的编程允许电源Vpp,当然这必须是该器件是使用12V编程电压Vpp。
XTAL1:
振荡器反相放大器及内部时钟发生器的输入端。
XTAL2:
振荡器反相放大器的输出端。
用户软件写入1秒不应该对这些非上市地点,因为它们可用于未来的产品援引新功能。
在这种情况下,重置或新位无效值将始终为0。
定时器2:
控制和状态位载于登记T2CON(见表2)和T2MOD(见表4定时器2)。
登记册对(RCAP2H,RCAP2L的)是捕捉/定时器2装入寄存器的16位捕捉模式或16位自动重载模式。
中断寄存器:
个别中断使能位在IE名册。
两个优先事项可以设定6个中断源的IP每册。
数据存储器:
AT89C52有256个字节的内部RAM,高128个字节与特殊功能寄存器(SFR)地址是重叠的,也就是高128字节的RAM和特殊功能寄存器的地址的相同的,但物理上它们是分开的。
当一条指令访问7FH以上的内部地址单元时,指令中使用的寻址方式是不同的,也即寻址方式决定是访问高128字节RAM还是访问特殊功能寄存器。
如果指令是直接寻址方式则为访问特殊功能寄存器。
定时器0和定时器1:
AT89C52的定时器0和定时器1的工作方式与AT89C51相同。
定时器2:
定时器2是一个16位定进/计数器。
它既可当定时器使用,也可作为外部事件计数器使用,其工作方式由特殊功能寄存器T2CON的C/T2位选择。
定时器2有三种工作方式:
捕获方式,自动重装载(向上或向下计数)方式和波特率发生器方式,工作方式由T2CON的控制位来选择,如表3所示:
定时器2由两个8位寄存器TH2和TL2组成,在定时器工作方式中,每个机器周期TL2寄存器的值加1,由于一个机器周期由12个振荡时钟构成,因此,计数速率的1/12.
在计数工作方式时,当T2引脚上外部输入信号产生由1至9的下降沿时,寄存器的值加1,在这种工作方式下,每个机器周期的5SP2期间,对外部输入进行采样。
若在第一个机器周期中采到的值为1,而在下一个机器周期中采到的值为9,则在紧跟综着的下一个周期的S3P1期间寄存器加1.由于识别1至0的跳变需要2个机器周期(24个振荡周期),因此,最高计数速率为振荡频率的1/24.为确保采样的正确性,要求输入的电平在变化前至少保持一个完整周期的时间,以保证输入信号至少被采样一次。
可编程时钟输出:
定时器2可通过编程从P1.0输出一个占空比为50%的时钟信号,如图8所示。
P1.0引脚除了是一个标准的I/O口外,还可以通过编程使用作为定时/计数器2的外部时钟和输出占空比50%的时钟脉冲。
当时钟振荡频率为16MHz时,输出时钟频率范围为61Hz—4MHz。
当设置定时/计数器2为时钟发生器时,C/T2(T2CON.1)=0,(T2MOD.1)=1,必须由TR2(T2CON.2)启动或停止定时器。
时钟输出频率取决于振荡频率和定时器2捕获寄存器(RCAP2H,RCAP2L)的重新装载值,公式如下:
在时钟输出方式下,定时器2的翻转不会产生中断,这个特性与作为波特率发生器使用时相仿。
定时器2作为波特率发生器使用是,还可作为时钟发生器使用,但需要注意的是波特率和时钟频率不能分开确定,这是因为它们同使用RCAP2H和RCAP2L。
中断:
AT89C55共有6个中断向量:
两个外中断(INT0和INT1),3个定时器中断(定时器0、1、2)和串行口中断。
所有这些中断源如图所示。
这些中断源可通过分别设置专用寄存器IE的置位或清0来控制每一个中断的允许或禁止。
IE也有一个总禁止位EA,它能控制所有中断的允许或禁止。
注意表中的IE。
6为保留位,在AT89C51中IE。
5也是保留位。
程序员不应将“1”写入这些位,它们是将来AT89系列产品作为扩展用的。
定时器2的中断是由T2CON中的TF2和EXF2逻辑或产生的,当转向中断服务程序时,这些标志位不能被硬件清除,事实上,服务程序需要确定是TF2或EXF2产生中断,而由软件清除中断标志位。
定时器0和定时器1的标志位TF0和TF1在定时器溢出那个机器周期的S5P2状态置位,而会在下一个机器周期才查询到该中断标志。
然而,定时器2的标志位TF2在定时器溢出的那个机器周期的S2P2状态置位,并在同一个机器周期内查询到该标志。
三、uC\os-II在AT89C55上的移植
虽然μC/OS-II大部分源代码是用C语言写的,但是完成和处理器一些有关的代码时,照旧必须要用汇编语言来实现的。
要使uC\OS-II正常运行,必须满足一下要求:
(1)处理器的C编译器能产生可重入型代码。
(2)用C语言就可以打开和关闭中断。
(3)处理器支持中断,并且能产生定时中断(通常频率在10至100Hz之间)。
(4)处理器能支持容纳一定量的数据存储硬件堆栈(可能是几千字节)。
(5)处理器有将堆栈指针和其他CPU寄存器的内容读出并存储到堆栈或内存中的指令。
AT89C55与KeilCx51编译器可以满足以上条件,可以将uC\OS-II移植到AT89C55系列处理器。
需要说明一点,目前uC\OS-II的版本较多,但基本都一致,兼容性也很好,本例采用的是uC\OS-IIV2.52版。
μC/OS-II的移植包括以下几个部分。
(1)设置与编译器有关的代码[OS_CPU.H]
在差异的处理器中有差异的字长,所以必须界说一系列数据范例以确保移植的准确性。
另外,在uC/OS-II中,不使用C的short、int和long等数据范例,这些都是和编译器相干的。
下面即是uC/OS-II界说的一部分数据范例。
typedefunsignedcharBOOLEAN;
typedefunsignedcharINT8U;/*无标志8位整数*/
typedefsignedcharINT8S;/*有标志8位整数*/
typedefunsignedintINT16U;/*无标志16位整数*/
typedefsignedintINT16S;/*有标志16位整数*/
typedefunsignedlongINT32U;/*无标志32位整数*/
typedefsignedlongINT32S;/*有标志32位整数*/
typedeffloatFP32;/*单精度浮点数*/
typedefdoubleFP64;/*双精度浮点数*/
首先来看对临界段的处理,就是关中断,处理完毕后在开中断。
uC\OS-II提供了3种方法来处理,针对AT89C55单片机,可以使用方法1来处理临界段。
在AT89C55系列单片机中,中断允许寄存器IE的第7位EA为中断允许控制为,EA=0屏蔽所有中断、EA=1允许所有中断。
AT89C55堆栈从低地址往高地址增长(1=向下,0=向上),因此将OS_STK_GROWTH定义为0。
OS_TASK_SW()是一个宏,在uC\OS-II从低优先级任务切换到高优先级任务是被调用。
uC\OS-II假定任务切换时靠中断级代码完成的,或者说uC\OS-II的任务切换时靠模仿中断动作来完成的。
uC\OS-II需要一条处理器指令,使其行为就像是硬件中断。
MCS-51没有软中断指令,在这种情况下,需要将堆栈结构设置成与中断堆栈结构一样,在用函数调用的方式来实现任务切换,也就是说,通过函数来模仿软中断指令。
(2)用C语言编写6个与操作体系有关的函数[OS_CPU_C.C]这10个函数是:
OSTaskStkInit()、OSTaskCreatHook()、OSTaskDelHook()、OSTaskSwHook()、OSTaskStatHook()、OSTaskIdleHook()、OSTimeTickHook()、OSInitHookBegin()、OSInitHookEnd()和OSTCBInitHook()。
这10个函数只对OSTaskStkInit()编写代码,后9个函数必须声明,但是内部并没有代码。
在对堆栈设计时需要考虑一下因素:
<1>传统的8051处理器在中断来临时只将程序计数器PC的值压入堆栈。
<2>按照uC\OS-II的要求,保存全部寄存器,AT89C55的寄存器有PSW、ACC、B、DPL、DPH、R0-R7和SP。
<3>Cx51编译器允许用CPU寄存器传递3个参数。
<4>堆栈从低地址向高地址增长。
<5>堆栈指针指向上次入栈地址。
<6>AT89C55存在系统栈。
<7>系统栈深度为256字节。
因为需要进行任务栈与系统栈的复制,获得系统栈的起始地址,所以需要对系统进行一些定义。
首先,堆栈起点由Keil决定,只关心大小,然后通过SOStack获得keil分配的SP起点。
下面的代码就是相关的汇编代码,可以放在启动代码中,也可以放在相关的文件中。
为了函数重入,形参和局部变量必须保存在堆栈里。
MCS-51硬件堆栈太小,Keil将根据内存模式在相应内存空间仿真堆栈,增长方向由上向下,与硬件栈相反。
对于大模式编译,函数返回地址保存在硬件堆栈里,形参和局部变量放在仿真堆栈中,对MCS-51咬使用大模式编译。
3.编写4个汇编语言函数[OS_CPU_A.S]
uC/OS-II的移植实例要求用户编写4个简略的汇编语言函数:
OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()、OSTickISR()。
表2移植所需要的具体材料及移植的参数
编译器
硬件堆栈大小
任务栈大小
系统栈保存参数(包括模栈指针?
C_XBP)
每秒切换次数
定时器初值
单片机型号
KeilCx51
30H
50H
17
50
B800H
STC11F48XE
4.测试、编写驱动和应用步伐
做完以上事情以后,就要测试移植的是否准确。
测试一个μC/OS-II实时内核并不庞大,即是让这个实时内核在自己的目的板上跑起来。
uC/OS-II移植完成以后,就要在这个实时内核之上编写接口驱动步伐。
由于嵌入式操作体系体积更小,功效更强,且快速、稳固,更具有针对性,因此不像其它操作体系那样,对体系的全部接口配置都需要驱动、管理、调治和监视。
由于嵌入式产品是针对特别的用途而计划的,有很强的埋头性,因此,在编写驱动步伐时内容更精简,更具有稳固性,编写出的驱动模块更小。
编写驱动步伐应完成以下基本功效:
①对配置初始化和开释;②把数据从内核传送到硬件和从硬件读取数据;③读取应用步伐传送给配置文件的数据和回送应用步伐恳求的数据;④检测和处理配置出现的错误。
实现了以上功效以后,一个嵌入式操作体系就基本组成了。
4、系统硬件电路设计
1.复位电路部分
如图所示,当要对晶片重置时,只要按此开关就能完成LED和开关的重置。
2.晶振部分
产生时钟信号
3.总设计图
5、系统软件设计
#include"includes.h"
unsignedchari=0;
unsignedcharj=0;
unsignedchara[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsignedcharb[8]={0x30,0x18,0x24,0x12,0x24,0x18,0x30,0x00};
voidTaskStartyya(void*yydata)reentrant;
voidTaskStartyyb(void*yydata)reentrant;
voidTaskStartyyc(void*yydata)reentrant;
voidTaskStartyyd(void*yydata)reentrant;
voidTaskStartyye(void*yydata)reentrant;
OS_STKTaskStartStkyya[MaxStkSize];//注意:
我在ASM文件中设置?
STACK空间为40H即64。
OS_STKTaskStartStkyyb[MaxStkSize];//任务堆栈
OS_STKTaskStartStkyyc[MaxStkSize];
OS_STKTaskStartStkyyd[MaxStkSize];
OS_STKTaskStartStkyye[MaxStkSize];
voidmain(void)
{
OSInit();
InitTimer0();
InitSerial();
InitSerialBuffer();
KeyInit();
OSTaskCreate(TaskStartyya,(void*)0,&TaskStartStkyya[0],2);
OSTaskCreate(TaskStartyyb,(void*)0,&TaskStartStkyyb[0],3);
OSTaskCreate(TaskStartyyc,(void*)0,&TaskStartStkyyc[0],4);
OSTaskCreate(TaskStartyyd,(void*)0,&TaskStartStkyyd[0],5);
OSTaskCreate(TaskStartyye,(void*)0,&TaskStartStkyye[0],6);
OSStart();
}
voidTaskStartyya(void*yydata)reentrant//任务1
{for(;;)
{TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
P3=a[i];
P1=b[i];
i++;
if(i==8)
{i=0;}
}}
6、软件调试
1.软件调试
根据程序框图,写出对应的程序,在keilC中进行调试编译,生成.hex文件。
在Proteus中画出电路图,并装载上述生成的.hex文件,首先要对程序中的每个子函数进行功能测试,在得到我们想要的功能后还要对子函数与子函数之间的调用进行测试,在所有子函数测试都通过后才在能镶嵌到主函数中进行测试,仿真观察结果,根据结果再对程序进行修改,调试,直到满意为止。
2、硬件调试
2.1、检查元器件
在焊接之前应先检查各元器件的好坏。
检查电容、电感、电阻的大小是否正确。
检查二极管是否导通。
2.2、排列元器件
由于本次课程设计采用的是万用板,元器件在电路上的排列要自己排列分布好,以为焊接减少不必要的麻烦。
2.3、焊接
在分布好元器件的格局后,开始焊接,先焊接单片机底座、排母、其它元器件。
焊接完元器件后即元器件分布在万用板上已定型。
然后根据电路图,用导线连接各引脚。
在用导线连接时应注意,导线焊接在元器件引脚上时剥皮部分长度要适中。
每焊完一个元器件都应该检查是否有错。
2.4、调试
按照电路图焊接完毕后,检查电路完毕后。
单片机先不装上去,接上电源,用万用表测试单片机和液晶的电源引脚,看其值是否正常,不正常检查电路调试直至正常。
以避免烧坏元器件。
完成以上步骤后,接上电源装上单片机,看是否实现功能。
如果出错,检查电路,调试,直至出现正确结果。
七、实物组装
八、心得体会
经过这次课程设计,我觉得自己学到了不少东西。
归纳起来,主要有以下几点:
1.通过这次课程设计,我能将以前四年所学到的专业知识与实践相联系,将所学到的知识充分运用到本次设计中。
同时,我也认识到自己知识上不足的地方,体会到了所学理论知识的重要性,知识掌握得越多,设计得就更全面、更顺利、更好。
2.进一步熟悉了单片机的知识。
通过本次设计,我对单片机的基本原理、内部结构、各引脚功能、定时器和中断