单片机
返回首页

KEIL C51程序中如何嵌入汇编

2017-01-19 来源:eefocus

模块内接口:
使用如下标志符:
 asm
汇编语句
 endasm
注意:如果在程序中使用了,注意在Keil编译器中需要激活Properties中的
“Generate Assembler  File” 和“Assembler  File ”两个选项
1、把'xx.c'加入工程中,右击'xx.c'选择“options for file'xx.c' 选择
“Generate Assembler  File”和“Assemble SRC File”打上黑勾有效;

2、根据选择的编译模式,把相应的库文件象加'xx.c'一 
样加入工程中并放在'xx.c'下面,如smail模式下选'keil\\lib\s.lib'
加入工程中,如果要进行把'keil\c51\lib\c51fpl.lib'也加入工程中。
即:
在 Keil 安装目录下的 \C51\LIB\ 目录的LIB 文件如下:
C51S.LIB - 没有的 Small mo
C51C.LIB - 没有的 Compact mo
C51L.LIB - 没有浮点运算的  mo
C51FPS.LIB - 带浮点运算的 Small model
C51FPC.LIB - 带浮点运算的 Compact model
C51FPL.LIB - 带浮点运算的  model

3、在'xx.c'头文件中加入优化:比如 (4,speed)

4、在'xx.c'中加入汇编代码 
#pragma ASM
;Assembler Code Here
#pragma ENDASM
5、编译生成xx.hex

例:
#include
void delay(void)
{
#pragma asm
 R5,#5
DEL:
 R6,#2
DEL1:
 R7,#255
DJNZ R7,$
DJNZ R6,DEL1
DJNZ R5,DEL
;MOV  A,P1
;  A
;MOV  P1,A
#pragma endasm   
}
void delay1(unsigned int cnt)
{
while(cnt--);
}
void main()
{
   while(1)
  {
   delay1(1000);
   P1=0x55;
   delay(); 
  }
}



有时候用到需要精确延时之类的子程序时,用C语言比较难控制,这时候就可以在C中嵌入汇编

比较常用的keil中嵌入汇编的方法如下所示:
如图一,在C文件中要嵌入汇编的地方用#pragma asm和#pragma endasm分隔开来,这样编译时KEIL就知道这中间的一段是汇编了。

 

在有加入汇编的文件中,还要设置编译该文件时的选项

 

Generate Assembler SRC File 生成汇编SRC文件
 Assemble SRC File 封装汇编文件
 (如图三的状态为选中)
  选上这两项就可以在C中嵌人汇编了,设置后在文件图示中多了三个红色的小方块。

 

为了能对汇编进行封装还要在项目中加入相应的封装库文件, 在笔者的项目中编译模式是小模式所以选用C51S.LIB。这也是最常用的。这些库文件是中KEIL安装目录下的LIB目录中。 加好后就可以顺利编译了。(注:我只在7.0以上版本使用过)

 

 

 


(1)、C51语言中调用汇编语言程序;

C51语言调用汇编语言程序要注意以下几点:

1:在文件栏选中File Group和C51程序原文件,在配置文件选项中激活“产生汇编(SRC)文件,“编译(SRC)文件”和“创建工程(目标)时包含”三个选项。

2:根据选择的编译模式,把相应的库文件(如SMALL模式,库文件为KEIL\C51\LIB\C51S.LIB)加入工程中。

3:在C51语言中必须声明需要调用的函数为外部函数。extern void DELAY(void);

4:在汇编语言程序中必须声明被调用子程序为公共子程序,在被调用的文件中还需要声明此文件是可从新定位的。

PUBLIC  DELAY,DEL

DELAYY  SEGMENT CODE

RSEG    DELAYY

实例如下:

C51语言文件:

 

  1. #include 'reg51.h'  

  2. extern void DELAY(void);  

  3. extern void DEL(void);  

  4. void main(void)  

  5. {     

  6.     P1=0x00;   

  7.     DELAY();  

  8.     DEL();  

  9.     P1=0xff;  

  10. }  

 

汇编语言文件:

PUBLIC  DELAY,DEL

DELAYY  SEGMENT CODE

RSEG    DELAYY

 

DELAY:  MOV     R2,#3H

        DJNZ    R2,$

        RET

DEL:    MOV     R3,#03H

        DJNZ    R3,$

        RET

        END

 

(2)、C51语言中调用外部的C51函数;

C51语言调用外部的C51函数的注意事项如下:

1:在主调函数中必须声明被调用的函数为外部类型的函数,其余都一样。

实例如下:

主调函数A:

 

  1. #include 'reg52.h'  

  2. extern  void delay(void);  

  3. sbit    P1_1=P1^1;  

  4. void    main(void)  

  5. {  

  6.     P1_1=0;  

  7.     delay();  

  8.     P1_1=1;  

  9. }  

 

被调用的函数B:

 

  1. delay()  

  2. {  

  3.     unsigned char i;  

  4.     i=0;  

  5. }  

 

 

(3)、C51语言中嵌入汇编程序;

在C51语言中嵌套使用汇编语言编写程序要注意以下的几个问题:

1:在文件栏选中File Group和C51程序原文件,在配置文件选项中激活“产生汇编(SRC)文件,“编译(SRC)文件”和“创建工程(目标)时包含”三个选项。

2:根据选择的编译模式,把相应的库文件(如SMALL模式,库文件为KEIL\C51\LIB\C51S.LIB)加入工程中。

3:用#pragma  asm,和#pragma endasm语句包含嵌入的汇编语言程序。

实例如下:

 

  1. #include 'reg51.h'  

  2. void delay(void);  

  3. void main(void)  

  4. {     

  5. void delay(void);  

  6.     P1=0x00;  

  7.     #pragma asm  

  8.         MOV     R3,#08H  

  9.         DJNZ    R3,$  

  10.     #pragma endasm  

  11.     P1=0xff;  

  12. }  

  13. void delay(void)  

  14. {  

  15.     #pragma asm  

  16.         MOV     R4,#08H  

  17.         DJNZ    R4,$  

  18.     #pragma endasm  

  19. }  

 

 

(4)、汇编语言中外部子程序的调用

汇编语言中外部子程序的调用

在遍写程序的时候,可以在一个文件的汇编程序中调用另一个文件的子程序。具体的方法如下。

1:在主程序文件中要声明所调用的子程序在外部。比如在主程序中调用子程序名为DELAY的子程序,其格式为:EXTRN   CODE (DELAY)

2:在被调用的文件中要声明,被调用的子程序为公共类型的。比如DELAY要声明的格式为:PUBLIC  DELAY

3:在被调用的文件中还需要声明此文件是可从新定位的。

SS      SEGMENT CODE

RSEG SS

整个事例如下,文件A:

EXTRN   CODE (DELAY) 

EXTRN   CODE (DEL)

        ORG     0000H

        AJMP    MAIN

        ORG     0030H

MAIN:   NOP 

TT:     MOV     P0,#00H

        LCALL   DELAY

        LCALL   DEL

        MOV     P0,#0FFH

        LJMP    TT

END

文件B:

PUBLIC  DELAY

PUBLIC  DEL

SS      SEGMENT CODE

RSEG SS

 

DELAY: MOV     R2,#3H

DJNZ    R2,$

RET

DEL:    MOV     R3,#03H

DJNZ   R3,$

RET

END

(5)采用__asm进行汇编的嵌入,例如:

 

  1. if (sys_ctrl.t_run_num!=sys_ctrl.nt_run_num)  

  2. {  

  3.     __asm PUSH ACC                  //断点数据保存  

  4.     __asm PUSH B  

  5.     __asm PUSH PSW  

  6.     __asm PUSH AR0  

  7.     __asm PUSH AR1  

  8.     __asm PUSH AR2  

  9.     __asm PUSH AR3  

  10.     __asm PUSH AR4  

  11.     __asm PUSH AR5  

  12.     __asm PUSH AR6  

  13.     __asm PUSH AR7  

  14.           

  15.         sys_task[sys_ctrl.t_run_num].task_sp = SP;  //保存栈顶地址  

  16.         sys_ctrl.t_run_num = sys_ctrl.nt_run_num;   //任务号切换  

  17.         sys_ctrl.nt_run_num = 0;                    //将新任务号清除便于后续操作  

  18.         SP = sys_task[sys_ctrl.t_run_num].task_sp;  //获取新任务栈顶地址  

  19.           

  20.     __asm POP AR7                   //恢复断点数据  

  21.     __asm POP AR6  

  22.     __asm POP AR5  

  23.     __asm POP AR4  

  24.     __asm POP AR3  

  25.     __asm POP AR2  

  26.     __asm POP AR1  

  27.     __asm POP AR0  

  28.     __asm POP PSW  

  29.     __asm POP B  

  30.     __asm POP ACC  

  31. }  

编译时,进入如下对话框,选中其中标出的两项:

 


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • 短波AM发射器电路设计图

  • 带有短路保护系统的5V直流稳压电源电路图

  • 如何调制IC555振荡器

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章