Presentation is loading. Please wait.

Presentation is loading. Please wait.

本 章 重 点 单片机的C程序设计基础 单片机内部资源的C编程 课时安排:6个课时.

Similar presentations


Presentation on theme: "本 章 重 点 单片机的C程序设计基础 单片机内部资源的C编程 课时安排:6个课时."— Presentation transcript:

1 本 章 重 点 单片机的C程序设计基础 单片机内部资源的C编程 课时安排:6个课时

2 C51 程序设计基础 C是一种源于UNIX操作系统的语言,它是一种结构化语言,可以产生紧凑代码。C可以进行许多机器级函数控制而不用汇编语言。与汇编相比,有如下优点: (1)对单片机的指令系统不要求了解,仅要求对8051的存储器结构有初步了解; (2)寄存器分配、不同存储器的寻址以及数据类型等细节可由编译器管理; (3)程序有规范的结构,可分为不同的函数,这种方式可使程序满足结构化的要求;

3 C语言作为一种非常方便的语言而得到广泛的支持,C语言程序本身并不依赖于机器硬件系统,基本上不作修改就可根据单片机的不同较快地移植过来。
(4)关键字及运算函数可用近似人的思维过程方式使用; (5)编程及程序调试时间显著缩短,从而提高效率; (6)提供的库包含许多标准子程序,具有较强的数据处理能力; (7)已编号的程序可容易地植入新程序中,因为它具有方便的模块化编程技术。 C语言作为一种非常方便的语言而得到广泛的支持,C语言程序本身并不依赖于机器硬件系统,基本上不作修改就可根据单片机的不同较快地移植过来。

4 用C语言编写MCS–51单片机的应用程序,虽然不像用汇编语言那样具体地组织、分配存储器资源和处理端口数据,但在C语言编程中,对数据类型与变量的定义,必须要与单片机的存储结构相关联,否则编译器不能正确地映射定位。 用C语言编写单片机应用程序与编写标准的C语言程序的不同之处就在于根据单片机存储结构及内部资源定义相应的C语言中的数据类型和变量,其它的语法规定、程序结构及程序设计方法都与标准的C语言程序设计相同。

5 一、C51的程序结构 二、C51的数据类型 与一般C语言的结构相同,以main()函数为程序人口,程序体中包含若干语句还可以包含若干函数。
常用的数据类型有: 位型 字符型 整型 长整型 浮点型 bit char int long int float 1位 1字节 字节 4字节 字节 数组型 指针型

6 三、C51数据的存储类型 data bdata idata pdata xdata code 存储类型 与存储空间的对应关系
直接寻址片内RAM区,访问速度快(128byte) 可位寻址片内RAM区,运行位和字节混合访问(16byte) 间接寻址片内RAM区,可访问片内全部RAM(256byte)

7 unsigned int pdata dim; unsigned char xdata vector[10][10];
变量的存储类型定义举例: char var; bit bdata flag; float idata x, y; unsigned int pdata dim; unsigned char xdata vector[10][10]; #define uint unsigned int #define uchar unsigned char (1)var被定义在片内RAM区,地址00H~0FFH。 (2)flag被定义在片内RAM的可位寻址区,地址20H~2FH。 (3)x,y被定义在片内RAM区,只能用间接寻址方式。 (4)dim被定义的片外RAM区,并用 (5)vector被定义在片外RAM区, 并用

8 四、C51数据的存储模式 如果在定义变量时略去存储类型标志符,编译器会自动选择默认的存储类型。默认的存储类型进一步由SMALL、COMPACT、LARGE存储模式指令限制。 例如:若声明char var;在SMALL存储模式下,var变量被定位在DATA存储区;在COMPACT存储模式下, var变量被定位在PDATA存储区;在LARGE存储模式下,var变量被定位在XDATA存储区。 存储模式:存储模式决定了变量的默认存储类型,参数传递区和无明确存储类型的说明。

9 参数及局部变量放入可直接寻址的片内RAM区 (最大128字节,默认存储类型是DATA),因此访 问十分方便。
存储模式 说明 SMALL 参数及局部变量放入可直接寻址的片内RAM区 (最大128字节,默认存储类型是DATA),因此访 问十分方便。 参数及局部变量放入分页片外RAM区(最大256 字节,默认存储类型是PDATA),通过寄存器R0和 R1间接寻址。 LARGE COMPACT 参数及局部变量放入片外RAM区(最大64K字 节,默认存储类型是XDATA), 使用数据指针DPTR 来间接寻址。 用DPTR进行访问效率较低。

10 五、C51包含的头文件 通常有:reg51.h math.h absacc.h stdio.h stdlib.h
注:这些头文件的位置是“C:\C51\INC”。

11

12

13

14

15

16 六、C51的运算符 与C语言基本相同: + - * / (加 减 乘 除)
* / (加 减 乘 除) > >= < <= (大于 大于等于 小于 小于等于) == != (测试等于 测试不等于) && || ! (逻辑与 逻辑或 逻辑非 ) >> << (位右移 位左移) & | (按位与 按位或) ^ ~ (按位异或 按位取反)

17 七、C51的基本语句 与标准C语言基本相同: if 选择语言 switch/case 多分支选择语言 while 循环语言
do-while 循环语言 for 循环语言

18 八、C51对特殊功能寄存器的定义 为了能直接访问特殊功能寄存器SFR,C51提供了一种自主形式的定义方法,这种定义方法与标准C语言不兼容,只适用于对8051系列单片机进行C编程。 这种定义的方法是引入关键字“sfr”,语法如下: sfr sfr_name ‘=’ int constant; 例如: sfr SCON = 0x98; sfr TMOD = 0x89;

19 对于要经常单独访问SFR中的位,C51使用关键字“sbit”可以访问位寻址对象。有以下几种方法:
方法一: 例如:sfr PSW = 0xD0; sbit OV = PSW^2; 方法二: 例如:sbit OV = 0xD0^2; 方法三: 例如:sbit OV = 0xD2;

20 九、C51对并行接口的定义 8051单片机没有专用I/O指令,其口地址与数据存储器地址是统一编址的,即把一个口当作数据存储器中的一个单元来看待。 对于8051片内I/O口用关键字“sfr”来定义。 例如: sfr P0 = 0x80; sfr P1 = 0x90;

21 #include <absacc.h> #define P_DATA XBYTE[0x5eff]
对于片外扩展I/O口,则根据其硬件译码地址,将其视为片外数据存储器的一个单元,使用#define语句进行定义。一旦在头文件或程序中对这些片内外I/O口进行定义后,在程序中就可以自由使用这些口了。 例如: #include <absacc.h> #define P_DATA XBYTE[0x5eff] #define P_CON XBYTE[0x5fff] XBYTE被定义为(char *)0x20000L,0x20000L为一般指针,其存储类型为2,基地址为0000H,这样XBYTE成为指向xdata零地址的指针。而XBYTE[0x5eff]则是外部数据存储器的0x5eff绝对地址。

22 十、C51程序设计举例 【例1】清零程序(将2000H—20FFH的内容清零) ★ 汇编语言程序 SE01: MOV R0, #00H
ORG 0000H SE01: MOV R0, #00H MOV DPTR, #2000H ;(0000H)送DPTR LOO1: CLR A A ;0送(DPTR) INC DPTR ;DPTR+1 INC R ;字节数加1 CJNE R0, #00H, LOO1 ;不到FF个字节再清 LOOP: SJMP LOOP

23 uchar xdata *p=0x2000; /* 指针指向2000H单元 */
#include <reg51.h> #define uchar unsigned char void main( ) { int i; uchar xdata *p=0x2000; /* 指针指向2000H单元 */ for(i=0; i<256; i++) /*清零2000H-20FFH单元*/ *p = 0; p++; }

24 【例2】查找零的个数(在2000H--200FH中查出有几个字 节是零,把个数放在2100H单元中)
★ 汇编语言程序 ORG H L00: MOV R0, #10H ;查找16个字节 MOV R1, #00H MOV DPTR, #2000H L11: MOVX A, @DPTR CJNE A, #00H, L ;取出内容与00H相等吗? INC R ;取出个数加1 L16: INC DPTR DJNZ R0, L ;未完继续 MOV DPTR, #2100H MOV A, R1 A ;相同数个数送2100H L1E: SJMP L1E

25 ★查找零的个数C-51程序 #include <reg51.h> #define uchar unsigned char
void main ( ) { uchar xdata *p=0x2000; /*指针p指向2000H单元*/ int num=0, i; for(i=0; i<16; i++) if(*p==0) num++; /* 若该单元内容为零,则n+1 */ p++; /* 指针指向下一单元 */ } p=0x2100; /* 指针p指向2100H单元 */ *p=n; /* 把个数放在2100H单元中 */

26 【例3】双字节无符号整数快速乘法 ★ 汇编程序 ORG 0000H ADD A, R4 MOV A, R3 XCH A, B
MOV B, R7 MUL AB ;R3*R7 XCH A, R7 ;R7=(R3*R7)低字节 MOV R5, B ;R5=(R3*R7)高字节 MOV B, R2 MUL AB ;R2*R7 ADD A, R5 MOV R4, A CLR A ADDC A, B MOV R5, A ;R5=(R2*R7)高字节 MOV A, R6 MOV B, R3 MUL AB ;R3*R6 ADD A, R4 XCH A, B ADDC A, R5 MOV R5, A MOV PSW.5, C ;存CY MOV A, R2 MOV B, R6 MUL AB ;R2*R6 ADD A, R5 CLR A MOV ACC.0, C MOV C, PSW.5 ;加上次加法的位 ADDC A, B MOV R6, A JMP $

27 【例3】双字节无符号整数快速乘法改进 MULA1 DATA 30H MULA2 DATA 31H MULB1 DATA 32H
RESUL0 DATA 34H RESUL1 DATA 35H RESUL2 DATA 36H RESUL3 DATA 37H ORG 0000H MAIN: MOV MULA1, #77H MOV MULA2, #19H MOV MULB1, #07H MOV MULB2, #11H MOV A, MULA1 MOV B, MULB1 MUL AB MOV RESUL0, A MOV RESUL1, B;第一次乘 MOV A, MULA2 ADD A, RESUL1 MOV RESUL1, A MOV A, B ADDC A, #00H MOV RESUL2, A;第二次乘

28 MOV RESUL2, A MOV A, B ADDC A, RESUL3 MOV RESUL3, A;第四次乘 SJMP $ END MOV A, MULA1 MOV B, MULB2 MUL AB ADD A, RESUL1 MOV RESUL1, A MOV A, B ADDC A, RESUL2 MOV RESUL2, A CLR A ADDC A, #00H MOV RESUL3, A;第三次乘 MOV A, MULA2 ADD A, RESUL2

29 ★ C-51程序 #include <reg51.h> #define uint unsigned int #define ulong unsigned long void main( ) { uint xdata *p1=0x2000; /*双字节被乘数在2000H单元*/ uint xdata *p2=0x2002; /*双字节乘数在2002H单元 */ ulong xdata *p3=0x2010; /*4字节乘积放在2010H单元*/ *p3 = (*p1) * (*p2); }

30 十一、8051内部资源的C51编程 1、中断 C51编译器支持在C源程序中直接开发中断程序,因此减轻了用汇编语言开发中断程序的繁琐过程。使用该扩展属性的函数定义语法如下: 返回值 函数名 interrupt n [using m] { …… } (其中,n对应中断源的编号,m对应工作寄存器组编号)

31 编 号 中 断 源 入 口 地 址 1 2 3 4 表1 MCS-51中断源编号 外部中断0 0003H 定时器/计数器0 000BH
编 号 中 断 源 入 口 地 址 外部中断0 0003H 1 定时器/计数器0 000BH 2 外部中断1 0013H 3 定时器/计数器1 001BH 4 串行口中断 0023H

32 using m 选项用于实现工作寄存器组的切换,m是中断服务子程序中选用的工作寄存器组号(0 ~ 3)。在许多情况下,响应中断时需保护有关现场信息,以便中断返回后,能使中断前的源程序从断点处继续正确地执行下去。这在MCS-51单片机中,能很方便地利用工作寄存器组的切换来实现。即在进入中断服务程序前的程序中使用一组工作寄存器,进入中断服务程序后,由"using m"切换到另一组寄存器,中断返回后又恢复到原寄存器组。这样互相切换的两组寄存器中的内容彼此都没有被破坏。

33 【例4】下图所示是利用优先权解码芯片,在单片机8031的一个外部中断INT1上扩展多个中断源的原理电路图。图中是以开关闭合来模拟中断请求信号。当有任一中断源产生中断请求,能给8031的INT1引脚送一个有效中断信号,由P1的低3位可得对应中断源的中断号。 图 1 扩展多个中断源

34 #include <reg51.h> #define uchar unsigned char uchar status;
bit flag=0; void service_int1( ) interrupt 2 using 2 /* INT1中断服务程序, { 使用第2组工作寄存器*/ flag = 1; /* 设置标志 */ status = p1 & 0x07; /* 存输入口状态 */ } void main( ) { IP = 0x04; /*置INT1为高优先级中断*/ IE = 0x84; /*INT1开中断,CPU开中断 */

35 while(1){ if(flag){ /* 表示有中断发生 */ switch(status){ /*选择中断源分支 */ case 0: program0( ); break; /* 处理IN0 */ case 1: program1( ); break; /* 处理IN1 */ case 2: program2( ); break; /* 处理IN2 */ case 3: program3( ); break; /* 处理IN3 */ case 4: program4( ); break; /* 处理IN4 */ case 5: program5( ); break; /* 处理IN5 */ case 6: program6( ); break; /* 处理IN6 */ case 7: program7( ); break; /* 处理IN7 */ } flag = 0; /* 处理完成清标志 */

36 2、定时器编程实例 【例5】设单片机的fosc=12MHz,要求在P1.0引脚上输出周期为2ms的方波。
分析:周期为2ms的方波,要求定时间隔为1ms,每次时间到P1.0取反。于是可计算出定时1ms需要计数1000次。 由于计数器是加1计数,为得到1000次计数,必须给定时器置初值“-1000”。 方法一:用T0的方式1编程,采用查询方式,

37 #include <reg51.h>
sbit P1_0 = P1^0; void main( ) { TMOD = 0x01; /*定时器T0方式1 */ TR0 = 1; /*启动T0*/ while(1){ TH0 = -(1000 / 256); /*装载定时初值 */ TL0 = -(1000 % 256); while(!TF0){ ; } /*查询TF0=1?*/ P1_0 = !P1_0; /*1ms时间到,P1.0反相*/ TF0 = 0; /*软件清TF0*/ }

38 方法二:用T0的方式1编程,采用中断方式。 #include <reg51.h> sbit P1_0 = P1^0; void timer0(void) interrupt 1 using 1 { P1_0 = !P1_0; TH0 = -(1000 / 256); /*重新置定时初值 */ TL0 = -(1000 % 256); }

39 void main(void) { TMOD = 0x00; P1_0 = 0; TH0 = -(1000 / 256); /*装载定时初值 */ TL0 = -(1000 % 256); EA = 1; ET0 = 1; TR0 = 1; do{ ; } while(1); }

40 【例6】采用12 MHz晶振,在P1.0脚上输出周期为2.5s ,占空比20%的脉冲信号。
分析:12 MHz晶振,定时0.5s,可以将0.5s分解为10次50ms,则50ms的计数值是50000,选择方式1。 高电平是10倍的定时时间,低电平是40倍的定时时间.

41 #include <reg51.h>
#define uchar unsigned char #define PERIOD 50 #define HIGH 10 timer0( ) interrupt 1 using 1 /* T/C0中断服务程序 */ { static uchar time=0; TH0= - (50000 / 256 ); /* 重置计数值 */ TL0= - (50000 % 256 ); time++; if(time <= HIGH) P1=1; /* 10次定时以内输出高电平 */ else /* 剩余40次定时输出低电平 */ if(time == PERIOD) time=0 ; P1=0 ; }

42 main( ) { TMOD = 0x01 ; /* 定时器0方式1 */ TH0 = / 256 ; /* 预置计数初值 */ TL0 = % 256 ; EA = 1; /* 开CPU中断 */ ET0 = 1 ; /* 开T/C0中断 */ TR0 = 1 ; /* 启动T/C0 */ do { ; }while(1) ; }

43 十二、8279编程实例 下图是8279与键盘、LED显示器的接口电路。当有键按下时,8279可用中断方式通知8031。编程实现功能为:当有键00H~0FH按下时,完成键值获取,并用LED输出显示键值。 根据接口电路中8279的片选信号和A0的解法,8279的端口地址为: 数据口地址:DFFEH 命令/状态口地址:DFFFH 设fosc=6MHz,分频次数N=10

44 . 8279 位驱动 Y0 Y1 Y2 Y4 Y5 Y3 A B C SL0 SL1 SL2 段 驱 动 8031 D0 D7 ALE
RL0 . RL7 Y0 Y1 Y2 Y4 Y5 Y3 A B C SL0 SL1 SL2 8031 74LS373 CLK A0 D0 D7 ALE P0.0 P0.7 8279 CE RD WR IRQ P2.5 INT0 OUTA3 OUTB0 74LS138

45 #include <reg51.h>
#include <absacc.h> #define DATA XBYTE[0xdffe] #define COM XBYTE[0xdfff] #define uchar unsigned char /*table[ ]对应00H~0FH 的段码表*/ uchar code table[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; uchar idata diss[8] = {0, 1, 2, 3, 4, 5, 6, 7}; /*显示缓冲区*/ sbit flag = ACC^7; uchar keyin(void); /*取键值函数*/ uchar deky(void); /*判断是否有键按下函数*/ void disp(uchar idata *d); /*显示函数*/

46 void main(void) { uchar i; COM = 0xd1; /*总清除命令*/ do{ ACC = COM; }while(flag == 1); /*等待清除结束*/ COM = 0x00; /*键盘、显示方式*/ COM = 0x2a; /*时钟分频*/ while(1){ for(i=0; i<8; i++){ disp(diss); /*显示缓冲区内容*/ diss[i] = keyin( ); /*键值输入到显示缓冲区*/ }

47 void disp(uchar idata *d) /*显示函数*/
{ uchar i; COM = 0x90; /*写显示RAM命令*/ for(i=0; i<8; i++){ COM = i + 0x80; /*写显示RAM命令*/ DATA = table[*d]; d++; } uchar deky(void) /*判断FIFO是否有键按下*/ { uchar k; k = COM; /*读8279的状态*/ return(k & 0x0f); }

48 uchar keyin(void) /*取键值函数*/
{ uchar i; while(deky( ) == 0); /*无键按下,继续等待*/ COM = 0x40; /*读FIFO命令*/ i = DATA; i = i & 0x3f; /*取键盘数据低6位,因为有48个按键*/ return(i); /*返回键值*/ }

49 Keil C与汇编混合使用 所谓混合编程,就是在一个项目中,同时使用C和汇编两种语言。 C
语言和汇编语言混合编程的方法形式多样,可以是以汇编语言为主 体,在其中内嵌部分C语言;也可以是以C语言为主体在其中加入部 分汇编语言(此方法实用价值较高,而被工程师们广泛的采用)。 在此方法中,用汇编语言编写对有关硬件的驱动和处理、复杂的算 法、实时性要求较高等底层的东西,来满足单片机对某些硬件高 效、快速、精确的处理等性能上的要求。用C语言来编写程序的主体 部分。这样就将C语言的可移植性强和可读性好与汇编语言的高效、 快速及可直接对硬件进行操作等优点相结合。两者优劣互补、相得 益彰,加快我们产品的开发周期,具有极高的现实意义和实用价 值!

50 Keil C与汇编混合使用 一. KEIL C51的命名规则 在KEIL C51中,编译器对C语言程序中的函数会
自动的进行转换,转换规则如下表: 无参数或无寄存器参数传递的函数 void func1(void)   -> func1 含通过寄存器传递的参数 void func2(int) ->_func2 可重入函数 void func3(char)reentrant  ->?_func3

51 Keil C与汇编混合使用 二. KEIL  C51函数的参数传递规则 通过寄存器传递的函数参数表

52 Keil C与汇编混合使用 二. KEIL  C51函数的参数传递规则 函数返回值使用的寄存器列表

53 Keil C与汇编混合使用 方法1是利用编译控制命令#pragma asm(用来标识所插入的汇编语句的起始位置) 和 #pragma endasm (用来标识所插入的汇编语句的结束位置) ,这两条命令必须成对出现,并可以多次出现。在Keil C51中不对插入的汇编代码做任何的处理。

54 Keil C与汇编混合使用

55 Keil C与汇编混合使用 方法二、keilC中调用汇编子函数的方法 第一步:用C语言编写函数的框架,文件名为.c。如:
PIDWork.c文件 void PID(void) //无参函数void PID(void) { //user1} void PID_k(void) { //user2} void PID_out(void) { //user3} long int PID_MUL(int a,int b) //有参函数long int PID_MUL(int a,int b) { //user4}

56 Keil C与汇编混合使用 方法二、keilC中调用汇编子函数的方法
第二步:建工程,添加PIDWork.c文件,设置编译模式,并添加相应的模式库文件。 如:编译模式为Small:variables in DATA,添加库文件C51S.LIB 第三步:选中PIDWork.c右击鼠标选中option for ,,,点击右边的“Generate Assembler SRC File”和“Assemble SRC File”出现黑色勾。然后build,生成了PIDWork.SRC文件 第四步:将PIDWork.SRC文件扩展名改为.ASM,这样就完成了函数的接口规则,在在代码段里添加相应的汇编程序完成相应的功能。

57 Keil C与汇编混合使用 方法二、keilC中调用汇编子函数的方法 NAME PIDWORK
?PR?PID?PIDWORK      SEGMENT CODE ?PR?PID_k?PIDWORK    SEGMENT CODE ?PR?PID_out?PIDWORK  SEGMENT CODE ?PR?_PID_MUL?PIDWORK SEGMENT CODE ?DT?_PID_MUL?PIDWORK SEGMENT DATA OVERLAYABLE  PUBLIC _PID_MUL  PUBLIC PID_out  PUBLIC PID_k  PUBLIC PID  RSEG  ?DT?_PID_MUL?PIDWORK ?_PID_MUL?BYTE:           a?340:   DS   2  ORG  2           b?341:   DS   2

58 Keil C与汇编混合使用 ; ; void PID(void) //无参函数void PID(void)
 RSEG  ?PR?PID?PIDWORK PID: ;添加汇编程序   RET    ; END OF PID ; ; void PID_k(void)  RSEG  ?PR?PID_k?PIDWORK PID_k: ;添加汇编程序   RET    ; END OF PID_k ;

59 Keil C与汇编混合使用 ; void PID_out(void)
 RSEG  ?PR?PID_out?PIDWORK PID_out: ;添加汇编程序   RET    ; END OF PID_out ; ; long int PID_MUL(int a,int b) //有参函数long int PID_MUL(int a,int b)  RSEG  ?PR?_PID_MUL?PIDWORK _PID_MUL:    ; SOURCE LINE # 17  MOV   a?340,R6  MOV   a?340+01H,R7  MOV   b?341,R4  MOV   b?341+01H,R5 ;添加汇编程序   RET    ; END OF _PID_MUL  END

60 Keil C与汇编混合使用举例 //main.c文件 #include < reg51.h > #define uchar unsigned char #define uint unsigned int extern uint AFUNC(uchar v_achr,bit v_bflag); void main() {      bit BFLAG;      uchar mav_chr;      uint     mvintrslt;      mav_chr=0xd4; BFLAG=1;      mvintrslt=AFUNC(mav_chr,BFLAG); }

61 Keil C与汇编混合使用举例 //CFUNC.c文件 #define uchar unsigned char #define uint unsigned int uint AFUNC(uchar v_achr,bit v_bflag) {      uchar tmp_vchr;      uint   tp_vint;      tmp_vchr=v_achr;      tp_vint=(uint)v_bflag;      return tmp_vchr+(tp_vint<<8); }

62 Keil C与汇编混合使用举例 //编译后CFUNC.SRC文件 NAME CFUNC ?PR?_AFUNC?CFUNC      SEGMENT CODE ?BI?_AFUNC?CFUNC      SEGMENT BIT OVERLAYABLE      PUBLIC     ?_AFUNC?BIT      PUBLIC     _AFUNC      RSEG   ?BI?_AFUNC?CFUNC ?_AFUNC?BIT:      v_bflag?041:    DBIT    1 ; #define uchar unsigned char ; #define uint unsigned int ; ; uint AFUNC(uchar v_achr,bit v_bflag)    

63 Keil C与汇编混合使用举例 //编译后CFUNC.SRC文件 RSEG   ?PR?_AFUNC?CFUNC _AFUNC:      USING     0              ; SOURCE LINE # 5 ;---- Variable 'v_achr?040' assigned to Register 'R7' ---- ; {              ; SOURCE LINE # 6 ;      uchar tmp_vchr; ;      uint     tp_vint; ; ;      tmp_vchr=v_achr;              ; SOURCE LINE # 10 ;---- Variable 'tmp_vchr?042' assigned to Register 'R5' ----      MOV       R5,R7 ;      tp_vint=(uint)v_bflag;              ; SOURCE LINE # 11      MOV       C,v_bflag?041      CLR       A      RLC       A

64 Keil C与汇编混合使用举例 思考:C代码与汇编的优劣!
//编译后CFUNC.SRC文件 ;---- Variable 'tp_vint?043' assigned to Register 'R6/R7' ---- ;      return tmp_vchr+(tp_vint<<8);              ; SOURCE LINE # 12      MOV       R6,A      MOV       R4,#00H      CLR       A      ADD       A,R5      MOV       R7,A      MOV       A,R4      ADDC      A,R6      MOV       R6,A ; }              ; SOURCE LINE # 13 ?C0001:      RET ; END OF _AFUNC      END 思考:C代码与汇编的优劣! Jc next Mov r6, #0 ret Next: mov r6, #1


Download ppt "本 章 重 点 单片机的C程序设计基础 单片机内部资源的C编程 课时安排:6个课时."

Similar presentations


Ads by Google