990 likes | 1.16k Views
第 2 章 SPCE061A 单片机硬件结构. µ’nSP TM 的内核结构 单片机的片内存储结构 单片机的 I/O 接口 时钟电路 PLL 震荡器 时间基准信号. 低功耗睡眠和唤醒 CTC A/D 转换器 D/A 转换器 LVD/LVR SIO 与 UART. § 2.1 µ ’nSP TM 的内核结构. 1 、 µ ’nSP TM 内核结构. SR: 状态寄存器 NZSC : 4 个标志位 DS :数据段 CS :代码段. N :负标志, bit 15 =1 , N=1 。 Z :零标志 S :符号标志, =1 ,结果应为负。
E N D
第2章 SPCE061A单片机硬件结构 • µ’nSPTM的内核结构 • 单片机的片内存储结构 • 单片机的I/O接口 • 时钟电路 • PLL震荡器 • 时间基准信号 • 低功耗睡眠和唤醒 • CTC • A/D转换器 • D/A转换器 • LVD/LVR • SIO与UART
1、µ’nSPTM内核结构 SR:状态寄存器 NZSC:4个标志位 DS:数据段 CS:代码段 N:负标志,bit15=1,N=1。 Z:零标志 S:符号标志,=1,结果应为负。 C:进位/借位标志
2、16 位 16 位的乘法运算和内积(乘加)运算 µ’nSP™提供了高速的16 位 16 位乘法运算指令MUL, 和16 位内积运算指令MULS 。二者都可以用于有符号数相乘(signed signed) 或无符号数与有符号数相乘(unsigned signed)的运算。 MUL 指令只需花费12 个时钟周期,MULS 指令花费10n+6 个时钟周期,其中n 为乘加的项数。例如:“MR=[R2]*[R1] ,4”表示求4 项乘积的和,MULS指令只需花费46(10×4+6=46)个时钟周期。这两条指令大大的提升了µ’nSP™的数字信号处理能力。 • MR=[Rd]*[Rs] {,ss} {,n} MR=((Rd))χ((Rs))+ ((Rd+1))χ((Rs+1))+ ((Rd+2))χ((Rs+2)) + … …
3、溢出判断举例 程序状态字的使用 [例2.1]: R1=32767,R2=32767,求二者之和。运算后R1 中的内容为0xFFFE。 R1=32767 //设值后的标志位为N=0,Z=0,S=0,C=1;R1=0x7FFF R2=32767 //设值后的标志位为N=0,Z=0,S=0,C=1;R2=0x7FFF R1+=R2 //运算后的标志位为N=1,Z=0,S=0,C=0;R1=0xFFFE 作为无符号数看待,此时:‘C’为0 说明无进位产生;若作为有符号数看待,此时:N!=S 说明计算结果超出有符号数的范围,即产生溢出,另外‘S’为0 说明运算结果不为负。 例2.2]: R1=-12345,R2=-1,求二者之和。运算后R1 中的内容为0xCFC6。 R1=-12345 //设值后的标志位为N=1,Z=0,S=0,C=1,此时 R1=0xCFC7 R2=-1 //设值后的标志位为N=1,Z=0,S=0,C=1,此时 R2=0xFFFF R1+=R2 //运算后的标志位为N=1,Z=0,S=1,C=1,此时 R1=0xCFC6作为无符号数看待,此时:‘C’为1 说明有进位产生;若作为有符号数看待,此时:‘N=S’说明无溢出产生,‘S’为1 说明运算结果为负。 [例2.3]:R1=32767,R2=-12345,求二者之差。运算后R1 中的内容为0xB038。R1=32767 //设值后的标志位为N=0,Z=0,S=0,C=1, R1=0x7FFF R2=-12345 //求补后的标志位为N=1,Z=0,S=0,C=1, R2=0xC7C7 R1-=R2 //运算后的标志位为N=1,Z=0,S=0,C=0, R1=0xB038作为无符号数看待,此时:‘C’为0,说明有借位产生;若作为有符号数看待此时‘N!=S’说明有溢出产生;‘S’为0 说明运算结果为正。
标志位应用思考题 S=?N=?C=?Z=? • 两正数相加 • 两负数相加 • 异号相加
§2.2 单片机的片内存储结构 • 程序存储器与数据存储器 • 单片机的程序与数据分别寻址 • 程序存储器—ROM、EPROM、E²PROM、FLASH。 • 数据存储器—SRAM • SPCE061A的存储结构 • SRAM:2KW • FLASH:32KW
SPCE061A内存映射 0x000000 0x0007FF 0x000800 0x006FFF 0x007000 0x007FFF 0x008000 0x00FFF5 0x00FFF6 0x00FFFF 2KW SRAM 保留空间 I/O端口 32K FALSH ROM 中断向量
SPCE061A堆栈 • 按先进后出的存取原则,存取数据。 • SP作为堆栈操作的地址指针,始终指向栈顶。SP最初指向的位置称栈底。 • 堆栈是在内存SRAM中开辟的空间。 • 压栈,指针自动减1;出栈指针自动加1。 • SP的初始化值为0x07FF。 0x07FF* 堆栈生长方向 栈底 栈顶 (SP) 0x0000
SPCE061A堆栈操作 先压栈,后SP-1。 先SP+1,后出栈。 0x07FF* 堆栈生长方向 栈底 栈顶 (SP) 0x0000
闪存FLASH • Flash采用分区结构,读与SRAM相同;按分区(扇区)擦除或分区写存储器数据。 • 不能直接对Flash进行修改,只能以程序方式作相应修改。 • SPCE061A 具有32K 字(32K×16 位)闪存容量,这32K 字的内嵌闪存被划分为128 个页,每个页存储容量为256 个字;起始地址为0x8000,可用来存储程序与数据。
FLASH的操作 1、读取操作 在芯片上电后,闪存就处于读取状态,读取的操作与SRAM 相同。2、擦除操作 在对闪存写入数据前,必须对闪存进行擦除操作。由于闪存采用分页的数组结构,使得各个存储页可以被独立地擦除。当用户向闪存控制接口发出页擦除命令以后,只要向该页某个地址写入任意的数据,对应到这个地址的的记忆页就被擦除。要保证擦除操作的正确完成,必须考虑以下几个参数:1. 该闪存的内部分页结构。2. 每个页分区的擦除时间为20mS。 3、写入操作 分写入一个字与连续写入多个字。
FLASH的编程举例 [例2.4]://================================================ //程序名称:FLASH.asm//描述:擦除、写入1 个字、写入多个字子程序//================================================.INCLUDE hardware.inc.DEFINE C_FLASH_SIZE 0x8000 //定义flash 的空间为32K 字.DEFINE C_FLASH_BLOCK_SIZE 0x0100 //定义共分为256 页.DEFINE C_FLASH_MATCH 0xAAAA.DEFINE C_FLASH_PAGE_ERASE 0x5511 //擦除一页控制字.DEFINE C_FLASH_1WORD_PGM 0x5533 //写一个字的控制字.DEFINE C_FLASH_SEQUENT_PGM 0x5544 //写多个字的控制字.CODE //=================================================== //函数 名称: F_FlashWrite1Word()//描述:写一个字到FLASH 中//传入参数:1、Flash 写入地址 2、欲写入的数据//无返回值//===================================================.public _F_FlashWrite1Word.DEFINE P_Flash_Ctrl 0x7555_F_FlashWrite1Word: .procPUSH BP TO [SP] //将BP 压入堆栈内BP = SP + 1 //BP的值变为SP+1R1 = C_FLASH_MATCH //先送AAAA[P_Flash_Ctrl] = R1R1 = C_FLASH_1WORD_PGM //再送5533[P_Flash_Ctrl] = R1R1 = [BP+3] //取Flash 写入地址R2 = [BP+4] //取欲写入的字数据[R1] = R2 //把数据写入内存单元中POP BP FROM [SP] //恢复BPRETF //子程序返回.ENDP //=========================================================//函数名称: F_FlashWrite()//描述:连续写多个字//传入参数:1、Flash 写入起始地址2、欲写入数据的起始地址3、写入的数量//无返回值//=========================================================.public _F_FlashWrite_F_FlashWrite: .proc //子程序的开始PUSH BP TO [SP] //将BP 压入堆栈内BP = SP + 1 //BP的值变为SP+1R1 = [BP+3] //取Flash 写入起始地址R2 = [BP+4] //取欲写入数据的起始地址R3 = [BP+5] //写N 个字R4 = C_FLASH_MATCH //将AAAA 送到控制单元[P_Flash_Ctrl] = R4L_FlashWriteLoop:R4 = C_FLASH_SEQUENT_PGM //把5544 送到控制单元[P_Flash_Ctrl] = R4R4 = [R2++] //继续下一个数的写入[R1++] = R4R3 -= 1 //计数减一JNZ L_FlashWriteLoop //不为0 时继续进行写入操作[P_Flash_Ctrl] = R3 //写入结束POP BP FROM [SP] //恢复BPRETF //子程序返回.ENDP //=================================================== //函数名称: F_FlashErase()//描述:擦除256 字节//传入参数:1、擦除页的任一个地址//===================================================.public _F_FlashErase_F_FlashErase: .proc //擦除一页的子程序PUSH BP TO [SP] //将BP 压入堆栈内BP = SP + 1R1 = C_FLASH_MATCH //先将AAAA 送到控制单元[P_Flash_Ctrl] = R1R1 = C_FLASH_PAGE_ERASE //再将5511 送到控制单元[P_Flash_Ctrl] = R1R1 = [BP+3] //取擦除页的任一个地址[R1] = R1 //写入任意值进行擦除POP BP FROM [SP] //恢复BP RETF //子程序返回.ENDP SP 原(BP) BP=(SP)+1 (PC) (SR) FLASH地址 保存数据
§2.3单片机输入输出接口 单片机输入输出接口应注意的问题 SPCE061A输入输出接口
输入输出接口及用途 • CPU可以并行方式通过I/O口,进行数据的输入输出。 • 利用这种接口方式,可以设计并行接口与相应的I/O设备连接。如,打印机、LCD显示器、键盘、……。 • 可以对开关量按位进行测试与控制。
1、单片机I/O接口应注意的问题 • 工作状态多,控制字多。 • 根据应用确定I/O工作状态。 • 数据输出应注意的问题 • 输出接口的瞬时负载与静态负载 • 前者的负载能力>后者。 • 输出接口具有有限驱动能力。 • 输出接口的两种驱动方式。 • 输出电流与拉电流方式,一般前者为0.1~5mA,后者为25mA。 • 数据输入应注意的问题 • I/O接口作为输入时,根据I/O结构注意输出电路对输入的影响。 • 读I/O口,分,读输出数据寄存器与端口。是两个不同的数据通道。 • 输入时I/O应具有锁存功能。 • 可以上拉电阻,下拉电阻或悬空三种方式面对I/O设备。 • I/O口的功能复用与分时复用。
SPCE061A I/O接口应注意的问题 • I/O口有8个工作状态,由方向、属性、数据三个寄存器定义。 • 锁存器存储外部输入的瞬时数据。 • 由控制字确定I/O缓冲寄存器和数据寄存器与引脚连线。 • I/O口静态负载,输出驱动能力为2~3mA,拉入≤20mA。 • 复位时为下拉电阻输入。 • I/O口可按位定义,但CPU是按字操作。 • 向I/O数据寄存器(P_IOA_Data)写数据时,数据寄存器会同时连接引脚输出;而向I/O缓冲寄存器(P_IOA_Buffer)写数据到数据寄存器时,数据寄存器是与引脚断开的。
2、SPCE061A I/O接口 • 有两个16位的通用并行口,即PIOA和PIOB。 • 并行口的I/O位有8个工作状态,由三个16位的寄存器(方向、属性、数据)对应定义其I/O位的工作状态。 • PIOB0~10除可用作并行口外,还另具有特殊功能。
并行IO口的位组织结构 外部电路接口端 程序访问端
并行IO口的寄存器 与端口无关
如何通过程序管好这些I/O口,用好这些I/O口呢?如何通过程序管好这些I/O口,用好这些I/O口呢?
PIO端口特性 IOA[0] 提示:在上述这种情况下,若要通过程序判断LED是否亮着,可根据IOA[0]的状态确定,不能去读P_IOA_Data[0],只能去读P_IOA_Buffer[0],其值才为IOA[0]的真实状态。 要使LED发亮,使该端口为输出状态,且向P_IOA_Data[0]写___。这时,读P_IOA_Data[0], 其值为___。读P_IOA_Buffer[0],其值为___。
[例2.5]、 IO 口初始化—设置IO 口 设置IOA[3~0] 为带下拉电阻的输入口,IOA[7~4]为带上拉电阻的输入口,IOA[11~8]为带数据寄存器的高电平输出口,IOA[15~12] 为带数据寄存器的低电平输出口。 R1 = 0x0FF0; //设置A 端口的数据向量,IOA0~IOA3 与IOA12~IOA15 [P_IOA_Data] = R1; //置高,IOA4~IOA7 与IOA8~IOA11 置低R1 = 0xFF00; //设置A 端口的属性向量,IOA0~IOA8 置低,[P_IOA_Attrib] = R1; // IOA12~IOA15置高R1 = 0xFF00; //设置A 端口的方向向量,IOA0~IOA8 置低,[P_IOA_Dir] = R1; // IOA12~IOA15置高
设置下拉、上拉、悬浮这三种输入方式有何意义?分别适合与那种电路接口?设置下拉、上拉、悬浮这三种输入方式有何意义?分别适合与那种电路接口? 端口输入工作原理与结构 具有唤醒输入时
[例2.6] 将A 端口的任意引脚接VDD,用单步跟踪程序,通过观察寄存器表中的R2,R3 的值可观察到二者的不同。 .INCLUDE hadware.inc //包含头文件.CODE.PUBLIC _main //主程序_main: R1=0x0000 //设置A 口为带下拉电阻的输入口[P_IOA_Data]=R1 //设置A 端口的数据向量[P_IOA_Attrib]=R1 //设置A 端口的属性向量[P_IOA_Dir]=R1 //设置A 口的方向向量//************此时将A 口的任意一口接高电平**************// R3=[P_IOA_Data] //把P_IOA_Data 中的值送到寄存器R3 R2=[P_IOA_Buffer] //把P_IOA_Buffer 中的值送到寄存器R2WAIT: JMP WAIT //主程序循环 IOA[15..8] : 60~53 IOA[7..0] : 48~41
[例2.7]通过指令向I/OB输出全1,测试I/OB端口电平,比较(R3)。[例2.7]通过指令向I/OB输出全1,测试I/OB端口电平,比较(R3)。 .DEFINE P_IOB_Data 0x7005.DEFINE P_IOB_Dir 0x7007.DEFINE P_IOB_Attrib 0x7008.DEFINE P_IOB_Buffer 0x7006.CODE.PUBLIC _main //主程序_main: R1=0xFFFF //设置B 口为带反向器的低电平输出[P_IOB_Dir]=R1 //设置3 个属性向量[P_IOB_Data]=R1 R1=0x0000 [P_IOB_ Attrib]=R1 R1=0x0000 //向寄存器写入0x0000 [P_IOB_Data]=R1//****************此时检测B口的电平为高****************// R3=[P_IOB_Buffer] // 回读Buffer 的值为0x0000LOOP: JMP LOOP //主程序循环 IOB0 …. IOB15
作业: P73 6、7、8、
[例2.8]:设置A 端口低8 位为带下拉电阻的输入端口,作为按键输入;B 端口低8 位为带数据寄存器的高电平输出口,外接发光二极管显示。当Key1 按下时对应的B0 口灯亮,依此类推…… 上拉? ……LOOP1:R2=[P_IOA_Data] //是第一键按下,IOB0 口输出高电平R2&=0x0001 //确保只有IOB0 口输出高电平[P_IOB_Data]=R2JMP _MAINLOOP2:R2=[P_IOA_Data] //是第二键按下,IOB1 口输出高电平R2&=0x0002 //确保只有IOB1 口输出高电平[P_IOB_Data]=R2JMP _MAIN……LOOP7:R2=[P_IOA_Data] //是第七键按下,IOB6 口输出高电平R2&=0x0040 //确保只有IOB6 口输出高电平[P_IOB_Data]=R2JMP _MAIN //*********** 假设已经取到键值,判断键值并输出显示***********//……R1 = [keycode] //将所取的键值送到R1 中CMP R1,0x0000 //若所取的键值为0 则表明无键按下,返回主程序JE _MAINCMP R1 ,0x0001 //比较是否为第一键按下JE LOOP1 //是,跳跃到LOOP1CMP R1 ,0x0002 //比较是否为第二键按下JE LOOP2 //是,跳跃到LOOP2……CMP R1 ,0x0040 //比较是否为第七键按下JE LOOP7 //是,跳跃到LOOP7R2=[P_IOA_Data] //否则,肯定是第八个键按下,IOB7 口输出高电平R2&=0x0080[P_IOB_Data]=R2 //IOB7 口输出高电平,点亮该口的指示灯JMP _MAIN //返回主程序 //**************A 端口, B 端设置子程序**************//R1 = 0x0000 // R1 的值为0x0000[P_IOA_Dir] = R1 //设置A 口的方向向量[P_IOA_Attrib] = R1 //设置A 端口的属性向量R1 = 0x00FF[P_IOA_Data] = R1 //设置A 端口的数据向量R2 = 0X00FF // R2 的值为0x00FF[P_IOB_Dir] = R2 //设置B 口的方向向量[P_IOB_Attrib] = R2 //设置B 端口的属性向量[P_IOB_Data] = R2 //设置B 端口的数据向量
[例2.8]的电路分析: OK! 此处电平无变化!
[例2.9] IOB2 和IOB4 增加一个外部RC 电路形成反馈回路,以获得振荡源频率。 可否设置为带上拉电阻或带下拉电阻输入方式,为什么? //将IOB4 设置成悬浮式输入口,IOB2 设置成反相输出口R1=0x0004; [P_IOB_Dir]=R1; //0000000000000100 R1=0x0010; //0000000000010000 [P_IOB_Attrib]=R1;[P_IOB_Data]=R1// 写入P_FeedBack 口,设定IOB2,IOB4 为特殊功能端口R1=0x0004;[P_FeedBack]=R1;
SPCE061A I/O接口小结 • 通用并行接口及用途。 • SPCE061A并行输入输出接口的结构与特性。 • SPCE061A并行输入输出接口的工作方式与初始化。
§2.4 时钟电路 • 时钟按数据资料的参考电路连接。 • 上电后,可用示波器观察输出端口,若出现与晶体频率相同,幅度为1V左右的正弦波时,说明电路起振。 • 晶体频率只能在其允许范围内选择,要注意其精度。 C1 20pf OSC32I 32768Hz OSC32O C2 20pf
§2.5锁相环PLL震荡器 Phase Lock Loop P_SystemClock(7013H)
PLL 时钟发生器 及倍频器 fosc Fosc/n n=1,2,4,8,16,32,64 CPUCLK 32768Hz b7~5 b2~0 P_System_Clock b2~0=111时CPU时钟停止工作,系统切换至低功耗的备用状态
[例2.11] 编写1mS的延时子程序 …… R1=0x0023 //Fosc选择20MHz,CPUCLK选择Fosc/8=2.56MHz [P_System_Clock]=R1 R3=0x0000 DELAY: R2=0x0000 LOOP1: //(3+3+5)21 1/2560000=0.000090234375S R2+=1 //3,内循环100µS CMP R2,21 //3 JB LOOP1 //无符号数,<转移。5/3 R3+=1 CMP R3,10 JB DELAY RETF
欲选择CLKB的32Hz为CTC的时钟源,在初始化CTC之前,先初始化P_TimeBase_Stup,即:欲选择CLKB的32Hz为CTC的时钟源,在初始化CTC之前,先初始化P_TimeBase_Stup,即: …… R1=0x0002 [P_TimeBase_Stup]=R1 …… 一、时基信号组成结构 在系统中用作CTC的计数器时钟和定时中断信号IRQ4、5、6。 3、2 1、0 由P_INT_Ctrl单元的b2~6控制。
二、时基信号控制寄存器 • 时基设置寄存器 • P_TimeBase_Setup($700EH) • 控制字结构,见P45表2.11、2.12 • 时基清除端口 • P_TimeBase_Clear($700FH) • 写任意数使时基计数器清零,用于对时基发生器的时间校准。
§2.7低功耗睡眠和唤醒 • 低功耗技术 • 工艺改进,如,普遍采用HCMOS • 工作电压降低,如,低至2.5V、1.8V。 • CPU间断工作。 • 睡眠状态的低功耗 • 降低CPU的工作频率,即强振与弱振。 • 由三级管的VA特性可知,高频特性越好,三级管可以最快的速度越过放大区进入饱和或截止状态,使功耗降低。 • 片内功能模块分别供电
SPCE的OSC提供有两种工作模式,一种为:normal mode 另一为:auto-power saving mode.两者即为强振、弱振之说,其实两者之间的最大区别就是给OSC提供的电流大小,在normal mode时,电流会比auto-power save mode大10uA左右,当然后者是在System clock 稳定之后了。而auto-power saving mode 正如其意,自动节能模式,即率弱振模式为系统默认的设置,在上电、复位、唤醒后,系统的时钟都工作在此状态下,一会auto-power saving mode会在前7.5秒工作在强振模式下,以提供足够的电流给晶振起振,待稳定后(7.5秒),auto-power saving mode会只给晶振提供很小的电流,以供维持振荡用;而normal mode则不同,会提供给晶振足够的电流。也就是说,两种模式的主要不同点在于供给晶振的电流大小,则最直接的表现为当系统内部用到系统时钟提供的时基资源太多时,同时系统的运算又很重时,弱振肯定没有强振稳定了:) SPCE的OSC提供有两种工作模式,一种为:normal mode 另一为:auto-power saving mode.两者即为强振、弱振之说,其实两者之间的最大区别就是给OSC提供的电流大小,在normal mode时,电流会比auto-power save mode大10uA左右,当然后者是在System clock 稳定之后了。而auto-power saving mode 正如其意,自动节能模式,即率弱振模式为系统默认的设置,在上电、复位、唤醒后,系统的时钟都工作在此状态下,一会auto-power saving mode会在前7.5秒工作在强振模式下,以提供足够的电流给晶振起振,待稳定后(7.5秒),auto-power saving mode会只给晶振提供很小的电流,以供维持振荡用;而normal mode则不同,会提供给晶振足够的电流。也就是说,两种模式的主要不同点在于供给晶振的电流大小,则最直接的表现为当系统内部用到系统时钟提供的时基资源太多时,同时系统的运算又很重时,弱振肯定没有强振稳定了:) 关于强振与弱振 SPCE的OSC提供有两种工作模式,一种为:normal mode 另一为:auto-power saving mode.两者即为强振、弱振之说,其实两者之间的最大区别就是给OSC提供的电流大小,在normal mode时,电流会比auto-power save mode大10uA左右,当然后者是在System clock 稳定之后了。而auto-power saving mode 正如其意,自动节能模式,即率弱振模式为系统默认的设置,在上电、复位、唤醒后,系统的时钟都工作在此状态下,一会auto-power saving mode会在前7.5秒工作在强振模式下,以提供足够的电流给晶振起振,待稳定后(7.5秒),auto-power saving mode会只给晶振提供很小的电流,以供维持振荡用;而normal mode则不同,会提供给晶振足够的电流。也就是说,两种模式的主要不同点在于供给晶振的电流大小,则最直接的表现为当系统内部用到系统时钟提供的时基资源太多时,同时系统的运算又很重时,弱振肯定没有强振稳定了:)
低功耗系统中要注意的问题 • 了解CPU的几种工作状态如何转换,是通过硬件还是软件。 • 从低功耗到高功耗转换的不稳定期。 • 同一程序在强振与弱振工作状态下执行时间的差异。 • 进入低功耗工作状态时,对I/O驱动的差异。 • CPU 复位(包括各种复位)时,各种工作状态是如何转换的。 • 对睡眠状态前的系统时钟与CPU时钟的恢复问题。
SPCE061A睡眠与唤醒的状态转换 • 用软件方法转换工作状态到睡眠状态。 • 强振3.3V,30~50mA。 • 弱振3.3V,2mA。 • 睡眠3.3V,2µA。 低电压 复位 软件方法 强振 延时32个时钟 软件方法 睡眠前状态 睡眠 中断唤醒 延时0.7s 弱振 软件方法
SPCE061A的睡眠与唤醒 • 睡眠: • CPU在软件控制下进入睡眠。 • 系统睡眠时,时钟关闭,CPU停止工作。 • 系统资源维持现状,以便醒来继续工作。 • 唤醒: • CPU在硬件中断控制下唤醒。 • 系统唤醒时,时钟打开,CPU首先进入中断服务,再继续睡眠前的工作。 • SPCE061A的唤醒源有—IRQ3_KEY、FIQ、IRQ1~6、UART_IRQ。
[例2.12]编程实现系统从工作状态进入睡眠状态,触键唤醒CPU。[例2.12]编程实现系统从工作状态进入睡眠状态,触键唤醒CPU。 • 程序使CPU进入睡眠的方法: • 准备好唤醒源,如: • 初始化端口,如IOA[7-0]为输入。 • 中断设置,打开唤醒源中断(如键唤醒中断)。 • 读P_IOA_Latch单元,激活键唤醒功能。 • 将P_SystemClock的第2~0位置为111,系统进入睡眠状态。第4位置为0,关闭时钟。 //R1=0x0000 [P_IOA_Attrib]=R1 [P_IOA_Dir]=R1 [P_IOA_Data]=R1 //中断设置 INT OFF R1=0x0080 //允许触键中断,将唤醒源的中断打开。 [P_Int_Ctrl]=R1 INT IRQ //读P_IOA_Latch单元,用于触键唤醒。锁存IOA[7-0]的值。 R1=[P_ IOA_Latch] //将P_SystemClock的第2~0位置为111,系统进入睡眠状态。第4位 //置为0,关闭时钟。 R1=0x0007 [P_SystemClock]=R1 //IRQ3中断服务子程序。 .TEXT .PUBLIC _IRQ3 _IRQ3: R1=0x0100 TEST R1, [P_Int_Ctrl] //外部中断1? JNZ L_IRQ3_Ext1 R1=0x0200 TEST R1, [P_Int_Ctrl] //外部中断2? JNZ L_IRQ3_Ext2 L_IRQ3_KeyChange_WakeUp://肯定是键唤醒中断 R1=0x0080 //清键唤醒中断 [P_Int_Clear]=R1 ……
作业: P73 16、