北航ARM9实验报告

更新时间:2024-01-29 04:15:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1

ARM9嵌入式系统实验

实验报告

院(系)名称 自动化科学与电气工程学院 学生姓名 学

任课老师

2013年 11 月 15 日

北京航空航天大学研究生实验报告

实验一

ARM基础知识和开发环境

一、实验目的

1.掌握ARM的串行口工作原理。 2.学习编程实现ARM的UART通讯。 3.掌握S3C2410寄存器配置方法。

二、实验内容

1.熟悉打开已有工程的步骤,掌握仿真调试的方法。

2.建立一个新工程,熟练掌握编译器和链接器的设置方法。

3.从串口输入字符串,将0~9数字在超级终端上连续显示,―Enter‖键换行。 4.将第三步得到的字符转换成BCD码,限制在0~1023,用于控制直流电机。

三、预备知识

1. 了解EWARM集成开发环境的基本功能 2. 学习串口通讯的基本知识

3. 熟悉S3C2410串口有关的寄存器

四、实验设备及工具

1. 2410s教学实验箱

2. S3C2410的JTAG仿真器

3. ARM EWARM5.3集成开发环境 4. 串口连接线

五、实验原理及说明

1. 异步串行I/O

异步串行方式是将传输数据的每个字符一位接一位(例如先低位、后高位)地传送。数据的各不同位可以分时使用同一传输通道,因此串行I/O可以减少信号连线,最少用一对线即可进行。接收方对于同一根线上一连串的数字信号,首先要分割成位,再按位组成字符。为了恢复发送的信息,双方必须协调工作。在微型计算机中大量使用异步串行I/O方式,双方使用各自的时钟信号,而且允许时钟频率有一定误差,因此实现较容易。但是由于每个字符都要独立确定起始和结束(即每个字符都要重新同步),字符和字符间还可能有长度不定的空闲时间,因此效率较低。

- 1 -

北京航空航天大学研究生实验报告

2. RS-232C接口通信的两种基本连接方式

这是美国电子工业协会推荐的一种标准(Electronic industries Association

Recoil-mended Standard)。它在一种25针接插件(DB—25)上定义了串行通信的有关信号。这个标准后来被世界各国所接受并使用到计算机的I/O接口中。两种连接方式如下图:

3. 信号电平规定

1) EIA电平:双极性信号逻辑电平, 它是一套负逻辑定义

? -3V到-25V之间的电平表示逻辑―1‖。 ? +3V到+25V之间的电平表示逻辑―0‖。

2) TTL电平:计算机内部(S3C2410)使用LVTTL电平 3) 电平转换电路:常用专门的RS-232接口芯片,如SP3232、SP3220等,在LVTTL

电平和EIA电平之间实现相互转换。

4. 异步串行口接口电路

六、实验方法

1. 以实验一为模板,完成实验的1和2。

2. 将接收串口数据的数组cl[1]改为cl[256],用cl[i]==0x0d 回车字符作为一帧结束的

条件。

3. 将―Exp4 电机转动控制实验‖ inc目录下的MotorCtrl.H 和src目录下的MotorCtrl.C

拷到该工程相应目录,将MotorCtrl.C 添加到工程中。

4. 在main函数里包含以下头文件 #include ―../inc/MotorCtrl.h‖

5. 在main函数里包含以下头文件 #include ―inc/macro.h―,#define

MOTOR_COUNT 12657。

6. 在Main函数里执行init_MotorPort()。

7. 直流电机调试的函数是 SetPWM((setspeed -512)*MOTOR_COUNT/1024),

setspeed是速度指令,取值范围0~1023。

七、程序源代码

#include \#include \

- 2 -

北京航空航天大学研究生实验报告

#define U8 unsigned char #include #include #define TRUE 1 #define FALSE 0

#define MOTOR_COUNT 12657

//#pragma import(__use_no_semihosting_swi) // ensure no functions that use semihosting

#define rUTRSTAT0 (*(volatile unsigned *)0x50000010) #define rUTRSTAT1 (*(volatile unsigned *)0x50004010)

#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch) #define WrUTXH1(ch) (*(volatile unsigned char *)0x50004020)=(unsigned char)(ch) #define RdURXH0() (*(volatile unsigned char *)0x50000024) #define RdURXH1() (*(volatile unsigned char *)0x50004024) //void Uart_SendByten(int Uartnum, U8 data); void Uart_SendByten(int,U8);

char Uart_Getchn(char* Revdata, int Uartnum, int timeout);

unsigned int num;

void ARMTargetInit(void); void hudelay(int time); int main(void) { //int ndev; char c[2];

char err; ARMTargetInit(); // do target (uHAL based ARM system) initialisation // init_MotorPort(); Uart_SendByten(0,0xa);//换行 Uart_SendByten(0,0xd);//回车

printf(\ while(1) { err=Uart_Getchn(c,0,0); //从串口采集数据

if (err==TRUE) {

if(c[0] == '\\r') {

Uart_SendByten(0,0xa);//换行

- 3 -

北京航空航天大学研究生实验报告

Uart_SendByten(0,0xd);//回车 if(num < 1024) {

printf(\ SetPWM((num -512)*MOTOR_COUNT/1024); } else {

printf(\ }

num = 0;

Uart_SendByten(0,0xa);//换行 Uart_SendByten(0,0xd);//回车

printf(\ } else {

Uart_SendByten(0,c[0]); //显示采集的数据 if(c[0] > '9' || c[0] < '0') {

Uart_SendByten(0,0xa);//换行 Uart_SendByten(0,0xd);//回车

printf(\ Uart_SendByten(0,0xa);//换行 Uart_SendByten(0,0xd);//回车

printf(\ num = 0; } else {

c[1] = c[0] - '0';

num = num * 10 + c[1]; } } } } }

void Uart_SendByten(int Uartnum, U8 data)//ok eric rong { //int i; if(Uartnum==0) { while(!(rUTRSTAT0 & 0x4)); //Wait until THR is empty.

- 4 -

北京航空航天大学研究生实验报告

hudelay(10); WrUTXH0(data); } else { while(!(rUTRSTAT1 & 0x4)); //Wait until THR is empty. hudelay(10); WrUTXH1(data); } }

char Uart_Getchn(char* Revdata, int Uartnum, int timeout) { if(Uartnum==0){ while(!(rUTRSTAT0 & 0x1)); //Receive data read *Revdata=RdURXH0(); return TRUE; } else{ while(!(rUTRSTAT1 & 0x1));//Receive data read *Revdata=RdURXH1(); return TRUE; } }

八、思考题

1. 232串行通讯的数据格式是什么? 答:格式如下图所示

2. 串行通讯最少需要几根线,分别如何连接?

答:至少需要三根线,分别是发送线,接收线,和接地线。连接方法如图所示,

- 5 -

北京航空航天大学研究生实验报告

3. ARM的串行口有几个,相应的寄存器是什么? 答:S3C2410自带三个异步串行口控制器。控制寄存器UCONn,FIFO控制寄存器UFCONn,线路控制寄存器ULCONn,控制寄存器UMCONn,状态寄存器UTRSTAT,错误状态寄存器UERSTAT,FIFO状态寄存器UFSTAT,发送寄存器UTXH和接收寄存器URXH,波特率因子寄存器UBRDIV。

4. 用中断方式实现串口驱动。

答:中断方式实现串口驱动的流程图如下:

- 6 -

北京航空航天大学研究生实验报告

实验二

LCD 和电机等综合实验

一、实验目的

1.熟悉ARM本身自带的六路即三对PWM,掌握相应寄存器的配置。

2.编程实现ARM系统的PWM输出用于控制直流电机。 3.了解LCD基本概念与原理。 4.理解LCD的驱动控制。

5.熟悉用ARM内置的LCD控制器驱动LCD。

二、实验内容

学习直流电机的工作原理,了解实现电机转动对于系统的软件和硬件要求。学习ARM知识,掌握PWM的生成方法。

1.编程实现ARM芯片的一对PWM输出用于控制直流电机的转动,通过A/D旋钮控制其正反转及转速。

2.通过超级终端来控制直流电机的转动。 学习LCD显示器的基本原理,理解其驱动控制方法。掌握两种LCD驱动方式的基本原理和方法。并用编程实现:

1. 用ARM内置的LCD控制器来驱动LCD。

三、预备知识

1、用EWARM集成开发环境,编写和调试程序的基本过程。 2、ARM应用程序的框架结构。

3、掌握通过ARM自带的A/D转换器的使用。 4、了解直流电机的基本原理。

四、实验设备及工具

硬件:ARM嵌入式开发平台、用于S3C2410的JTAG仿真器、PC机Pentium100以上。 软件:PC机操作系统Win2000或WinXP、EWARM集成开发环境、仿真器驱动程序、超级终端通讯程序

五、实验原理及说明

1)直流电动机的PWM电路原理

晶体管的导通时间也被称为导通角а,若改变调制晶体管的开与关的时间,也就是说通过改变导通角а的大小,如下图所示,来改变加在负载上的平均电压的大小,以实现对电动机的变速控制,称为脉宽调制 (PWM)变速控制。在PWM变速控制中,系统采用直流电源,放大器的频率是固定,变速控制通过调节脉宽来实现。

- 7 -

北京航空航天大学研究生实验报告

2)开发平台中直流电机驱动的实现

开发板中的直流电机的驱动部分如图7-3所示;由于S3C2410X芯片自带PWM定时器,所以控制部分省去了三角波产生电路、脉冲调制电路和PWM信号延迟及信号分配电路,取而代之的是S3C2410X芯片的定时器0、1组成的双极性PWM发生器。

PWM发生器用到的寄存器主要有以下几个:TCFG0、TCFG1、TCON、TCNTB0 & TCMPB0、TCNTO0。

3)LCD(Liquid Crystal Display)原理

液晶得名于其物理特性:它的分子晶体,以液态存在而非固态。 LCD显示器的基本原理就是通过给不同的液晶单元供电,控制其光线的通过与否,从而达到显示的目的。因此,LCD的驱动控制归于对每个液晶单元的通断电的控制,每个液晶单元都对应着一个电极,对其通电,便可使光线通过(也有刚好相反的,即不通电时光线通过,通电时光线不通过)。

4)S3C2410 LCD控制器逻辑框图

5)UPTECH-2410-S LCD图形显示方式

UPTECH-2410-S的LCD显示模块由LCD控制器和16位色彩色LCD示器组成。其显示方式以直接操作显示缓冲区的内容进行,LCD控制器会通过DMA从显示缓冲区中获取数据,不需要CPU干预。

本系统采用的LCD分辨率为640X480,工作在65536色彩色显示模式,在该模式下,显示缓冲区中的一个字节数据代表LCD上的一个点的颜色信息,因此,所需要的显示缓冲区大小为640X480X2字节。其中每个字节的彩色数据格式如下图所示:

- 8 -

北京航空航天大学研究生实验报告

六、实验方法

电机试验

1 通过一个电位器控制直流电机转动速度,并且用该电位器值使屏幕显示不同颜色。 2 用三个电位器分别控制R、G、B,观察屏幕的变化。 3 使用函数Uart_Printf(),将RGB的值打印到串口输出。 LCD实验:

1 在Main函数里执行LCD_Init();

2 将AD采样的结果在驱动电机的同时,和jcolor建立起联系。 3 显示缓冲区填充LCDBufferII2[k][j]=jcolor; 4 调用LCDFresh()函数。

七、程序源代码

#include \#include \#include #include #include

#include \#include \#include \#include \#include \

#define MCLK (50700000)

#define MOTOR_SEVER_FRE 1000 //20kHz #define MOTOR_CONT (MCLK/2/2/MOTOR_SEVER_FRE) #define MOTOR_MID (MOTOR_CONT/2)

#define ADCCON_FLAG (0x1<<15)

//#define ADCCON_ENABLE_START_BYREAD (0x1<<1) #define ADCCON_ENABLE_START_BYREAD (0x0<<1)

#define rADCCON (*(volatile unsigned *)0x58000000) #define rADCDAT0 (*(volatile unsigned *)0x5800000C) #define PRSCVL (49<<6)

#define ADCCON_ENABLE_START (0x1) #define STDBM (0x0<<2) #define PRSCEN (0x1<<14)

- 9 -

北京航空航天大学研究生实验报告

#define rADCCON (*(volatile unsigned *)0x58000000) #define rADCDAT0 (*(volatile unsigned *)0x5800000C) #define rUTRSTAT0 (*(volatile unsigned *)0x50000010) //#define rUTRSTAT0 (*(volatile unsigned *)0x50000024) #define RdURXH0() (*(volatile unsigned char *)0x50000024)

extern U32 LCDBufferII2[480][640];

void ARMTargetInit(void);

void init_ADdevice() {//初始化 rADCCON=(PRSCVL|ADCCON_ENABLE_START|STDBM|PRSCEN); } /*

int GetADresult(int channel) {

rADCCON=ADCCON_ENABLE_START_BYREAD|(channel<<3)|PRSCEN|PRSCVL; hudelay(10); while(!(rADCCON&ADCCON_FLAG));//转换结束 return (0x3ff&rADCDAT0);//返回采样值 } */

int GetADresult(int channel) { rADCCON=ADCCON_ENABLE_START_BYREAD|(channel<<3)|PRSCEN|PRSCVL;

rADCCON|=0x01; //启动AD转换器 hudelay(10); while(!(rADCCON&ADCCON_FLAG));//转换结束 return (0x3ff&rADCDAT0);//返回采样值} }

int main(void)

- 10 -

北京航空航天大学研究生实验报告

{ //int i,j,ADData,lastADData,count=0; //char Revdata[10]; //////////////A, AB, B, BC, C CD, D, DA //int stepdata[]={0x10,0x30,0x20,0x60,0x40,0xc0,0x80,0x90}; int i,ADData[3],j = 0; char ADData_8[3] = {0}; ARMTargetInit(); //开发版初始化 init_MotorPort(); init_ADdevice(); LCD_Init(); for(;;) { //begin: Uart_Printf(0,\motor.\\n\ for(;;) { for(i=0;i<3;i++) { ADData[i]=GetADresult(i);

ADData_8[i]=ADData[i] >> 2;

printf(\ } //Uart_Printf(0,\ hudelay(10); SetPWM((ADData[1]-512)*MOTOR_CONT/1024); hudelay(10);

for(i=0;i

LCDBufferII2[j][i] = (U32)(ADData_8[0]<<16) + (U32)(ADData_8[1]<<8) + ADData_8[2]; } }

LCD_Refresh(); } } }八、思考题

1)液晶显示的基本原理是什么?

答:LCD显示器是通过给不同的液晶单元供电,控制其光线的通过与否,从而达到显示

- 11 -

北京航空航天大学研究生实验报告

的目的。因此,LCD的驱动控制归于对每个液晶单元通断电的控制,每个液晶单元都对应着一个电极,对其通电,便可使用光线通过(也有刚好相反的,即不通电时光线通过,通电时光线不通过)。光源的提供方式有两种:透射式和反射式。笔记本电脑的LCD显示屏即为透射式,屏后面有一个光源,因此外界环境可以不需要光源。而一般微控制器上使用的LCD为反射式,需要外界提供光源,靠反射光来工作。

2)总线方式驱动液晶模块和使用控制器进行驱动控制有什么异同?

答:(1) 总线驱动方式

一般带有驱动模块的LCD显示屏使用这种驱动方式,由于LCD已经带有驱动硬件电路,因此模块给出的是总线接口,便于与单片机的总线进行接口。驱动模块具有八位数据总线,外加一些电源接口和控制信号。而且自带显示缓存,只需要将要显示的内容送到显示缓存中就可以实现内容的显示。由于只有八条数据线,因此常常通过引脚信号来实现地址与数据线复用,以达到把相应数据送到相应显示缓存的目的。下图为一个典型的显示模块(HY-12864B)提供的总线接口。 (2) 控制器扫描方式

S3C2410X中具有内置的LCD控制器,它具有将显示缓存(在系统存储器中)中的LCD图象数据传输到外部LCD驱动电路的逻辑功能。 S3C2410X中内置的LCD控制器可支持灰度LCD和彩色LCD。在灰度LCD上,使用基于时间的抖动算法(time-based dithering algorithm)和FRC (Frame Rate Control)方法,可以支持单色、4级灰度和16级灰度模式的灰度LCD。 在彩色LCD上,可以支持256级彩色,使用STN LCD可以支持4096级彩色。对于不同尺寸的LCD,具有不同数量的垂直和水平象素、数据接口的数据宽度、接口时间及刷新率,而LCD控制器可以进行编程控制相应的寄存器值,以适应不同的LCD显示板。

3)LCD显示图形的基本思想是什么?

答:UPTECH-3000的LCD显示模块由S3C2410的LCD控制器和256色彩色LCD显示器组成。其显示方式以直接操作显示缓冲区的内容进行,LCD控制器会通过DMA从显示缓冲区中获取数据,不需要CPU干预。本系统采用的LCD分辨率为320X240,工作在256色彩色显示模式,在该模式下,显示缓冲区中的一个字节数据代表LCD上的一个点的颜色信息,因此,所需要的显示缓冲区大小为320X240X1字节。其中每个字节的彩色数据格式如下图所示:

- 12 -

北京航空航天大学研究生实验报告

实验三

基于实时操作系统μC/OS-II实验

一、 实验目的

1. 了解uCOS-II内核的主要结构。

2. 在内核移植了uCOS-II 的处理器上创建任务。

二、实验内容

1. 运行实验十,在超级终端上观察四个任务的切换。

2. 任务1~3,每个控制―红‖、―绿‖、―蓝‖一种颜色的显示,适当增加OSTimeDly()的时间,且优先级高的任务延时时间加长,以便看清三种颜色。 3. 引入一个全局变量 BOOLEAN ac_key,解决完整刷屏问题。

4. 任务4管理键盘和超级终端,当键盘有输入时在超级终端上显示相应的字符。

三、预备知识

1.掌握在EWARM集成开发环境中编写和调试程序的基本过程。 2.了解S3C2410处理器的结构。 3.了解uCOS-II系统结构。

四、实验设备及工具

硬件:ARM嵌入式开发平台、用于S3C2410的JTAG仿真器、PC机Pentium100以上。 软件:PC机操作系统Win2000或WinXP、EWARM集成开发环境、仿真器驱动程序、超级终端通讯程序。

五、实验原理及说明

所谓移植,指的是一个操作系统可以在某个微处理器或者微控制器上运行。虽然uCOS-II的大部分源代码是用C语言写成的,仍需要用C语言和汇编语言完成一些与处理器相关的代码。比如:uCOS-II在读写处理器、寄存器时只能通过汇编语言来实现。因为uCOS-II在设计的时候就已经充分考虑了可移植性,所以,uCOS-II的移植还是比较容易的。

1. 要使uCOS-II可以正常工作,移植?COS-II时须满足的条件:

a) b) c) d) e)

处理器的C编译器能产生可重入代码; 在程序中可以打开或者关闭中断;

处理器支持中断,并且能产生定时中断(通常在10—100Hz之间); 处理器能容纳一定量数据的硬件堆栈;

处理器有将栈指针和其他CPU寄存器内容保存到栈(或者内存)的指令,以及相应的出栈指令。

2. 多任务,uCOS-II支持多任务并行执行,使用OSTaskStkInt()创建新任务,

同时调用本函数来初始化该任务的栈结构。任务的状态转换如下图:

- 13 -

北京航空航天大学研究生实验报告

六、实验方法

1 以实验十为模板,将实验六 inc目录下的LCD320.H 和src目录下的LCD640.C拷到 模板下的相应目录,将LCD640.C加入工程中。 2 包含以下头文件 #include ―inc/lcd320.h‖。

3 改LCD640.C 文件中包含头文件的路径, #include \ 4 声明引用的变量 extern U32 LCDBufferII2[LCDHEIGHT][LCDWIDTH];

七、程序源代码

#include\ /* uC/OS interface */ #include \#include \#include \

#include \

#include \#include \#include #include

//#pragma import(__use_no_semihosting_swi) // ensure no functions that use semihosting

OS_EVENT *MboxSem;

extern U32 LCDBufferII2[LCDHEIGHT][LCDWIDTH];

BOOLEAN ac_key = TRUE;

int i,j = 0;

- 14 -

北京航空航天大学研究生实验报告

char err; char *c;

#define rUTRSTAT0 (*(volatile unsigned *)0x50000010)

#define RdURXH0() (*(volatile unsigned char *)0x50000024)

#define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)

#define RED (0xff << 16) #define BLUE (0xff << 8) #define GREEN (0xff)

char Uart_Getchn(char* Revdata, int Uartnum, int timeout); void Uart_SendByten(int Uartnum, U8 data);

///******************任务定义***************///

/*OS_STK SYS_Task_Stack[STACKSIZE]= {0, }; //system task刷新任务堆栈 #define SYS_Task_Prio 1 void SYS_Task(void *Id);*/

OS_STK task1_Stack[STACKSIZE]={0, }; //Main_Test_Task堆栈 void Task1(void *Id); //Main_Test_Task #define Task1_Prio 12

OS_STK task2_Stack[STACKSIZE]={0, }; //test_Test_Task堆栈 void Task2(void *Id); //test_Test_Task #define Task2_Prio 15

OS_STK task3_Stack[STACKSIZE]={0, }; //test_Test_Task堆栈 void Task3(void *Id); //test_Test_Task #define Task3_Prio 17

OS_STK task4_Stack[STACKSIZE]={0, }; //test_Test_Task堆栈 void Task4(void *Id); //test_Test_Task #define Task4_Prio 19

/**************已经定义的OS任务************* #define SYS_Task_Prio 1 #define Touch_Screen_Task_Prio 9 #define Main_Task_Prio 12

#define Key_Scan_Task_Prio 58 #define Lcd_Fresh_prio 59

- 15 -

北京航空航天大学研究生实验报告

#define Led_Flash_Prio 60

***************************************/////////

///*****************事件定义*****************///

/////////////////////////////////////////////////////

// Main function. // //////////////////////////////////////////////////// int main(void) { ARMTargetInit(); // do target (uHAL based ARM system) initialisation // OSInit(); // needed by uC/OS-II // //OSInitUart(); //initOSFile();

//#if USE_MINIGUI==0 // initOSMessage(); // initOSDC(); // LoadFont(); //#endif //loadsystemParam(); // create the tasks in uC/OS and assign increasing // // priorities to them so that Task3 at the end of // // the pipeline has the highest priority. // //LCD_printf(\ //OSTaskCreate(SYS_Task, (void *)0, (OS_STK *)&SYS_Task_Stack[STACKSIZE-1], SYS_Task_Prio); OSTaskCreate(Task1, (void *)0, (OS_STK *)&task1_Stack[STACKSIZE-1], Task1_Prio); OSTaskCreate(Task2, (void *)0, (OS_STK *)&task2_Stack[STACKSIZE-1], Task2_Prio); OSTaskCreate(Task3, (void *)0, (OS_STK *)&task3_Stack[STACKSIZE-1], Task3_Prio);

OSTaskCreate(Task4, (void *)0, (OS_STK *)&task4_Stack[STACKSIZE-1],

- 16 -

北京航空航天大学研究生实验报告

Task4_Prio); OSAddTask_Init(0);

BSPprintf(0,\ //LCD_printf(\ //LCD_printf(\ //LCD_ChangeMode(DspGraMode); OSStart(); // start the OS // // never reached // return 0; }//main

////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Task1(void *Id) { for(;;){ BSPprintf(0,\ if(ac_key == TRUE) {

ac_key = FALSE;

for(i=0;i

LCDBufferII2[j][i] = RED; } }

LCD_Refresh(); ac_key = TRUE; } OSTimeDly(1000); } }

void Task2(void *Id) { for(;;){ BSPprintf(0,\ if(ac_key == TRUE)

- 17 -

北京航空航天大学研究生实验报告

{

ac_key = FALSE;

for(i=0;i

LCDBufferII2[j][i] = GREEN; } }

LCD_Refresh(); ac_key = TRUE; } OSTimeDly(2000); } }

void Task3(void *Id) { /*char txmsg;

MboxSem = OSMboxCreate((void *)0); txmsg = 'A';*/ for(;;){ //OSMboxPost(MboxSem, (void *)&txmsg);

//BSPprintf(0,\ if(ac_key == TRUE) {

ac_key = FALSE;

for(i=0;i

LCDBufferII2[j][i] = BLUE; } }

LCD_Refresh(); ac_key = TRUE; } OSTimeDly(5000); } }

void Task4(void *Id) {

- 18 -

北京航空航天大学研究生实验报告

//char *rxmsg; // INT8U err; for(;;){

// rxmsg = (char *)OSMboxPend(MboxSem, 0, &err); //BSPprintf(0,\ err=Uart_Getchn(c,0,0); //从串口采集数据 Uart_SendByten(0, *c);

Uart_SendByten(0,0xa);//换行 Uart_SendByten(0,0xd);//回车 //OSTimeDly(1000); } }

void Uart_SendByten(int Uartnum, U8 data)//ok eric rong { //int i; if(Uartnum==0) { while(!(rUTRSTAT0 & 0x4)); //Wait until THR is empty. hudelay(10); WrUTXH0(data); } }

char Uart_Getchn(char* Revdata, int Uartnum, int timeout) { while(!(rUTRSTAT0 & 0x1)); //Receive data read *Revdata=RdURXH0(); return TRUE; }

八、思考题

1. 如何提高键盘的响应速度?

答:可以设置键盘任务具有较高的优先级,并且任务设置短延时时间。 2. 全局变量 ac_key对共享资源管理有何意义?

答:ac_key的引入有效地保证了进行多个任务时,任务的有效完成,由于进入任务后

- 19 -

北京航空航天大学研究生实验报告

将ac_key置为0,使得其他具有高优先级任务进行时,无法进入任务本身的实际执行,从而等待原任务进行结束后,将ac_key从新置1后,其他任务才能开始执行,本实验中保证了刷屏的顺利进行,使得刷屏结束后才能进行新的任务,解决了完整刷屏的问题。

- 20 -

北京航空航天大学研究生实验报告

实验四

多任务综合实验

一、实验目的

1. 学习周期任务、任务的同步和任务间通信。

二、实验内容

1.运行实验十,删除任务四、任务定义和OSTaskCreate(Task4…),任务三for循环体内仅保留以下两句BSPprintf(0,―run task3\\n‖); OSTimeDly(3000),在超级终端上观察任务运行情况。

2. 使用系统定时中断实现周期任务,任务1 、2、3进入for循环就挂起,在定时钩子函

数中定时1秒、2秒和4秒后将其恢复。

3. 创建信号量管理数组实现任务间同步,在主函数中定义一个INT16U的两维数组

a[2][3],不同的任务往数组内写不同的值,连同任务号一起打印在超级终端上。 4. 创建消息邮箱实现任务间通信,Task1记录任务执行的次数,通过消息邮箱在Task2

里显示。

5. 附加题:文件的使用。

二、 预备知识

1.掌握在EWARM集成开发环境中编写和调试程序的基本过程。 2.了解S3C2410处理器的结构。 3.了解uCOS-II系统结构。

4. 了解多任务的创建,及互斥同步控制。

四、实验设备及工具

硬件:ARM嵌入式开发平台、用于S3C2410的JTAG仿真器、PC机Pentium100以上。 软件:PC机操作系统Win2000或WinXP、EWARM集成开发环境、仿真器驱动程序、

超级终端通讯程序。

五、实验原理及说明

1)同步与互斥

为了实现资源共享,一个操作系统必须提供临界区操作的功能。

μC/OS采用关闭/打开中断的方式来处理临界区代码,从而避免竞争条件,实现任务间的互斥;μC/OS定义两个宏(macros)来开关中断,即:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL();这两个宏的定义取决于所用的微处理器,每种微处理器都有自己的OS_CPU.H文件。

ARM9S3C2410中断的打开与关闭;

#define OS_ENTER_CRITICAL() { cpu_sr = INTS_OFF(); } #define OS_EXIT_CRITICAL() { if(cpu_sr == 0) INTS_ON(); }

2)任务间同步:信号量(Semaphores)

- 21 -

北京航空航天大学研究生实验报告

a. 信号量在多任务系统中的功能

实现对共享资源的互斥访问(包括单个共享资源或多个相同的资源); 实现任务之间的行为同步;

b. 必须在OS_CFG.H中将OS_SEM_EN开关常量置为1,这样μC/OS才能支持信号量。 c. uC/OS中信号量由两部分组成:信号量的计数值(16位无符号整数)和等待该信号量的任务所组成的等待任务表;

d. uC/OS中信号量系统服务函数有:OSSemCreate()、OSSemPend(),、OSSemPost()、OSSemAccept()、OSSemQuery()。

3)任务间通信:消息邮箱(MailBox)

a.邮箱(MailBox):一个任务或ISR可以通过邮箱向另一个任务发送一个指针型的变量,该指针指向一个包含了特定―消息‖(message)的数据结构;

b.必须在OS_CFG.H中将OS_MBOX_EN开关常量置为1,这样μC/OS才能支持邮箱。 c. 邮箱的系统服务函数:OSMboxCreate()、OSMboxPend()、OSMboxPost()、OSMboxAccept()、OSMboxQuery()。

六、实验方法

1. 以实验十为模板。

2. 将任务函数内的OSTimeDly()删除,在打印语句之前悬挂任务1~3,

OSTaskSuspend(Taskn_Prio),按以下路径ucos-ii->arch->os_cpu_c.c 找到钩子函数void OSTimeTickHook (void),用计数器控制恢复任务操作,编写OSTaskResume( Taskn_Prio);

3. 信号量管理 声明信号量OS_EVENT *Fun_Semp; 在Main函数里创建信号量Fun_Semp=OSSemCreate(1);

在各个Task里执行下列操作

OSSemPend(Fun_Semp,0,&err); ………….

OSSemPost(Fun_Semp);

4 . 定义事件控制块指针OS_EVENT *Str_Box,

在main函数里创建消息邮箱,Str_Box=OSMboxCreate((void*)

在Task1里发送消息 Times+=1; s=&Times; OSMboxPost(Str_Box,s); 在Task2里请求消息邮箱ss=OSMboxPend(Str_Box,0,&err);printf(\

5. 文件的使用.文件使用的关键是加载文本文件,用记事本创建 test.txt文件,文件的内容不包含汉字。运行实验十三,此时LCD上没有任何显示。打开超级终端,按回车键,显示/sys> 用mkdir创建ucos子目录,在ucos下再创建fj子目录,用cd进入/sys/ucos/fj> ,在该目录下执行命令dl test.txt –d,按回车键,加载test.txt 。再运行文件十三,在LCD上即可观察你编写的文本文件。

七、程序源代码

#include\ /* uC/OS interface */ #include \#include \

#include \#include \#include

- 22 -

北京航空航天大学研究生实验报告

#include

//#pragma import(__use_no_semihosting_swi) // ensure no functions that use semihosting

OS_EVENT *MboxSem;

OS_EVENT *Fun_Semp; OS_EVENT *Str_Box; INT8U err;

INT16U a[2][3]; INT8U i,j;

INT8U Times,*s,*ss;

///******************任务定义***************///

/*OS_STK SYS_Task_Stack[STACKSIZE]= {0, }; //system task刷新任务堆栈 #define SYS_Task_Prio 1 void SYS_Task(void *Id);*/

OS_STK task1_Stack[STACKSIZE]={0, }; //Main_Test_Task堆栈 void Task1(void *Id); //Main_Test_Task #define Task1_Prio 12

OS_STK task2_Stack[STACKSIZE]={0, }; //test_Test_Task堆栈 void Task2(void *Id); //test_Test_Task #define Task2_Prio 15

OS_STK task3_Stack[STACKSIZE]={0, }; //test_Test_Task堆栈 void Task3(void *Id); //test_Test_Task #define Task3_Prio 17

/**************已经定义的OS任务************* #define SYS_Task_Prio 1 #define Touch_Screen_Task_Prio 9 #define Main_Task_Prio 12

#define Key_Scan_Task_Prio 58 #define Lcd_Fresh_prio 59 #define Led_Flash_Prio 60

***************************************/////////

///*****************事件定义*****************///

- 23 -

北京航空航天大学研究生实验报告

/////////////////////////////////////////////////////

// Main function. // //////////////////////////////////////////////////// int main(void) { ARMTargetInit(); // do target (uHAL based ARM system) initialisation // OSInit(); // needed by uC/OS-II // Fun_Semp=OSSemCreate(1);

Str_Box=OSMboxCreate((void *)0); //OSInitUart(); //initOSFile();

//#if USE_MINIGUI==0 // initOSMessage(); // initOSDC(); // LoadFont(); //#endif //loadsystemParam(); // create the tasks in uC/OS and assign increasing // // priorities to them so that Task3 at the end of // // the pipeline has the highest priority. // //LCD_printf(\ //OSTaskCreate(SYS_Task, (void *)0, (OS_STK *)&SYS_Task_Stack[STACKSIZE-1], SYS_Task_Prio); OSTaskCreate(Task1, (void *)0, (OS_STK *)&task1_Stack[STACKSIZE-1], Task1_Prio); OSTaskCreate(Task2, (void *)0, (OS_STK *)&task2_Stack[STACKSIZE-1], Task2_Prio); OSTaskCreate(Task3, (void *)0, (OS_STK *)&task3_Stack[STACKSIZE-1], Task3_Prio); OSAddTask_Init(0);

BSPprintf(0,\ //LCD_printf(\ //LCD_printf(\ //LCD_ChangeMode(DspGraMode); OSStart(); // start the OS //

- 24 -

北京航空航天大学研究生实验报告

Times = 0; // never reached // return 0; }//main

////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Task1(void *Id) { for(;;){

OSTaskSuspend(Task1_Prio);

OSSemPend(Fun_Semp,0,&err); BSPprintf(0,\ Times+=1; s=&Times;

OSMboxPost(Str_Box,s); for(i = 0;i < 2;i++) {

for(j = 0;j < 3;j++) {a[i][j] = 1;

BSPprintf(0,\ } BSPprintf(0,\

OSSemPost(Fun_Semp); //OSTimeDly(1000); } }

void Task2(void *Id) { for(;;){

OSTaskSuspend(Task2_Prio); OSSemPend(Fun_Semp,0,&err); ss=OSMboxPend(Str_Box,0,&err); BSPprintf(0,\

for(i = 0;i < 2;i++) {

for(j = 0;j < 3;j++) { a[i][j] = 2;

BSPprintf(0,\

- 25 -

北京航空航天大学研究生实验报告

} BSPprintf(0,\

printf(\ //OSTimeDly(3000);

OSSemPost(Fun_Semp); } }

void Task3(void *Id) { for(;;){

OSTaskSuspend(Task3_Prio); OSSemPend(Fun_Semp,0,&err); BSPprintf(0,\ for(i = 0;i < 2;i++) {

for(j = 0;j < 3;j++) {a[i][j] = 3;

BSPprintf(0,\ } BSPprintf(0,\ //OSTimeDly(3000);

OSSemPost(Fun_Semp); } }

创建消息邮箱实现任务间通信,Task1记录任务执行的次数,通过消息邮箱在Task2里显示。 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void Task1(void *Id) {

int *s;

static int Times=0; for(;;){

OSTaskSuspend(Task1_Prio); //OSSemPend(Fun_Semp,0,&err); BSPprintf(0,\Times+=1; s=&Times;

OSMboxPost(Str_Box,s);

//OSSemPost(Fun_Semp); } }

void Task2(void *Id) {

for(;;){

- 26 -

北京航空航天大学研究生实验报告

}

OSTaskSuspend(Task2_Prio); //OSSemPend(Fun_Semp,0,&err); BSPprintf(0,\

ss=OSMboxPend(Str_Box,0,&err); BSPprintf(0,\//OSSemPost(Fun_Semp);

}

Hook函数调用代码:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void OSTimeTickHook (void) {

static int i=0; switch(i) {

case 1000: OSTaskResume(12);

break;

case 2000: OSTaskResume(12);OSTaskResume(15); break;

case 3000: OSTaskResume(12); break;

case 4000: OSTaskResume(12);OSTaskResume(15);OSTaskResume(17); i=-1;

break;

} i++; }

八、思考题

1. 用钩子函数实现周期任务有何特点? 答:钩子函数是由系统每隔1ms自动调用一次,从而通过合理使用钩子函数可以保证时间的周期性任务的完成。

2. 用信号量是如何实现任务间同步的? 答:信号量的同步主要是通过OSSemCreate()、OSSemPend()和OSSemPost()三个函数来完成的。首先创建一个信号量,从空闲事件控制块链表中得到一个ECB,初始化ECB,包括设置信号量的初始值、把等待任务列表清零、设置ECB的事件类型等,然后返回一个指向该事件控制块的指针。如果信号量的计数值大于0,将它减1并返回,如果信号量的值等于0,则调用本函数的任务将被阻塞起来,等待另一个任务把它唤醒,调用OSSched()函数,调度下一个最高优先级的任务运行。最后,检查是否有任务在等待该信号量,如果没有,将信号量的计数值加1并返回;如果有,将优先级最高的任务从等待任务列表中删除,并使它进入就绪状态,调用 OSSched(),判断是否需要进行任务切换。

3. 简述消息邮箱实现任务间通信的过程。

- 27 -

北京航空航天大学研究生实验报告

答:消息邮箱实现任务间通信主要通过以下函数过程进行的:

a.OSMboxCreate():创建一个邮箱;在创建邮箱时,须分配一个ECB,并使用其中的字段OSEventPtr指针来存放消息的地址; b. OSMboxPend():等待一个邮箱中的消息;若邮箱为满,将其内容(某消息的地址)返回;若邮箱为空,当前任务将被阻塞,直到邮箱中有了消息或等待超时; c. OSMboxPost():发送一个消息到邮箱中;如果有任务在等待该消息,将其中的最高优先级任务从等待列表中删除,变为就绪状态;

d.OSMboxAccept():无等待地请求邮箱消息;若邮箱为满,返回它的当前内容;若邮箱为空,返回空指针;

4. 简述文件加载到FLASH过程。

答:文件加载到FLASH过程如下:

a. 用记事本创建test.txt文件,文件的内容不包含汉字。 b. 打开超级终端,按回车键,显示/sys>时,使用mkdir命令创建文件要存放的目录。 c. 使用cd命令进入存放文件的目录。 d. 在该目录下执行命令:dl test.txt –d。

e. 在超级终端下选择已经创建好的文件test.txt,发送到FLASH中。

- 28 -

本文来源:https://www.bwwdw.com/article/l9ew.html

Top