嵌入式计算机系统设计第五次实验报告

Keil程序仿真 & 算法及性能评估
2022.4.18~2022.4.30
实验环境:个人电脑、Keil、STC-ISP、STC-B学习板、步进电机
实验目的:
任务1:完善实验三(步进电机驱动)。
任务2:在完善实验三基础上,实现蜂鸣器可控发声和指示。
i.Beep模块按分层设计(底层驱动、向应用层提供API函数)
ii.按键模块按分层设计(底层驱动、向应用层提供事件及API函数)
iii.(选做)在Beep模块设计完成基础上,实现播放音乐的功能(参照STCBSP提供的Music模块API)
实验条件:同前
实验内容:

任务1:完善实验三(步进电机驱动)

实验3已完善,详情见实验3

任务2:在完善实验三基础上,实现蜂鸣器可控发声和指示。

(1)Beep模块按分层设计(底层驱动、向应用层提供API函数) 首先定义相关引脚:蜂鸣器的电源引脚在P3.4


编写驱动函数:
将相关引脚设置为推挽模式,并设置好定时器的模式:如下本次蜂鸣器使用的是定时器1,控制定时器的寄存器见操作手册,每个寄存器的功能如下图所示,其中TH1和TL1表示定时器1的初始值(表示T1的高8位和低8位),系统启动后,T1,每个时钟加一,直到溢出后触发定时器中断并重装初始值(这需要模式设置)
所以如图SysClock/(Hz*2)就表示T1需要经过多少次加1才能溢出,然后将这个数值乘上每个时钟周期的时间即可得到,发生一次定时器中断所需要的的时间
(这里T1设置的是12不分频模式1T速度是分频的12倍,所以如果是12T分频模式还需要乘12才是定时器中断一次的时间)
在这里插入图片描述

利用定时器中断进行蜂鸣器的发声:不断将引脚反转从而达到使蜂鸣器震动发声的效果,beep_time用于控制蜂鸣器发声的时间,当蜂鸣器不发生时需要将引脚置于低电平(减少功耗)
在这里插入图片描述

设置蜂鸣器属性:设置蜂鸣器发声的频率和时间(通过修改定时器的频率做到)
然后根据频率计算出应该进行中断的次数来控制时间(beep_time 单位10ms)
在这里插入图片描述

(2)按键模块按分层设计(底层驱动、向应用层提供事件及API函数)

对于按键的引脚而言,原理图如下,所以当key1,2,3按下后相关的引脚电平会为0,抬起时为1,我们可以根据按键电平的跳变来判断按键是抬起还是按下
在这里插入图片描述

定义引脚和驱动函数:驱动函数只需将相关引脚设置为准双向口来确保可以输出高低电平同时不会因电流过大(如推挽模式)而将引脚烧坏
在这里插入图片描述

我们定义两个状态:一个当前状态和上一时刻状态,我们可以通过这两个状态的不同来判断按键是否按下或抬起
大致原理如下:
在这里插入图片描述

这里我使用的是40ms内如果相关按键电平为0的时间超过25ms则我们认为是按键按下状态,否则为抬起状态,相关代码如下:
当判断有按键事件发生时,运行回调函数CallBack,这个函数需要用于自己提供

在这里插入图片描述

最后获取按键事件状态:在按键获取一次事件后需要将按键事件复位
在这里插入图片描述

(3)(选做)在Beep模块设计完成基础上,实现播放音乐的功能(参照STCBSP提供的Music模块API)

首先想要播放音乐我们需要通过蜂鸣器发出每一个音调的声音,相关音调的频率如下(因为是使用蜂鸣器模块作为底层,所以这里驱动函数是空的):
在这里插入图片描述

每个字母表示相关音调的7个音节的低中高音(比如C数组前7位表示,C调的低音do、re、mi、fa、so、la、si再后面7位表示中音最后7位高音)
然后我们编写播放音调的函数,变量syl取值为0x11-0x17,0x21-0x27,0x31-0x37,每个字节的高4位表示低中高音,第4位表示音节,所以我们获取相关频率可以按照如图方式进行,然后变量beats表示这个音节的节拍数(取值单位为1/16个节拍,如0x10表示1个节拍),beatsPM表示1分钟的节拍数(比如60就表示一个节拍1s,这个变量用于控制1个节拍的时间),然后我们通过这两个变量计算出蜂鸣器发声的时间(图中公式是为了减少因为除法带来的误差进行化简后的结果)
在这里插入图片描述

然后我们开始播放音乐:
通常情况下每次取两字节第一个字节表示音节,第二个字节表示节拍
如果遇到控制字符(如修改音调或改变每分钟节拍数)则进行相关的处理,没有遇到的情况如下:播放一次后songsit(用于记录播放位置)加2,播放完成后改变音乐模式为enumModeStop
在这里插入图片描述

相关控制字符如改变节拍率:改变后跳转songsit到下一个可以播放的字符位置即可,跳转时判断一下是否到歌曲结束部分,其余控制字符同理。
在这里插入图片描述

设置音乐播放的初始属性:
在这里插入图片描述

改变音乐播放状态:注意在停止时将变量复位
在这里插入图片描述

获取音乐播放状态:该函数用于后续对这几个函数进行封装后连续播放音乐
在这里插入图片描述

最后进行这几个功能的汇总测试:

用“定时器2”及其“中断”控制(无源)蜂鸣器发声,要求发声频率可以改变和显示;

注:发声频率在200~2000Hz范围内;
按键控制发声频率变化(每次变化步长 >= 100Hz);
发声频率在数码管上显示;
步进电机(4个流水灯)快慢随发声频率同步变化。
通过按键控制频率,按键1蜂鸣器将按照设定的频率发声1s,按键2增加频率同时增加电机的运行速度,按键3降低频率同时降低电机的运行速度。
显示部分通过10ms回调实时显示。
具体代码如下图所示
在这里插入图片描述

完整代码

蜂鸣器头文件

#include "STC15F2K60S2.H"
sbit beep_bit = P3 ^ 4;
unsigned int Hz = 1000;
extern code long int SysClock;
unsigned int beep_time = 0;
void _BeepInit()
{
    P3M0 = 0X10; // 保持其他模式不变,P3.4设置为推挽输出
    P3M1 = 0X00;
    beep_bit = 0;

    AUXR |= 0x40; //定时器1工作在1T、16位自动重装初值
    TMOD &= 0x0F; //计算器方式控制高4位控制T1低4位控制T0,这里只控制T1
    TL1 = 65536 - (SysClock / (Hz * 2));
    TH1 = (65536 - SysClock / (Hz * 2)) >> 8; //两者都是T1计数器
    TR1 = 1;                                  //允许T1开始计数
    ET1 = 1;
}
void beep_play(void) interrupt 3
{
    if (beep_time)
    {
        beep_time--;
        beep_bit = ~beep_bit;
    }
    else
        beep_bit = 0;
}
void _SetBeep(unsigned int hz, unsigned int time)
{
    Hz = hz;
    TL1 = 65536 - (SysClock / (Hz * 2));
    TH1 = (65536 - SysClock / (Hz * 2)) >> 8; //两者都是T1计数器
    beep_time = time * (Hz/50);
}

按键头文件

#include "STC15F2K60S2.H"
enum KeyName
{
    enumKey1,
    enumKey2,
    enumKey3
}; //按键名
enum KeyActName
{
    enumKeyNull,
    enumKeyPress,
    enumKeyRelease,
    enumKeyFail
}; //按键动作名
sbit KEY1 = P3 ^ 2;
sbit KEY2 = P3 ^ 3;
sbit KEY3 = P1 ^ 7;
bit state1 = 1, state2 = 1, state3 = 1; //按键状态1:抬起,0按下
bit Lstate1 = 1, Lstate2 = 1, Lstate3 = 1;
enum KeyActName KeyAct1 = enumKeyNull, KeyAct2 = enumKeyNull, KeyAct3 = enumKeyNull, KeyAct;
unsigned char count = 40;
unsigned char key_num1 = 0, key_num2 = 0, key_num3 = 0;
void Key_Init() //初始化函数
{
    // IT1 = 1;
    // IT0 = 1; //下降沿触发
    P3M0 &= 0xf3;
    P3M1 &= 0xf3; // p3.2,p3.3准双向口
    P1M0 &= 0x7f;
    P1M1 &= 0x7f;
    // EX0 = 1;
    // EX1 = 1; //开启INT0,INT1的中断服务
}
void KeyJudge(void (*CallBack)()) // 1ms延时,按键状态改变函数(核心)
{
    if (KEY1 == 0)
        key_num1++;
    if (KEY2 == 0)
        key_num2++;
    if (KEY3 == 0)
        key_num3++;
    if (count != 0)
        count--;
    else //改变状态
    {
        count = 40;         //复位
        if (key_num1 >= 25) // 40ms内有25ms时间处于按下状态则认为是按下
            state1 = 0; //按下状态
        else
            state1 = 1;     //抬起状态
        if (key_num2 >= 25)
            state2 = 0;     //按下状态
        else
            state2 = 1;     //抬起状态
        if (key_num3 >= 25) 
            state3 = 0;     //按下状态
        else
            state3 = 1; //抬起状态

        if ((Lstate1 == 1 && state1 == 0) || (Lstate1 == 0 && state1 == 1)) //按键1按下或抬起
        {
            if (Lstate1 == 1 && state1 == 0)
                KeyAct1 = enumKeyPress;
            else
                KeyAct1 = enumKeyRelease;
            CallBack();
        }
        if ((Lstate2 == 1 && state2 == 0) || (Lstate2 == 0 && state2 == 1)) //按键2按下或抬起
        {
            if (Lstate2 == 1 && state2 == 0)
                KeyAct2 = enumKeyPress;
            else
                KeyAct2 = enumKeyRelease;
            CallBack();
        }
        if ((Lstate3 == 1 && state3 == 0) || (Lstate3 == 0 && state3 == 1)) //按键3按下或抬起
        {
            if (Lstate3 == 1 && state3 == 0)
                KeyAct3 = enumKeyPress;
            else
                KeyAct3 = enumKeyRelease;
            CallBack();
        }
        Lstate1 = state1;
        Lstate2 = state2;
        Lstate3 = state3;
        key_num1 = 0;
        key_num2 = 0;
        key_num3 = 0;
    }
}
char _GetKeyAct(char key) //事件获取一次后就状态取消
{
    switch (key)
    {
    case enumKey1:
        KeyAct = KeyAct1;
        KeyAct1 = enumKeyNull;
        return KeyAct;
    case enumKey2:
        KeyAct = KeyAct2;
        KeyAct2 = enumKeyNull;
        return KeyAct;
    case enumKey3:
        KeyAct = KeyAct3;
        KeyAct3 = enumKeyNull;
        return KeyAct;
    default:
        return enumKeyFail;
    }
}

音乐播放器头文件

extern void _SetBeep(unsigned int hz, unsigned int time);
code unsigned int A[21] = {221, 248, 278, 294, 330, 371, 416, 441, 495, 556, 589, 661, 742, 833, 882, 990, 112, 1178, 1322, 1484, 1665};
code unsigned int _B[21] = {248, 278, 294, 330, 371, 416, 467, 495, 556, 624, 661, 742, 833, 935, 990, 1112, 1178, 1322, 1484, 1665, 1869};
code unsigned int C[21] = {131, 147, 165, 175, 196, 221, 248, 262, 294, 330, 350, 393, 441, 495, 525, 589, 661, 700, 786, 882, 990};
code unsigned int D[21] = {147, 165, 175, 196, 221, 248, 278, 294, 330, 350, 393, 441, 495, 556, 589, 661, 700, 786, 882, 990, 1112};
code unsigned int E[21] = {165, 175, 196, 221, 248, 278, 312, 330, 350, 393, 441, 495, 556, 624, 661, 700, 786, 882, 990, 1112, 1248};
code unsigned int F[21] = {175, 196, 221, 234, 262, 294, 330, 350, 393, 441, 495, 556, 624, 661, 700, 786, 882, 935, 1049, 1178, 1322};
code unsigned int G[21] = {196, 221, 234, 262, 294, 330, 371, 393, 441, 495, 556, 624, 661, 742, 786, 882, 990, 1049, 1178, 1322, 1484};
// unsigned int D[7]={294,330,350,393,441,495,556};
// unsigned int DHigh[7]={589,661,700,786,882,990,1112};
// tone: 音调。F9,FA,FB,FC,FD,FE,FF分别对应G\A\B\C\D\E\F调,
unsigned char beatsPM = 60; //每分钟节拍数,最好为60的倍数
unsigned char tone = 0xFD;
unsigned int time;
enum PlayState
{
    enumBeepOK,
    enumBeepBusy,
    enumBeepFail
};
enum PlayerMode
{
    enumModeInvalid = 0, //播放模式非法
    enumModePlay,        //播放
    enumModePause,       //暂停(可恢复续放)
    enumModeStop
}; //停止(结束)
enum PlayerMode MusicMode = enumModeStop;
unsigned char *_song;
unsigned int songsit = 0;
unsigned int begin;
unsigned int end;
unsigned int songsize;
unsigned int delay = 1;
bit repeat = 0;
enum MusicKeyword
{
    enumMscSetBeatsPM = 0xF0, //音乐编码中关键字: 设置 音乐节拍
    enumMscSetTone,           //音乐编码中关键字: 设置   音调
    enumMscRepeatBegin,       //音乐编码中关键字: 设置 重复开始
    enumMscRepeatEnd
}; //音乐编码中关键字: 设置 重复结束
void MusicPlayerInit()
{
    // BeepInit();
}
// 0x11 — 0x17 :对应低音 do、re、mi、fa、so、la、si、						    0x21 — 0x27 :对应中音 do、re、mi、fa、so、la、si
//           0x31 — 0x37 :对应高音 do、re、mi、fa、so、la、si
// 		其中“节拍数”部分:
// 0x01-0xFF:单位1/16拍。也即十六进制中,高4位表示整拍数,低4位表示分拍数(1/16)
// 	    如:发音2拍:  0x20
// 		      发音半拍: 0x08
// 			    发音1拍半:0x18
// 函数返回值:enumBeepOK:调用成功
// 				enumBeepBusy:忙(上一音未按设定发完,或因蜂鸣器正在发音)
// 				enumBeepFail:调用失败(音调参数tone不对,或音高编码scale不对)
// enumMscDrvSeg7           :  启用LED
// 																		enumMscDrvLed            :  启用Light
// 																		enumMscDrvSeg7andLed     :  启用LED和Light
// 																		enumMscSetBeatsPM        :  设置节拍率, 后面再跟 节拍率(1字节)
// 																		enumMscSetTone           :  设置音调,   后面再跟 音调(1字节):0xFA 或 0xFB 或 0xFC 或 0xFD 或 0xFE 或 0xFF 或 0xF9
// 																		enumMscRepeatBegin       :  设置音乐播放重复开始处。重复一次(暂不能多次),暂不能嵌套(嵌套无效或可能导致不可预期结果)
// 																		enumMscRepeatEnd         :  设置音乐播放重复结束处
char PlayTone(unsigned char syl, unsigned char beats)
{
    switch (tone)
    {
    case 0xFA: // A调
        time = (int)(beats * 25) / (int)(beatsPM / 15);
        _SetBeep(A[((syl >> 4) - 1) * 7 + (syl & 0x0F) - 1], time);
        return enumBeepOK;
    case 0xFB: // B调
        time = (int)(beats * 25) / (int)(beatsPM / 15);
        _SetBeep(_B[((syl >> 4) - 1) * 7 + (syl & 0x0F) - 1], time);
        return enumBeepOK;
    case 0xFC: // C调
        time = (int)(beats * 25) / (int)(beatsPM / 15);
        _SetBeep(C[((syl >> 4) - 1) * 7 + (syl & 0x0F) - 1], time);
        return enumBeepOK;
    case 0xFD: // D调
        time = (int)(beats * 25) / (int)(beatsPM / 15);
        _SetBeep(D[((syl >> 4) - 1) * 7 + (syl & 0x0F) - 1], time);
        return enumBeepOK;
    case 0xFE: // E调
        time = (int)(beats * 25) / (int)(beatsPM / 15);
        _SetBeep(E[((syl >> 4) - 1) * 7 + (syl & 0x0F) - 1], time);
        return enumBeepOK;
    case 0xFF: // F调
        time = (int)(beats * 25) / (int)(beatsPM / 15);
        _SetBeep(F[((syl >> 4) - 1) * 7 + (syl & 0x0F) - 1], time);
        return enumBeepOK;
    case 0xF9: // G调
        time = (int)(beats * 25) / (int)(beatsPM / 15);
        _SetBeep(G[((syl >> 4) - 1) * 7 + (syl & 0x0F) - 1], time);
        return enumBeepOK;
    default:
        return enumBeepFail;
    }
}
void PlayMusic() // 1ms回调
{
    if (MusicMode == enumModePlay) //处于播放状态
    {
        delay--;
        if (delay != 0)
            return;
        if (_song[songsit] == enumMscSetBeatsPM) //改变节拍率
        {
            beatsPM = _song[songsit + 1];
            if (songsit + 2 == end)
            {
                if (repeat == 0) //不用重复
                {
                    MusicMode = enumModeStop;
                    songsit = 0;
                    delay = 1;
                    return;
                }
                else //需要重复
                {
                    repeat = 0;
                    songsit = begin;
                    delay = 1;
                    return;
                }
            }
            else
                songsit += 2;
        }
        if (_song[songsit] == enumMscSetTone) //改变音调
        {
            tone = _song[songsit + 1];
            if (songsit + 2 == end)
            {
                if (repeat == 0) //不用重复
                {
                    MusicMode = enumModeStop;
                    songsit = 0;
                    delay = 1;
                    return;
                }
                else //需要重复
                {
                    repeat = 0;
                    songsit = begin;
                    delay = 1;
                    return;
                }
            }
            else
                songsit += 2;
        }
        if (_song[songsit] == enumMscRepeatEnd) //记录重复结束位置
        {
            end = songsit;
            if (songsit + 1 == songsize) //最后一个字符
            {
                if (repeat == 0) //不用重复
                {
                    MusicMode = enumModeStop;
                    songsit = 0;
                    delay = 1;
                    return;
                }
                else //需要重复
                {
                    repeat = 0;
                    songsit = begin;
                    delay = 1;
                    return;
                }
            }
            else
                songsit++;
        }
        if (_song[songsit] == enumMscRepeatBegin) //记录重复开始位置
        {
            begin = songsit + 1;
            repeat = 1;                  //进行重复
            if (songsit + 1 == songsize) //最后一个字符
            {
                if (repeat == 0) //不用重复
                {
                    MusicMode = enumModeStop;
                    songsit = 0;
                    delay = 1;
                    return;
                }
                else //需要重复
                {
                    repeat = 0;
                    songsit = begin;
                    delay = 1;
                    return;
                }
            }
            else
                songsit++;
        }
        if (_song[songsit] != 0x00)                                    //休止符
            PlayTone(_song[songsit], _song[songsit + 1]);              //播放音节
        delay = (int)(_song[songsit + 1] * 250) / (int)(beatsPM / 15); //以下一个音节的节拍数作为延时
        if (songsit + 2 == end)                                        //播放完毕
            MusicMode = enumModeStop;
        else
            songsit += 2;
    }
}
void SetMusic(unsigned char _beatsPM, unsigned char _tone, unsigned char *pt, unsigned int datasize)
{
    beatsPM = _beatsPM;
    tone = _tone;
    _song = pt;
    songsit = 0;
    end = datasize;
    songsize = datasize;
}
void SetPlayerMode(enum PlayerMode play_ctrl)
{
    MusicMode = play_ctrl;
    if (MusicMode == enumModeStop)
    {
        songsit = 0;
        delay = 1;
    }
}
unsigned char GetPlayMode()
{
    if (MusicMode == enumModeStop)
        return enumBeepOK;
    else
        return enumBeepBusy;
}

测试主程序(不含音乐测试,想测试音乐将主函数最后的注释SetPlayMode取消即可自动开始播放音乐)

//功能:双通道秒表,K3、K1独立控制两个秒表计时开始和结束,计时分辨率0.01S
#include "STC15F2K60S2.H"
//#include "beep.h"
//#include "Key.h"
#include "sys.h"
#include "motor.h"
#include "STC15F2K60S2.H"
#include "displayer.h"
#include "my_beep.h"
#include"my_key.h"
#include"my_music.h"
#include "song.c"

code unsigned long SysClock=11059200;         //必须。定义系统工作时钟频率(Hz),用户必须修改成与实际工作频率(下载时选择的)一致
unsigned int Hh=1000;
#ifdef _displayer_H_                          //显示模块选用时必须。(数码管显示译码表,用戶可修改、增加等) 
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01, 0x41, 0x48, 
	              /* 序号:   0   1    2	   3    4	    5    6	  7   8	   9	 10	   11		12   13    14     15     */
                /* 显示:   0   1    2    3    4     5    6    7   8    9  (无)   下-  中-  上-  上中-  中下-   */  
	                       0x3f|0x80,0x06|0x80,0x5b|0x80,0x4f|0x80,0x66|0x80,0x6d|0x80,0x7d|0x80,0x07|0x80,0x7f|0x80,0x6f|0x80 };  
             /* 带小数点     0         1         2         3         4         5         6         7         8         9        */
#endif
unsigned int TextHz=200;
unsigned int speed=1;
void Display_CallBack()
{
  Seg7Print(10,10,10,10,TextHz/1000,TextHz/100%10,TextHz/10%10,TextHz%10);
}
void key_callback()
{
  if(_GetKeyAct(enumKey1)==enumKeyPress)
  {
    _SetBeep(TextHz,100);
  }
  if(_GetKeyAct(enumKey2)==enumKeyPress)
  {
    if(TextHz!=2000)
    {
      TextHz+=200;
      speed++;
      SetMotor(enumStepMotor1, speed, 10000);
    }
  }
  if(_GetKeyAct(enumKey3)==enumKeyPress)
  {
    if(TextHz!=200)
    {
      TextHz-=200;
      speed--;
      SetMotor(enumStepMotor1, speed, 10000);
    }
  }
}
void CallBack_1ms()
{
  PlayMotor();
  PlayMusic();
  KeyJudge(key_callback);
}
void main()
{ 
  MySTC_Init();
  DisplayerInit();
	Key_Init();
  MusicPlayerInit();
  _BeepInit();
  MotorInit();
  SetDisplayerArea(0,7);
  Seg7Print(10,10,10,10,10,10,10,10);
  LedPrint(0x0f);
  SetMusic(60,0xFC,song,sizeof(song));
 
  SetMotor(enumStepMotor1, speed, 10000);
  //SetEventCallBack(enumEventKey,key_callback);
  SetEventCallBack(enumEventSys1mS,CallBack_1ms);
  SetEventCallBack(enumEventSys10mS,Display_CallBack);

  //SetPlayerMode(enumModePlay);
  while (1)
  {
    MySTC_OS();
  }
}
  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
嵌入式实验报告全文共6页,当前为第1页。嵌入式实验报告全文共6页,当前为第1页。西安电子科技大学 嵌入式实验报告全文共6页,当前为第1页。 嵌入式实验报告全文共6页,当前为第1页。 嵌入式系统 课程实验报告 实验名称 ARM开发基础 成 绩成 绩 ** 学院 1518021 班 成 绩 成 绩 姓名 ** 学号 同作者 无 实验日期 2018 年 6 月 14 日 指导教师评语: 指导教师: 年 月 日 实验目的 初步学会使用 μVision3 IDE for ARM 开发环境及 ARM 软件模拟器; 通过实验掌握简单 ARM 汇编指令的使用方法; 实验内容 熟悉开发环境的使用并使用 ldr/str, mov 等指令 学习使用 add/sub/lsl/lsr/and/orr 等指令,完成基本算术/逻辑运算; 设计实现表达式 y=a*8+b/2-c, 并验证之。 嵌入式实验报告全文共6页,当前为第2页。嵌入式实验报告全文共6页,当前为第2页。 嵌入式实验报告全文共6页,当前为第2页。 嵌入式实验报告全文共6页,当前为第2页。 实验原理 ARM9 处理器内核共有 37 个寄存器: 31 个通用寄存器,包括程序计数器(PC)。这些寄存器都是 32 位的; 6 个状态寄存器。这些寄存器也是 32 位的,但是只是使用了其中的 12 位。 这里简要介绍通用寄存器,关于状态寄存器的介绍。 1. ARM 通用寄存器 通用寄存器(R0-R15)可分为三类: 不分组寄存器 R0~R7; 分组寄存器 R8~R14; 程序计数器 PC。 (1)不分组寄存器 R0~R7 不分组寄存器 R0~R7 在所有处理器模式下,它们每一个都访问一样的 32 位寄存器。它们是真正的通用寄存器,没有体系结构所隐含的特殊用途。 (2)分组寄存器 R8~R14 分组寄存器 R8~R14 对应的物理寄存器取决于当前的处理器模式。若要访问特定的物理寄存器而不依赖当前的处理器模式,则要使用规定的名字。 寄存器 R8~R12 各有两组物理寄存器:一组为 FIQ 模式,另一组为除了 FIQ 以外的所有模式。寄存器 R8~R12 没有任何指定的特殊用途,只是在作快速中断处理时使用。寄存器 R13, R14 各对应 6 个分组的物理寄存器, 1 个用于用户模式和系统模式,其它 5 个分别用于 5 种异常模式。寄存器 R13 通常用做堆栈指针,称为SP;寄存器 R14 用作子程序链接寄存器,也称为 LR。 嵌入式实验报告全文共6页,当前为第3页。嵌入式实验报告全文共6页,当前为第3页。 (3)程序计数器 PC 寄存器 R15 用做程序计数器 (PC)。 在本实验中, ARM 核工作在用户模式, R0~R15 可用。 2.存储器格式 ARM 体系结构将存储器看作是从零地址开始的字节的线性组合。字节零到字 节三放置第一个字(WORD),字节四到字节七存储第二个字,以此类推。 ARM 体系结构可以用两种方法存储字数据,分别称为大端格式和小端格式。 大端格式 在这种格式中,字数据的高位字节存储在低地址中,而字数据的低位字节则存放在高地址中,如图 4-1 所示。 嵌入式实验报告全文共6页,当前为第3页。 嵌入式实验报告全文共6页,当前为第3页。 小端格式 嵌入式实验报告全文共6页,当前为第4页。嵌入式实验报告全文共6页,当前为第4页。在这种格式中,字数据的高位字节存储在高地址中,而字数据的低位字节则存放在低地址中,如图 4-2 所示。 3. Realview 基础知识 μVision3 IDE 集成了 REALVIEW 汇编器 AARM、编译器 CARM、链接器LARM,若采用 GNU 编译器则需要下载安装相应的工具包。本书所有例程代码均按照 REALVIEW 的语法和规则来书写。关于AARM、 CARM 和 LARM 的规范和具体使用,可参照 μVision3 IDE 所带的帮助文档,在此不再赘述。 嵌入式实验报告全文共6页,当前为第4页。 嵌入式实验报告全文共6页,当前为第4页。 实验步骤 拷贝整个实验例程源码目录到本地磁盘自己的工作目录下; 2) 使用 μVision IDE for ARM 通过 ULINK2 仿真器连接实验板,打开实验例程目录 ARM 体系\1.1_asm1 子目录下的 asm_1a.Uv2 例程,编译链接工程; 3)该工程配置为在模拟器中运行。可以通看工程属性查看:菜单"Project""Options for Target Asm1",在弹出的对话框中点击"Debug": 可以看到选择为"Use Simulator", 在 Debug 选项页内设置了一个初始化文件:DebugINRam.ini。此.INI 文件用于设置生成的.AXF 文件下载到目标中的位置,以及调试
第一章 系统设计 …………………………………………………………………………………4 第一节 课题目标及总体方案…………………………………………………………………..4 第二节 元器件的选择和连线…………………………………………………………………..4 第三节 程序和芯片的初始化…………………………………………………………………..5 第四节 构建功能模块…………………………………………………………………………..6 第五节 实现信息的传递…………………………………………………………………..……7 第二章 实验(测试)结果及讨论……….……………………………………………………….8 第一节 ads1.2 软件的编译,连接和运行……………………………………………………..8 第二节 protues 7.4仿真软件的联合调试……………………………………………………...9 第三章 结论………………………………………………………………………………………10 心得体会……………………………………………………………………………………………11 参考文献 …………………………………………………………………………………………12 附 录 …………………………………………………………………………………………13 源程序………………………………………………………………………………………13
实验三 UC-OS移植实验 一、实验目的 在内核移植了uCOS-II 的处理器上创建任务。 二、实验内容 1.运行实验十,在超级终端上观察四个任务的切换。 2. 任务1~3,每个控制"红"、"绿"、"蓝"一种颜色的显示,适当增加OSTimeDly()的时间,且优先级高的任务延时时间加长,以便看清三种颜色。 引入一个全局变量 BOOLEAN ac_key,解决完整刷屏问题。 4. #define rUTRSTAT0 (*(volatile unsigned *)0x50000010) #define RdURXH0() (*(volatile unsigned char *)0x50000024) 当键盘有输入时在超级终端上显示相应的字符。 三、实验设备 硬件:ARM嵌入式开发平台、用于ARM920T的JTAG仿真器、PC机Pentium100以上。 软件:PC机操作系统Win2000或WinXP、ARM ADS1.2集成开发环境、仿真器驱动程序、超级终端通讯程序。 四、实验原理 所谓移植,指的是一个操作系统可以在某个微处理器或者微控制器上运行。虽然uCOS-II的大部分源代码是用C语言写成的,仍需要用C语言和汇编语言完成一些与处理器相关的代码。比如:uCOS-II在读写处理器、寄存器时只能通过汇编语言来实现。因为uCOS-II在设计的时候就己经充分考虑了可移植性,所以,uCOS-II的移植还是比较容易的。 要使uCOS一工工可以正常工作,处理器必须满足以下要求: 1)处理器的C编译器能产生可重入代码。 2)在程序中可以打开或者关闭中断。 3)处理器支持中断,并A能产生定时中断(通常在10Hz}1000Hz之间)。 4)处理器支持能够容纳一定量数据的硬件堆栈。 北航ARM9实验报告:实验3uCOS-II实验全文共6页,当前为第1页。5) 处理器有将堆栈指针和其它CPU寄存器存储和读出到堆栈(或者内存)的指令。 北航ARM9实验报告:实验3uCOS-II实验全文共6页,当前为第1页。 uCOS-II进行任务调度的时候,会把当前任务的CPU寄存器存放到此任务的堆栈中,然后,再从另一个任务的堆栈中恢复原来的工作寄存器,继续运行另一个任务。所以,寄存器的入栈和出栈是uCOS一工工多任务调度的基础。 五、实验步骤 1 以实验十为模板,将实验六 inc目录下的LCD320.H 和src目录下的LCD640.C拷到 模板下的相应目录,将LCD640.C加入工程中。 包含以下头文件 #include "inc/lcd320.h"。 改LCD640.C 文件中包含头文件的路径 。 #include "../inc/drv/reg2410.h" 4 声明引用的变量 extern U32 LCDBufferII2[LCDHEIGHT][LCDWIDTH]; 源程序 #include"../ucos-ii/includes.h" /* uC/OS interface */ #include "../ucos-ii/add/osaddition.h" #include "../inc/drivers.h" #include "../inc/sys/lib.h" #include "../src/gui/gui.h" #include "../inc/lcd320.h" #include <string.h> #include <stdio.h> //#include "..inc/lcd320.h" //#pragma import(__use_no_semihosting_swi) // ensure no functions that use semihosting OS_EVENT *MboxSem; ///******************任务定义***************/// /*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 北航ARM9实验报告:实验3uCOS-II实验全文共6页,当前为第2页。OS_STK task2_Stack[STACKSIZE]={0, }; //test_Test_Task堆栈 北航ARM9实验报告:实验3uCOS-II实验全文共6页,当前为第2页。 void Task2(void *Id); //tes
实验三 UC-OS移植实验 一、实验目的 在内核移植了uCOS-II 的处理器上创建任务。 二、实验内容 1.运行实验十,在超级终端上观察四个任务的切换。 2. 任务1~3,每个控制"红"、"绿"、"蓝"一种颜色的显示,适当增加OSTimeDly()的时间,且优先级高的任务延时时间加长,以便看清三种颜色。 引入一个全局变量 BOOLEAN ac_key,解决完整刷屏问题。 4. #define rUTRSTAT0 (*(volatile unsigned *)0x50000010) #define RdURXH0() (*(volatile unsigned char *)0x50000024) 当键盘有输入时在超级终端上显示相应的字符。 三、实验设备 硬件:ARM嵌入式开发平台、用于ARM920T的JTAG仿真器、PC机Pentium100以上。 软件:PC机操作系统Win2000或WinXP、ARM ADS1.2集成开发环境、仿真器驱动程序、超级终端通讯程序。 四、实验原理 所谓移植,指的是一个操作系统可以在某个微处理器或者微控制器上运行。虽然uCOS-II的大部分源代码是用C语言写成的,仍需要用C语言和汇编语言完成一些与处理器相关的代码。比如:uCOS-II在读写处理器、寄存器时只能通过汇编语言来实现。因为uCOS-II在设计的时候就己经充分考虑了可移植性,所以,uCOS-II的移植还是比较容易的。 要使uCOS一工工可以正常工作,处理器必须满足以下要求: 1)处理器的C编译器能产生可重入代码。 2)在程序中可以打开或者关闭中断。 3)处理器支持中断,并A能产生定时中断(通常在10Hz}1000Hz之间)。 4)处理器支持能够容纳一定量数据的硬件堆栈。 北航实验报告实验实验全文共6页,当前为第1页。5) 处理器有将堆栈指针和其它CPU寄存器存储和读出到堆栈(或者内存)的指令。 北航实验报告实验实验全文共6页,当前为第1页。 uCOS-II进行任务调度的时候,会把当前任务的CPU寄存器存放到此任务的堆栈中,然后,再从另一个任务的堆栈中恢复原来的工作寄存器,继续运行另一个任务。所以,寄存器的入栈和出栈是uCOS一工工多任务调度的基础。 五、实验步骤 1 以实验十为模板,将实验六 inc目录下的LCD320.H 和src目录下的LCD640.C拷到 模板下的相应目录,将LCD640.C加入工程中。 包含以下头文件 #include "inc/lcd320.h"。 改LCD640.C 文件中包含头文件的路径 。 #include "../inc/drv/reg2410.h" 4 声明引用的变量 extern U32 LCDBufferII2[LCDHEIGHT][LCDWIDTH]; 源程序 #include"../ucos-ii/includes.h" /* uC/OS interface */ #include "../ucos-ii/add/osaddition.h" #include "../inc/drivers.h" #include "../inc/sys/lib.h" #include "../src/gui/gui.h" #include "../inc/lcd320.h" #include <string.h> #include <stdio.h> //#include "..inc/lcd320.h" //#pragma import(__use_no_semihosting_swi) // ensure no functions that use semihosting OS_EVENT *MboxSem; ///******************任务定义***************/// /*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 北航实验报告实验实验全文共6页,当前为第2页。OS_STK task2_Stack[STACKSIZE]={0, }; //test_Test_Task堆栈 北航实验报告实验实验全文共6页,当前为第2页。 void Task2(void *Id); //test_Test_Task #define Task2_Prio 15 OS_STK task3_Stack
嵌入式系统设计技术》 Embed System Design Technology 课程基本信息 1.课程名称: 中文名:嵌入式系统设计技术 英文名:Embed System Design Technology 2.课程代号: 20229930 3.课程类别: 基础课(选修) 4.学时:51 学分: 3 教学目的及要求 嵌入式系统,一般指非PC系统,有计算机功能但又不称之为计算机的设备或器材.它是以应用为中心,软硬件可裁减的,适应应用系统对功能,可靠性,成本,体积,功耗等综合性严格要求的专用计算机系统.简单地说,嵌入式系统集系统的应用软件与硬件于一体,类似于PC中BIOS的工作方式,具有软件代码小,高度自动化,响应速度快等特点,特别适合于要求实时和多任务的体系.嵌入式系统主要由嵌入式处理器,相关支撑硬件,嵌入式操作系统及应用软件系统等组成,它是可独立工作的"器件",有时又称为"固件". 嵌入式系统几乎包括了生活中和工业上的所有电器设备,如掌上PDA,移动计算设备,电视机顶盒,手机上网,数字电视,多媒体,汽车,微波炉,数字相机,家庭自动化系统,电梯,空调,安全系统,自动售货机,蜂窝式电话,消费电子设备,工业自动化仪表与医疗仪器等.因此嵌入式系统开发技术成为现代计算机应用开发工程师必须掌握的知识. 本课程主要教授基于ARM系列CPU的嵌入式系统硬件软件基本设计方法. 教学内容 1.绪论 9 2.ARM7TDMI(-S)结构 9 3.ARM7TDMI(-S)指令集及汇编 6 4.LPC2106/2105/2104硬件结构与功能 6 5.LPC2106/2105/2104外设编程 3 6.CodeWarrior使用 3 7.ARM体系中的调试方法 3 8.实时系统概念 3 9.μC/OS-II原理及ARM移植 9 教材 教材名称: 讲课教材自编 教材作者: 唐臻宇 主要参考资料 1.《ARM体系结构与编程》,杜春雷编著,清华大学出版社2003年2月第一版; 2.《ARM微控制器基础与实战》,周立功等编著,北京航空航天大学出版社2003年11月第一版; 3.《μC/OS-II源码公开的实时嵌入式操作系统》,JEAN J.Labrosse著,绍贝贝译,中国电力出版社2001年8月第一版; 4.《嵌入式实时操作系统Small RTOS51原理及应用》,陈明计,周立功等编著,北京航空航天大学出版社2004年1月第1版; 5.《USB2.0设备的设计与开发》,边海龙,贾少华编著,人民邮电出版社2004年1月第1版; 6.《CPLD/FPGA可编程逻辑器件应用与开发》,王道县主编,国防工业出版社2004年1月第1版; 7.《Visual Basic 与分布式监控系统―RS-232/485串行通信》,范逸之编著,清华大学出版社2002年1月第1版. 成绩评定 本课程为理论课,考核方式为:闭卷考试.平时成绩占30%;期末考试占70%. 物理科学与技术学院 本科课程教学大纲

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值