上理工嵌入式答卷.docx
《上理工嵌入式答卷.docx》由会员分享,可在线阅读,更多相关《上理工嵌入式答卷.docx(29页珍藏版)》请在冰豆网上搜索。
上理工嵌入式答卷
研究生课程试题*
201/201学年第1学期考试课程嵌入式系统
学号姓名得分
一:
固件及软件描述题(20分)
1.1、阅读STM32启动代码,阅读STM(10X)固件标准,描述其主要观点。
1.2、描述MDK软件使用基本步骤。
二:
程序设计题(无操作系统)(20分)
2.1、根据固件建立工程,以流水灯为例说明固件建立工程和程序设计的方法(可自行设计硬件并结合该硬件进行阐述)
2.2、以按键中断实现灯的闪烁为例,描述设计其实现原理和主要程序设计含流程图。
(可自行设计硬件并结合该硬件进行阐述)
三.操作系统题(30分)
3.1、阐述裸μc/osII操作系统的基本原理(10分)。
3.2、如何在实现裸μc/osII系统的移植STM32(编译系统选MDK)(10分)。
3.3、在μc/osII系统中,中断实现的基本原理,并以按键中断实现灯的闪烁为例,阐述程序设计的基本方法。
(需结合硬件)(10分)
四.复杂工程题(30分)
4.1电子相框(或XXX)设计,根据自己的想法,阐述你心目中电子相框(或XXX)的功能及技术指标,并完成如下工程。
1)硬件电路设计(可以用PROTEL软件绘制)
2)软件设计。
一:
固件及软件描述题(20分)
1.1、阅读STM32启动代码,阅读STM(10X)固件标准,描述其主要观点。
答:
在嵌入式应用程序开发过程中,由于C语言编程,所以很少涉及到硬件底层寄存器的执行过程,一般都会直接在main函数里开始写代码,似乎main成了程序运行的起点。
但是,当MCU上电后,怎么找到main函数往往被忽略了,这就是启动代码的作用,因为系统是无法直接从硬件找到main函数的入口地址的,启动代码是用来初始化电路以及用来为高级语言写软件作好运行前准备的一小段汇编语言,是任何处理器上电复位时的程序运行入口点。
当刚上电的过程中,PC机会对系统的一个运行频率进行锁定在一个固定的值,这个设计频率的过程就是在汇编源代码中进行的,也就是在启动代码中进行的,也就是设置时钟频率。
时钟频率设置好了后,程序就开始运行,注意,程序是在存中运行的。
这个时候,就需要把一些源文件从flash里面copy到存中,又要对它们进行初始化读写,这又有频率的设置。
这些都是初始化。
初始化完成后,我们又要设置一些堆栈,要跳到C语言的main函数里面运行。
这就需要堆栈。
对普通的ARMCPU有这样一个要求:
在绝对地址为零的地方要放置一个异常向量表,但并不是所有的ARMCPU都留有这个一个空间,这就需要用到映射的功能。
我们可以将其它地方的一些空间映射到绝对地址里面。
当发生异常时,ARM核来读取异常中断表的时候,它会使用映射之后的那个表,这个就可以接着往下执行,否则在绝对地址零的地方找不到任何信息,程序就会死掉。
这些运行的环境全部建立好后,程序就会跳转到我们的main函数里面。
总之,启动代码,就是对最小系统的初始化。
包括晶振,CPU频率,向量表等。
STM32标准固件库,是一个固件函数包,它由程序、数据结构和宏组成,包括了微控制器所有外设的性能特征。
该函数库还包括每一个外设的驱动描述和应用实例,为开发者访问底层硬件提供了一个中间API,通过使用固件函数库,无需深入掌握底层硬件细节,开发者就可以轻松应用每一个外设。
每个外设驱动都由一组函数组成,这组函数覆盖了该外设所有功能。
STM32固件库其实就是一个函数库,它把程序模块话,封装起来了,开发者不需要写具体的程序代码,只需要调用即可。
1.2、描述MDK软件使用基本步骤。
答:
MDK软件的使用主要包括两个方面:
MDK软件的安装及其操作。
(1)keil软件的安装。
首先从www.embedinfo./下载到最新的keilMDK,下载完毕之后双击开始安装,可以看到一个欢迎界面:
点击Next,勾选安装协议,下一步,选择安装路径,填写用户信息:
点击Next就进入实质的安装过程了,然后等一会:
很快安装完毕,看到2个可选项:
1、保存当前uVision的设置。
2、载入以下选择的工程实例,默认即可。
点击Next,来到最后一个安装界面:
点击Finish,KeilMDK就完成安装了。
(2)操作。
1)在刚才解压“stm32f10x_fw_archivev2.0(May2009)”得到的文件夹里按照
路径\stm32f10x_fw_archivev2.0(May2009)\Archive,找到um0427.rar并将其解压。
2)在第1步解压到的um0427文件夹里按路径“\um0427\FWLib\project\RVMDK”找到文件:
“cortexm3_macro.s”和“stm32f10x_vector.s”,并将其复制到前面所新建的“STM32_FW\boot”文件夹中。
此二者为STM32在MDK环境下的启动的文件,是每一个STM32工程所必需的。
3)在“\um0427\FWLib\project”中找到文件:
“stm32f10x_it”和“stm32f10x_it”,并将其复制到“STM32_FW\interrupt”中。
此二者包含了STM32在MDK下的中断服务入口函数。
4)将“\um0427\FWLib\library”中的“inc”文件夹和“src”文件夹复制到“STM32_FW\library”中。
此二文件夹为STM32的固件函数库文件,一般情况下这两个文件夹里的文件都不推荐改动,可以设置只读属性。
5)最后请新建一个名字为“main.c”文件,放入“STM32_FW\src”中。
执行完以上操作后,应该得到如下结构:
STM32_FW\boot:
“cortexm3_macro.s”和“stm32f10x_vector.s”文件;
STM32_FW\interrupt:
“stm32f10x_it”和“stm32f10x_it”文件;
STM32_FW\src:
“main.c”文件;
STM32_FW\library:
“inc”文件夹和“src”文件夹;
19.jpg(31.02KB)
2011-1-1400:
37
二:
程序设计题(无操作系统)(20分)
2.1、根据固件建立工程,以流水灯为例说明固件建立工程和程序设计的方法(可自行设计硬件并结合该硬件进行阐述)
答:
1,首先下载并解压v3.5库函数.
2,先建一个文件夹取名LED,我们在LED文件夹里建立库函数的工程。
在LED文件夹下建立四个文件夹。
3,将库函数的里的文件STMv3.5\librarise\CMSIS\CM3\CoreSupport里的文件
STMv3.5\librarise\CMSIS\CM3\DeviceSupport\ST\STM32F10x里的文件
STMv3.5\librarise\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm里的文件
放入文件夹startup文件夹里面。
4,将库函数librarise\STM32F10_StdPeriph_Driver里的两个文件夹:
复制到建立的lib文件夹里。
5,在user文件夹里添加main.c文件,main.c文件里只写有如下代码即可:
此外,将库函数里的\Project\STM32F10x_StdPeriph_Template文件夹里的:
也复制到新建的user文件夹里面
6,Keil新建工程Ptoject\NewuVisionProject取名LED放在LED文件夹里面:
选择芯片型号:
这里选择STM32F103RB
点击OK后工程提示如下,选择否(因为我们建立的是库函数操作的工程,以上步骤中已经复制到文件夹里)。
点击
出现
设置如下:
点击TargetOptions
,设置如下:
其中
和
十分重要。
最后将设置输出的HEX文件到output文件夹:
如下图为最后设置完成的效果,编译之后没有问题:
流水灯程序设计方法如下:
首先我们来分析硬件电路,如下图所示:
其中PWR为系统电源指示灯,为蓝色。
LED0和LED1分别接在PB5和PE5上,为了方便判断DS0为红色的LED,DS1为绿色的LED。
由部的LED连线可知,要想发光二极管亮,就必须送入低电平,送入高电平则发光二极管熄灭,鉴于此原理,得出流水灯的程序流程图,如下所示:
PB5送低电平
PB5送高电平
延时
流水灯程序流程图
注:
程序代码见附件—LED流水灯程序
2.2、以按键中断实现灯的闪烁为例,描述设计其实现原理和主要程序设计含流程图。
(可自行设计硬件并结合该硬件进行阐述)
答:
在STM32中有中断这一概念,所谓中断,就是CPU正在工作时,突然来了一个优先级更高的中断源,向CPU发出中断请求,CPU暂时停止当前程序的执行转而处理新情况的程序和执行过程。
即在程序运行过程中,系统出现了一个必须由CPU立即处理的情况,此时CPU暂时中止程序的执行转而处理这个新的情况的过程就叫做中断。
3个按键中断,控制3个LED,当有按键按下时,触发中断,系统响应中断,进入中断服务子程序(控制LED灯),等处理完了之后系统又回到发生中断之前系统正在进行的任务。
首先编写main函数,主函数里包括常规的系统时钟配置、NIVC配置、GPIO配置、设置中断触发线、配置按钮中断触发方式、RCC配置。
然后编写子函数。
在NVIC子函数中需要分配中断向量表,设置中断优先级。
程序设计流程图如下图所示:
N
注:
程序代码见附件—按键中断
三.操作系统题(30分)
3.1、阐述裸μc/osII操作系统的基本原理(10分)。
答:
操作系统是裸机上的第一层软件,它是计算机系统中最重要的系统软件,是硬件的第一层封装与抽象,在计算机系统中占据着重要的地位,所有其它系统的软件与应用软件都依赖于操作系统的支持与服务。
除提供编程和接口外,操作系统还承担着任务管理、事件管理、消息管理、CPU管理、存管理、I/O管理等核心功能。
μC/OS-II是一种基于优先级的抢占式多任务实时操作系统,包含了实时核、任务管理、时间管理、任务间通信同步(信号量,,消息 队列)和存管理等功能。
它可以使各个任务独立工作,互不干涉,很容易实现准时而且无误执行,使实时应用程序的设计和扩展变得容易,使应用程序的设计过程大为减化。
μC/OS-II介绍
μC/OS-II是一个完整的、可移植、可固化、可裁剪的占先式实时多任务核。
μC/OS-II绝大部分的代码是用ANSI的C语言编写的,包含一小部分汇编代码,使之可供不同架构的微处理器使用。
至今,从8位到64位,μC/OS-II已在超过40种不同架构上的微处理器上运行。
μC/OS-II核结构
多任务系统中,核负责管理各个任务,或者说为每个任务分配CPU时间,并且负责任务之间的通讯。
核提供的基本服务是任务切换。
μC/OS-II可以管理多达64个任务。
由于它的作者占用和保留了8个任务,所以留给用户应用程序最多可有56个任务。
赋予各个任务的优先级必须是不相同的。
μC/OS-II为每个任务设置独立的堆栈空间,可以快速实现任务切换。
μC/OS-II近似地每时每刻总是让优先级最高的就绪任务处于运行状态,为了保证这一点,它在调用系统API函数、中断结束、定时中断结束时总是执行调度算法,μC/OS-II通过事先计算好数据简化了运算量,通过精心设计就绪表结构使得延时可预知。
3.2、如何在实现裸μc/osII系统的移植STM32(编译系统选MDK)(10分)。
答:
下面以LED实验为例,来说明如何在实现裸μc/osII系统的移植STM32。
1,用Keil软件打开LED工程,LED的工程文件如下所示:
这是开发裸机单片机程序时写的工程文件结构。
2,搭建uc/osII工程文件结构。
1)把LED工程所在的文件夹先改名为:
STM32+UCOS+LED。
2)在USER文件夹下新建includes.h头文件。
3)按照uc/osII文件结构图,在工程的目录下建立BSP文件夹、APP文件夹和uCOS-II文件夹。
BSP文件夹存放外设硬件驱动程序
APP文件夹存放应用软件程序
uCOS_II文件夹uc/osII的相关代码
4)把USER文件夹下的led.h和led.c文件剪切到BSP文件夹里。
在BSP文件夹里新建BSP.c和BSP.h文件。
5)在APP文件夹下建立app.c和app.h、app_cfg.h文件。
拷贝uc/os-II附件里的····\Software\EvalBoards\ST\STM32F103RB\IAR\OS-Probe-LCD\os_cfg.h到此目录。
6)把uC/OS-II源代码附件里的Software\uCOS-II下的Source文件夹复制到工程里刚才新建的uCOS-II文件夹里。
把··\Software\uCOS-II\Ports\arm-cortex-m3\Generic\IAR下的文件复制到工程uCOS-II文件夹中新建的Ports文件夹里。
复制后,选中全部文件,右键—属性—去除只读属性—确定。
7)打开工程文件,会发现提示错误,忽略它,直接点击确定。
出错的原因是我们修改了led.c和led.h的路径,所以需要手动删除原来的led.c:
建立BSP、APP和uCOS-II下两个文件夹,一共四个文件夹的组并添加相应的文件夹:
也要添加这四个文件件的编译路径:
即includepath设置为:
...\CMSIS;...\FWlib\inc;...\USER;...\APP;...\BSP;...\uCOS-II\Source
至此,完成全部工程的设置,现在开始移植修改代码。
8)配置cu/os-II
i)我们需要对os_cfg.h做如下修改:
首先禁用信号量、互斥信号量、、队列、信号量集、定时器、存管理,关闭调试模式:
其次,禁用多重事件控制:
修改os_cpu.h
将以上三个文件注释掉即可。
修改os_cpu_c.c
把OS_CPU_SysTickHandler(),OS_CPU_SysTickInit()及
注释掉(前面加#if0,后面加#endif就能注释掉)
修改os_cpu_a.asm
将下面的PUBIC改为EXPORT,即:
改为:
下面的这个也要改:
改为:
修改os_dbg.c
将里面的一条语句:
370.#defineOS_COMPLIER_OPT_root
该为:
371.#defineOS_COMPLIER_OPT//_root
修改startup_stm32f10x_hd.s
至此修改uc/os-II代码就结束了,接下来就是编写我们自己的代码。
编写includes.h(保存全部头文件的文件)
编写BSP:
BSP.c文件代码:
BSP.h头文件:
编写stm32f10x_it.c
需要在stm32f10x_it.c添加SysTick中断的处理代码:
407.voidSysTickHandler(void)
408.{OsintEnter();
OStimeTick();
OSIntExit();
}
9)创建任务
编写app_cfg.h用来设置任务的优先级和栈的大小
编写app.c这个是创建LED显示任务
编写app.h头文件
编写main()函数,这样就移植成功了。
3.3、在μc/osII系统中,中断实现的基本原理,并以按键中断实现灯的闪烁为例,阐述程序设计的基本方法。
(需结合硬件)(10分)
答:
1,首先,进行系统移植
(1)以Keil为开发软件,为uc/os-II操作系统建立一个目录,将操作系统核代码复制到一个目录下,最好是该目录的下一个子目录。
(2)在该目录下创建工程。
加入uc/os-II核文件到这个工程,搭建工程文件,详细步参考题3.2.
(3)配置μc/osII,修改部分代码,如os_cfg.h、os_cpu.h、os_cpu_c.c、
os_cpu_a.asm、os_dbg.c、startup_stm32f10x_hd.s等。
2,分析并搭建硬件电路
本实验过三个按键按下控制三个LED灯的亮暗情况,通过KEY-UP控制蜂鸣器,由电路的连线可以看出,当按键按下后要使灯亮则必须送高电平,
3,了解并熟悉STM32的每个I/O口都可以作为中断输入,要把I/O口作为外部中断输入,有以下几个步骤:
(1)初始化I/O口为输入。
(2)开启I/O口复用时钟,设置I/O口与中断线的映射关系。
STM32的I/O口与中断线的对应关系需要配置外部中断配置寄存器EXTICR,因此要先开启复用时钟,然后配置I/O口与中断线的对应关系,才能把外部中断与中断线连接起来。
(3)开启与该I/O口相对的线上中断/事件,设置触发条件,本实验设置成下降沿触发。
(4)设置中断分组(NVIC)并使能中断。
对于STM32的中断来说,只有配置了NVIC的设置并开启才能被执行,否则不会执行到中断服务函数中去。
(5)编写中断服务程序。
即编写有按键按下时LED灯就亮的中断服务程序,一共有三个。
4,编写主函数。
包括延时函数初始化、设置NVIC中断分组2:
两位抢占优先级,两位响应优先级、串口初始化、LED初始化、蜂鸣器端口初始化、按键连接初始化、外部中断初始化、点亮LED、延时。
5,编译,下载到硬件运行,查看结果和进行修改,直到成功。
四.复杂工程题(30分)
4.1电子相框(或XXX)设计,根据自己的想法,阐述你心目中电子相框(或XXX)的功能及技术指标,并完成如下工程。
1)硬件电路设计(可以用PROTEL软件绘制)
2)软件设计。
答:
1)见附件
2)主程序设计:
先对STM32及其外设进行初始化,再对界面进行初始化,接着根据功能选择而分别进入幻灯片模式或时间模式。
按键具体功能如下:
按键KEY0:
播放下一图片;按键KEY1:
播放上一图片;按键KEY2:
切换幻灯片模式与日期时间模式;按键RESET:
系统复位。
流程图:
程序:
intmain(void)
{
u8key;//返回检测按键值
u8t=0;//此值用于是否进行RTC的秒更新判断
FileInfoStruct*FileInfo;
u16pic_cnt=0;//当前目录下图片文件的个数
u16index=0;//当前选择的文件编号
u16time=0;//控制时间的变量
Stm32_Clock_Init(9);//系统时钟设置
delay_init(72);//延时初始化
uart_init(72,9600);//串口1初始化
LCD_Init();//初始化液晶
KEY_Init();//按键初始化
LED_Init();//LED初始化
SPI_Flash_Init();//SPIFLASH使能
RTC_Init();//RTC初次可配置时间
//EXTIX_Init();//外部中断初始化
if(Font_Init())//字库不存在,则更新字库
{
POINT_COLOR=RED;
LCD_ShowString(60,50,"MiniSTM32");
LCD_ShowString(60,70,"FontERROR");
while
(1);
}
POINT_COLOR=RED;
Show_Str(60,50,"CDUT",16,0);
Show_Str(40,70,"数码相框",16,0);
POINT_COLOR=DARKBLUE;
Show_Str(70,90,"仪器仪表",16,0);
Show_Str(90,110,"志强",16,0);
Show_Str(60,130,"201611",16,0);
Show_Str(50,150,"welcome",16,0);
POINT_COLOR=RED;
SD_Init();
while(FAT_Init())//FAT错误
{
Show_Str(60,170,"文件系统错误!
",16,0);
if(SD_Init())
{
Show_Str(60,190,"SD卡初始化失败!
",16,0);//SD卡初始化失败
Show_Str(60,210,"请检查SD卡是否插入?
",16,0);
}
delay_ms(500);
LCD_Fill(60,170,240,230,WHITE);//清除显示
delay_ms(500);
LED0=!
LED0;//红灯DS0指示运行有误
}
while(SysInfoGet
(1))//得到图片文件夹
{
Show_Str(60,170,"图片文件夹未找到!
",16,0);
Show_Str(0,190,"请在SD卡创建“PICTURE”文件夹!
",16,0);
delay_ms(500);
FAT_Init();
SD_Init();
LED0=!
LED0;//红灯DS0指示运行有误
LCD_Fill(0,170,240,210,WHITE);//清除上两行显示
delay_ms(500);
}
Show_Str(60,170,"开始显示图片...",16,0);
for(;time<3;time++)//延时3秒(注意:
delay_ms(u16)实参大于1000时延时不准)
delay_ms(1000);
time=0;
Cur_Dir_Cluster=PICCLUSTER;
while
(1)
{
pic_cnt=0;
Get_File_Info(Cur_Dir_Cluster,FileInfo,T_JPEG|T_JPG|T_BMP,&pic_cnt);//获取当前文件夹下面的目标文件个数
if(pic_cnt==0)//没有图片文件
{
LCD_Clear(WHITE);//清屏
while
(1)
{
if(time%3==0)//调整闪屏时间
Show_Str(20,170,"没有图片,请复制图片至SD卡中的PICTURE文件夹中,并重启系统!
",16,0);
elseLCD_Clear(WHITE);
time++;
delay_ms(300);
}
}
FileInfo=&F_Info[0];//开辟暂存空间.
index=1;
while
(1)
{
Get_File_Info(Cur_Dir_Cluster,FileInfo,T_JPEG|T_JPG|T_BMP,&index);//得到这图片的信息
LCD_Clear(WHITE);//清屏,加载下一幅图片的时候,一定清屏
AI_LoadPicFile(FileInfo,0,0,240,320);//显示图片
POINT_COLOR=BLUE;
Show_Str(0,0,FileInfo->F_Name,16,1);