汽车单片机原理及应用第五章 程序设计.ppt
第五讲程序设计,主要内容:汇编语言程序设计C语言程序设计,汇编程序基本结构78K系列微处理器使用RA78K0(汇编包)将源程序转换为机器语言RA78K0包括7个程序:结构化汇编预处理程序、汇编程序、连接程序、目标代码转换程序、库、列表转换程序和项目管理器PMplus项目管理器PM plus执行一系列操作:编辑、编译/装配、连接和调试等基于模块的设计方法通常将一个源程序分为多个模块,每个源程序模块应该按照有关格式编写,才可以传送给汇编程序,汇编成目标代码 模块头(可以省略)模块体 模块尾,汇编语言程序设计,模块头:可以使用的控制语句如下表,汇编语言程序设计,模块体:可以使用所有其他的伪指令、控制命令及指令系统中的所有指令。模块体必须用段来描述,可以使用下列4 种段描述模块体:代码段必须用CSEG 定义数据段必须用DSEG 定义位段必须用BSEG 定义绝对段用ORG 定义,或者用AT 指令重定位使用CSEG,DSEG,或BSEG 定义的段数据段必须在代码段之前定义模块尾:使用END 伪指令描述模块的结束,汇编语句的格式,符号和助记符之间必须根据助记符的种类选用冒号、1 个或几个空格或制表符隔开助记符和操作数之间必须用1 或几个空格或制表符隔开,有些指令没有操作数注释必须用分号隔开,注释可有可无每行必须用CR定界,汇编语言程序设计,符号的类型,CODE01 CSEG;“CODE01”是一个段名VAR01 EQU 10H;“VAR01”是一个(常量的)名字LAB01:DW 0;“LAB01”是一个标号NAME SAMPLE;“SAMPLE”是一个模块名MAC1 MACRO;“MAC1”是一个宏名,汇编语言程序设计,助记符助记符:可以是指令、伪指令或宏引用,操作数操作数是指令、伪指令或宏引用操作的数据根据不同的指令、伪指令或宏引用,操作数区可以有1 个或2 个操作数,也可以没有操作数,如果有两个操作数时,用逗号隔开,操作数主要类型 常数(数据和字符串常数)、字符串、寄存器名、特殊字符($,#,!,and)、段定义伪指令的重定位属性名、符号、表达式和位操作类型的操作数,汇编语言程序设计,二进制(后缀B或Y)、八进制(后缀O或Q)、十进制(后缀D或T,或没有后缀)、十六进制(后缀H)、ASCII 码(使用一对单引号,例如a代表65H),特殊字符$:表示指令的地址(多字节指令时代表这个地址的第一个字节);是一个分支指令的相对寻址模式!:表示一个分支指令的绝对寻址模式#:表示立即数:表示间接寻址,表达式和运算符,HIGH 运算符:返回该数据的高8位数值 LOW 运算符:返回该数据的低8位数值MOV A,#HIGH 1234H MOV A,#12H,汇编语言程序设计,DATAPOS 运算符:返回一个位符号的地址部分(字节地址)SYM EQU 0FE68H.6;用EQU定义“SYM”0FE68H.6MOV A,!DATAPOS SYM MOV A,!0FE68HBITPOS 运算符:返回一个位符号的位部分(位位置)SYM EQU 0FE68H.6CLR1 HL.BITPOS SYM CLR1 HL.6,汇编语言程序设计,运算符的优先顺序,汇编语言程序设计,汇编伪指令伪指令不生成机器代码,主要作用是:便于描述汇编源程序、初始化存储区及预留存储区、为汇编程序及连接器进行特定处理时提供所需要的信息,汇编语言程序设计,段定义方法及对应的存储区,代码段定位伪指令,CALLT0:段的起始地址是偶地址,且位于0040H007FH。为代码段指定被1字节指令CALLT 调用的子程序入口地址FIXED:段的起始地址位于0800H0FFFH。为代码段指定被2 字节指令CALLF 调用的子程序的入口地址AT:指定一个段的绝对地址。地址范围为0000HFEFFHUNIT:定义段地址可以位于0080HFA7FH 的任何位置,汇编语言程序设计,UNITP:段地址可在0080HFA7FH 的任何位置,并且起始地址为偶数地址IXRAM:定义段地址位于内部扩展RAMSECUR_ID:为专用的安全ID 指定段地址为0085H008EH。这个位置只能用于存放安全ID,数据段常用定位伪指令SADDR:段地址位于saddr(0FE20H0FEFFH)区SADDRP:段地址位于saddr(0FE20H0FEFFH)区,起始地址为偶数地址。使用SADDR和SADDRP定义变量时,变量的定位范围不可以超出这个固定的区域,否则将产生溢出错误AT:指定一个绝对地址UNIT:缺省设置。指定段地址可以位于RAM的任何位置UNITP:段地址可以位于RAM的任何位置,始地址为偶数地址IHRAM:段地址位于高速RAM,汇编语言程序设计,LRAM:段地址位于低速RAMDSPRAM:段地址位于显示RAMIXRAM:段地址位于内部扩展RAM,位单元段常用定位伪指令AT:用一个绝对地址的第0 位指定一个位单元段的起始地址。地址范围0FE20H0FEFFHUNIT:缺省设置。段地址位于0FE20H0FEFFH 的任何位置,ORG 伪指令:把表达式确定的值赋给程序计数器,遇到一个段定义伪指令(CSEG,DSEG,BSEG,或ORG)或END 伪指令为止格式:符号 ORG 表达式;注释,汇编语言程序设计,EQU 伪指令:把表达式的值赋给前面的名字。该名字不可以在程序的其他位置再次定义。表达式中使用的符号必须是已经定义过的符号格式:名字EQU 表达式;注释,SET 伪指令:把表达式的值赋给前面的名字。该名字可以在程序的其他位置以同样方法再次定义。由该表达式确定的名字数值在再次被定义前都是有效的。表达式中使用的符号必须是已经定义过的符号格式:名字SET 绝对表达式;注释,汇编语言程序设计,存储区初始化及预留定义伪指令DB 伪指令:初始化一个字节区域格式:标号:DB(大小)初始值,.;注释DW 伪指令:初始化一个字区域格式:标号:DW(大小)初始值,.;注释DS 伪指令:预留字节存储区,预留数量由绝对表达式确定格式:标号:DS 绝对表达式;注释DBIT 伪指令:在位单元段预留一个位存储单元格式:名字 DBIT;注释,汇编语言程序设计,目标模块名字声明伪指令NAME 伪指令:为目标模块分配一个由汇编程序输出的目标模块名格式:标号:NAME 目标模块名;注释,自动分支指令选择伪指令BR 伪指令:根据分支的目的地址范围自动地选择2 字节或3 字节的分支指令,并产生相应的目标代码格式:标号:BR 表达式;注释,汇编结束伪指令END 伪指令:用于结束源程序模块的结束格式:END;注释,汇编语言程序设计,宏伪指令宏的基本功能是使用一个名字实现子程序的功能。可以避免代码重复MCRO 伪指令格式:宏名:MACRO 形参,;注释宏体ENDM;注释LOCAL 伪指令:说明定义的符号是只在宏体中有效的本地符号格式:LOCAL 符号名,;注释,汇编语言程序设计,REPT 伪指令:重复执行由REPT-ENDM定义的一串指令,重复的次数由表达式的值确定格式:标号:REPT 绝对表达式;注释ENDM;注释IRP(不定次数的重复)伪指令:重复执行由IRP-ENDM定义的一串指令,当用实参替换形参时,重复的次数由实参的值确定格式:标号:IRP 形参,;注释ENDM;注释,汇编语言程序设计,EXITM(退出宏)伪指令:用于从MACRO伪指令定义的宏体和REPT-ENDM 或IRP-ENDM定义的重复模块中强制退出格式:标号:EXITM;注释ENDM(宏结束)伪指令:用于结束宏定义的指令执行格式:ENDM;注释,汇编语言程序设计,汇编程序结构举例:十六进制-ASCII码的代码转换程序,写缓冲区的程序设计DISP_byte_write1:MOVW HL,#DISP_buffer;缓冲区首地址入HLMOV A,!M_LCD_WORK;要写入的数据低位入AMOV HL+B,A;写入INC B;偏移地址加1MOV A,!M_LCD_WORK+1;要写入的数据高位入AMOV HL+B,A;写入MOV A,BMOV!M_LCD_SET,A;保存偏移地址RET,键盘扫描中断处理程序;名称:Keyscan,功能:Key Scan 中断处理程序,内部参数:KSF:Key Scan Flag(CPU产生,表示键扫描允许),M_keybuffer:键扫内容缓冲区,P_Keyscan:键扫描Port口,P_Keyreturn:键扫描返回Port口,出口参数:F_keyscan_int:键扫完毕标志,键值处理子程序名称:Key_process功能:键盘处理程序;根据扫描缓冲区中的内容,生成对应得键值入口参数:F_Keyscan_int:KeyScan 中断程序生成扫描内容内部参数:M_keycode_new:新键值,M_keycode_old:旧键值,M_Keybuffer:键扫内容缓冲,M_keywork_old:上次有效键值,M_keypress_timer:键按下时间计时器,F_keyin:已经有键按下,F_keychat_end:键盘消抖完毕,F_key_valid:按键是否无效,F_keyoff:等待所有键全放开,F_keypress_2s:健按下时间超过2秒,F_key_same:键第一次相同标志,F_keypress_2s;按下时间2秒,,键值处理子程序出口参数:M_keycode_work:当前工作键值,F_key_process:键处理请求,F_key_repeat:Key保持标志,F_key_click:键按下并松开,时间2秒,键值消抖子程序名称:Keychat,功能:按键消抖,入口参数:M_keycode_new:新键值;M_keycode_old:旧键值,内部参数:M_keychat:键消抖计数器,出口参数:F_keychat_end:chat 完;F_key_valid:键有效,键按下时间计时处理子程序名称:Timer_key_proc,功能:键时间处理(10ms调用),入口参数:M_keypress_timer:键按下时间计时器,出口参数:F_keypress_2s:键按下2秒标志,键值译码子程序名称:Key_decode,功能:键值译码(将键盘键值1-16转换成对应遥控键码),入口参数:A=键盘键值,出口参数:A=遥控键值,C程序设计概述 与标准C兼容。但涉及标准C语言的相关内容在此不作具体介绍。这里只介绍一些NEC 78K0系列扩展C的相关内容。NEC 78K0系列微处理器可以使用CC78K0(C 编译器)进行C程序的编译。CC78K0是一个通用、可移植的C编译器,它能有效的减少开发时间和降低开发费用。除了支持标准的C语言规范以外,CC78K0还支持78K0系列产品特有的规范。这不仅增加了它的可用性,也拓宽了在C语言中的应用。,C语言程序设计,C编译器CC78K0的功能与特性ANSI-C兼容性:CC78K0与标准C语言规范兼容。支持78K0系列产品特有的扩展规范CC78K0提供了78K0系列中扩展的规范,以易于用C语言描述集成在78K0系列产品内部的外围硬件的控制和中断服务例程。扩展的规范还用来提高ROM/RAM 效率。提高ROM/RAM效率强大的优化特性可以使代码紧凑。外部变量可以在saddr区定义(sreg 变量)。函数参数和自变量也可以在saddr区或寄存器中定义(norec,noauto 函数)。代码长度可以降低,程序执行速度可因此提高使用78K0的位操作指令可以定义和操作1位数据。可以描述短指令的功能(callt,callf 功能)。,C语言程序设计,C编译器CC78K0的功能与特性进行嵌入式控制的注意事项(1)78K0系列的外围设备可以用C语言直接控制。(2)中断服务可直接用C语言描述(可切换寄存器组)。(3)特殊指令,如开/关中断和循环操作指令,可以用嵌入式函数输出。(4)C源程序中可以嵌入汇编语言。支持嵌入式应用的库函数除ANSI-C 确定的标准库函数外,CC78K0还提供适用于嵌入式应用的库函数。函数信息输出 在将已定义的函数进行编译时,CC78K0可以输出静态数据信息(如堆栈的大小和数量)。,C语言程序设计,C程序的基本结构组成C程序的基本元素有:关键字、标识符、常数、字符串文字、运算符、分隔符、标题名、预处理编号、注释等。下面就以一个简单的C程序来说明C源程序的构成元素。,C语言程序设计,C程序的基本结构#include“expand.h”ExternvoidTestb(void);Extern:关键字ExternvoidChgb(void);ExternbitData1;ExternbitData2;.Data1,Data2:标识符(变量名)Voidmain()Data1=1;.1:常数Data2=2;.0:常数While(Data1).While:关键字Data1=Data2;.:分隔符Testb();.=:运算符,C语言程序设计,C程序的基本结构If(Date1,C语言程序设计,产生高效率的目标代码使用外部变量使用位数据区函数定义(1)callt函数callt函数使函数的入口地址定位在40H7FH区(callt指令表区),可以使用callt(或 _ _ callt)声明一个callt函数。C编译器编译后,将在函数名前面加?作为前缀,并使用callt指令调用此函数。描述如下:calltextern类型名 函数名_ _ calltextern类型名 函数名(2)callf函数:callf函数使用callf指令调用函数,可以减少指令代码。使函数的入口地址定位在800HFFFH区(callf指令表区),可以使用callf(或 _ _ callf)声明一个callf函数。使用callt指令调用此函数。描述如下:calltextern类型名 函数名_ _ calltextern类型名 函数名,C语言程序设计,产生高效率的目标代码最优化选项使用扩展语言规范按照如下推荐的方法定义函数,C语言程序设计,#pragma伪指令使用扩展语言规范#pragma伪指令是ANSI支持的预处理伪指令之一。根据#pragma后跟的字符串确定编译器的编译方法。如果编译器不支持#pragma伪指令,则#pragma伪指令被忽略并继续编译。为了避免由于使用了关键字而产生编译错误,不要使用关键字进行符号定义或者使用#ifdef进行分类。CC78K0支持的#pragma伪指令如下(#pragma后面的关键字可以是大写或者小写字母):,C语言程序设计,#pragma sfr:用C描述 SFR名#pragma asm:在C中插入ASM语言描述#pragma vect、#pragma interrupt:用C描述中断服务例程#pragma di、#pragma ei:在C中描述 DI/EI 指令#pragma halt、#pragma stop、#pragma nop、#pragma brk:用C描述CPU控制指令,#pragma伪指令,C语言程序设计,#pragma access:使用绝对地址访问函数#pragma section:改变编译器输出的段名并指定段的定位地址#pragma name:改变源程序模块名#pragma rot:使用循环函数#pragma mul:使用乘法函数#pragma div:使用除法函数#pragma bcd:使用BCD码操作函数#pragma tbl:使用表跳转函数#pragma opc:使用数据插入函数#pragma rtos_interrupt:实时操作系统(RX78K0)的中断控制#pragma rtos_task:使用实时操作系统的任务函数(RX78K0)#pragma ext_table:指定flash分支表区的第一个地址#pragma ext_func:从引导区调用函数到flash区#pragma realregister:使用寄存器直接引用函数#pragma hromcall:使用内置的固件自编程直接子程序调用函数#pragma inline:内部扩展标准库函数memcpy 和memset,C语言程序设计示例,C语言程序设计,NEC开发工具:项目管理器PM PLUS、系统仿真器SM+、在线仿真器ID78K0S-NS、编程器PG-FPL2、upd78F9222设备文件及编程用的参数文件。硬件资源:以upd78F9222微处理器为核心,外扩4个LED、一个可变电阻、两个按钮及一个旋钮。LED点灯控制示例1、功能描述:通过按钮控制LED的8种显示模式。上电后首先显示第1种模式按下SW1,显示下一个模式按下SW2从第1个模式开始重新显示2、外围器件和外部端口:upd78F9222内部定时器80;外部:LED1LED4,按钮SW1,SW2。3、程序设计:,