ASM51无参数化调用C51 函数的实现原理

发布者:bin0990最新更新时间:2018-04-06 来源: eefocus关键字:ASM51  无参数化  C51  函数 手机看文章 扫描二维码
随时随地手机看文章

    阐述了ASM51无参数化调用C51 函数的实现原理并给出实例来验证该方法的优越性和可行性。文章中表明这样一种观点:“利用汇编语言对I/O接口、中断向量及程序空间分配的巨大优势,让程序员对MCS51内的每一字节甚至是每一比特(可位寻址空间)全部进行统筹安排,设计好各个程序模块,包括I/O口地址和中断向量地址的处理;同时在具体数据处理、通信等不需要过多与硬件打交道的程序模块中,充分利用C51语言强大高效的编程能力”。上述观点并没有错,但是对I/O接口、中断向量及程序空间分配及MCS-51内的每一个字节甚至是每一比特(可位寻址空间)全部进行统筹安排,对于大多数程序员来讲恰恰是件不容易的事。地址空间、栈的起始地址和中断向量地址的分配等,经常顾此失彼,这边可行,那边又出问题。其实完全可以把上述繁重的工作交给C51去完成,由C51定义各个变量并自动分配各个变量的空间,而集中精力完成所需功能的A51程序设计。笔者在研制基于C51、插拔式DFLASH存储器的无纸记录仪中,就是利用全局及外部变量实现C51无参数化调用A51函数的,取得了很好的效果。

    1 C51无参数化调用A51函数的实现原理

    为了说明其原理,必须理解局部变量、全局变量和外部变量的意义。

    局部变量:是在函数内部定义的变量,只在定义它的函数内部有效,仅在使用它时,才为它分配内存单元。

    全局变量:又称外部变量,是在函数外部定义的变量,可以为多个函数共同使用,其有效作用范围是从它定义的位置开始直到整个程序文件结束。若一个全局变量不是在程序文件开始处定义的,但又希望在它的定义点之前的函数中引用该变量,这时应在引用该变量的函数中用关键字EXTERN将其说明为外部变量。此外如果一个程序模块文件中应用另一个程序模块中定义的变量时,也必须用EXTERN进行说明。全局变量在整个程序的执行过程中都要占用内存单元。

    外部变量(EXTERN):使用存储种类说明符EXTERN定义的变量称为外部变量。按照缺省规则,凡在所有函数之前,在函数外部定义的变量都是外部变量,定义时可以不写EXTERN说明符。但是,在一个函数体内说明一个在该函数体外或别的程序模块文件中定义过的外部变量时,则必须使用EXTERN说明符。一个外部变量被定义之后,它就被分配了固定的内存空间。外部变量的生存期为程序的整个执行时间。

    C语言允许将大型的程序分解为若干个独立的程序模块,各个模块可分别进行编译,然后将它们连接在一起。如果某个变量需要在所有程序模块文件中使用,只要在一个程序模块中将该变量定义成全局变量,而在其它程序模块中用EXTERN说明该变量是已被定义过的外部变量就可以了。

    在C51中定义函数时如果冠以关键字EXTERN即将其明确定义为一个外部函数。

    具体方法是:在C51用unsigned char定义的变量,则在A51中必须对应声明该变量在DATA区;在C51用bit定义位变量,则在A51中必须对应声明该变量在可位选区。A51中用关键字EXTRN表示外部变量,对应关系如下:

    C51 定义 A51声明

    unsigned char varible_name<->EXTRN DATA(varible_name)

    bit bit_name <->EXTRN BIT (bit_name)

    此外,C51编译器支持在C语言源程序中直接编写8051单片机的中断服务程序,从而减轻采用汇编语言编写中断服务程序的繁锁程度。C51编译器对函数的定义进行了扩展,增加了一个扩展关键字interrupt。定义中断服务函数的一般格式为:

    函数类型 函数名(形式参数表) [interrupt n]

    [using n]

    关键了interrupt后面的n是中断号,取值为0~31,编译器从8n+3处产生中断向量。Using后的n取值为0~3,表示选择那一组寄存器。

    2 C51无参数化调用A51函数的实例

    研制的无纸记录仪实现的功能是:记录仪有4个通道,每秒采样1次,每个通道每次采样需记录两个字节,根据各个通道的转储速率(从1~255可设定),把采样的数据写入外部数据存储器62256,一旦满512字节,就把512字节一次性写入FLASH MEMORY中。

    主程序用C51编程,每秒中断采样程序由A51实现。主程序的主要工作是:把采集到的数据按曲线、棒图和数据送到液晶显示器显示;根据一公平的条件查询数据等。中断程序就是采样4个通道,把在A51采样所写入的单元及所需要的一些位变量在C51定义为全局变量,在A51中这些变量声明为外部变量,在C51调用A51的中断函数必须声明为外部函数。这样就实现了C51无参数化调用A51。

    C51主程序如下:

    程序名为MYMAIN.C

    #include

    #include

    #include

    #define uchar unsigned char

    //以下3个函数在采样程序模块ZTDJLY.A51中,名称就是标号

    extern void sample(); //中断采样程序

    extern void initial(); //AD7715初始化

    extern void res_ram(); //外部存储器62256地址指针复位

    //以下变量为采样程序模块ZTDJLY.A51中所用到的变量

    bit write_alw,vz_bit,fs_bit;//write_alw=1,写放FLASH允许,vz_bit,fs_bit是零标定及满刻度标定的标志

    uchar sample_w[12];//4路连零点采样值,每路2个字节共10个字节,另外2个字节作定改62256前把采样值添加通道号处理所需单元

    uchar xdata *ram_point;//62256的指针

    uchar sa_p,sa_vzt[8];//sa_p为采样当前路,sa_vzt[8]为4路的零点

    uchar sa_timer[8]={1,1,1,1,1,1,1,1}; //4路的转储速率,前为子,后为母本

    ……


    void disp_int0() interrupt 0 using 2 //用中断0,使用寄存器2组

    {

    sample();//C51无参数化调用A51函数

    }

    main()

    {



    …

    initial();

    while(1) //主循环

    {

    ……

    }

    }

    A51程序如下:

    NAME ztdjly.a51

    ram_cs bit 090h.2 ;p1.2 ;62256片选

    b373 bit 090h.1 ;p1.1

    bit_dog bit 0b0h.4 ;3.4

    ;以上3个是AD7715的引脚定义

    data_bit bit 0a0h.6 ;P2.6

    adsclk_bit bit 0b0h.5 ;P3.5

    drdy_bit bit 0b0h.3 ;P3.3

    ?PR?sample?SAMPLE SEGMENT CODE ;定义程序代码段

    EXTRN DATA (sample_w) ;声明外部变量,在C51程序定义分配在DATA区

    EXTRN DATA(sa_p)

    EXTRN DATA(ram_point)

    EXTRN DATA (sa_timer)

    EXTRN DATA (sa_vzt)

    EXTRN BIT (write_alw) ;声明外部变量,在C51程序定义分配在可位寻址区

    EXTRN BIT (vz_bit)

    EXTRN BIT (fs_bit)

    PUBLIFC sample ;分用符号说明

    PUBLIC initial,res_ram

    RSEG ?PR?sample?SAMPLE

    using 0

    initial:;AD7715初始化,该标号即是C51定义外部函数

    ;initial()的入口地址

    ……

    ret

    ;


    sample: ;采样程序,该标号即是C51定义外部函数

    ;sample()的入口地址

    ……

    ret

    ……

    res_ram: ;62256指针复位,该标号即是C51定义外部函数res_ram()的入口地址


    ……

    ret

    end

    在研制无纸记录仪之前,作者用MASM51开发了其他仪表,采样部分有些相同,因此这次A51采样程序并不是重新编写,而是把以前的MASM51程序按A51的规则来修改。以前ASM的程序(数据段部分)如下所示:

    bseg

    ;

    write_alw bit 00h;

    vz_bit bit 01h

    fs_bit bit 02h

    ce_bit bit p1.6

    ram_cs bit p1.2

    b373 bit p1.1

    bit_dog bit p1.4

    data_bit bit P2.6

    sclk_bit bit P3.4

    drdy_bit bit p3.3

    ends

    ;

    dseg

    org 08h

    org 28h

    sample_w; ds 12

    sa_p: ds 1 ;当前通道号

    ram_point: ds 2

    sa_timer: ds 8 ;0,1,2,3每通道两字节

    sa_vzt: ds 8 ;0,1,2,3 vz

    ends

    ;

    cseg

    org 0h

    begin: reti

    org 03h

    lcall sample

    reti

    sample:

    ……

    ends

    从上述程序可以看出,在采样程序中所用到的变量并不少,定义在数据存储区28H单元起始的空间中。这样安排,对汇编程序没什么问题,但与C51主程序连接的时候,并不一定好,很多时候碰到地址空间溢出的问题(C51主程序编译连接后将近16K字节,CPU采用ATMEL公司的AT89C55WD)。如何调整这些变量的分配,并非容易。另外,C51随时要用到采样单元sample_w[12]的值,如果采用一般的参数传递,将是相当复杂而繁琐的;而采用全局及外部变量实现C51无参数经调用A51函数,极大简化了这些工作,大大提高了工作效率。


关键字:ASM51  无参数化  C51  函数 引用地址:ASM51无参数化调用C51 函数的实现原理

上一篇:单片机监控芯片X25043的功能介绍
下一篇:C8051F020单片机在海水淡化装置海水预处理上的应用

推荐阅读最新更新时间:2024-03-16 15:59

智能汽车程序、c51做智能小车
简介:本文介绍了c51做智能小车 的程序代码 /**********飞思卡尔智能汽车程序***/ //资源分配如下 //舵机用定时器0频率为50HZ //直流用定时器1频率为10KHZ //测速用外部中断0周期为50ms #include AT89X52.h #defineucharunsigned char #defineuint unsigned int sbit PWM_Steer=P1^0; sbit PWM_IN1=P1^2; sbit PWM_IN2=P1^3; //****舵机控制量************ //====f=24MHz ucharangle=8; /* uchar Low_Angle_L =
[单片机]
吉时利3390型任意波形/函数发生器的功能及特点分析
3390是一款功能灵活、简洁易用的可编程信号发生器,具有先进的函数、脉冲和任意波形生成能力。3390兼具出色的信号集成能力、快速的上升和下降时间、极低的噪声以及大容量波形存储器等特征于一体,能够提供高品质的输出信号。3390波形存储器容量相比市场上的其他同类波形发生器提高了四倍,能够支持高分辨率的波形。3390凭借其功能完善的任意波形发生器(ARB)、高速易用的特性,是面向最高50MHz波形应用的完整信号发生解决方案。 产品特点: ·一流的性能 ·50MHz正弦波频率 ·25MHz脉冲频率 ·支持256k点、14位分辨率的任意波形发生器 ·内置函数发生器功能包括:正弦、方波、三角波、噪声、直流等 ·具有快速(5ns)上升/下降
[测试测量]
Keil5安装教程(包含C51与MDK共存)WIN10 亲测可用
系统环境:WIN10 ,亲测可用。安装遇到问题的小伙伴欢迎骚扰我的个人公众号。 做为一个底层硬件小苦逼,经常需要用到stm32和51单片机,于是在keil for C51和mdk中来回换编译器,换来换去真是是人令人窒息。 所以今天就给大家带来了KEIL5编译环境的c51和MDK共存的教程。同时提供了STM32的pack,从f0到f4,以及低功耗的L系列,离线安装方便快捷。 02 安装教程 下载完成后,可以下图几个文件,首先进行c51的安装,双击C51V954.exe。 如果弹出警告窗口选择“是”。 点击NEXT 勾选 I agree to all thems of........ 点击Next
[单片机]
Keil5安装教程(包含<font color='red'>C51</font>与MDK共存)WIN10 亲测可用
STM32—IIC通信(软件实现底层函数)
使用GPIO引脚模拟SDA和SCL总线实现软件模拟IIC通信,IIC的具体通信协议层和物理层链接:IIC #ifndef __BSP_IIC_H #define __BSP_IIC_H #include stm32f10x.h #define SCL_PORT GPIOA #define SCL_PIN GPIO_Pin_2 #define SCL_MOOD GPIO_Mode_Out_OD #define SCL_SPEED GPIO_Speed_50MHz #define SDA_PORT GPIOA #define SDA_PIN GPIO_Pin_3 #defi
[单片机]
PWM控制亮度的流水灯c51程序
#include Reg52.h //--重定义函数变量--// #define uchar unsigned char #define uint unsigned int #define ulong unsigned long /* 定义常量 */ #define FOSC 12000000L //主时钟 #define T50us (65536-FOSC/12/1000000*50) //12T 模式下,50us 时间的计算方法 #define T10ms (65536-FOSC/12/1000*10) //12T 模式下,10ms 时间的计算方法 //--定义全局变量--// uc
[单片机]
单片机的中断函数编写方法
interrupt m修饰符 C51中断函数必须通过该修饰符进行修饰。在C51程序设计中,当函数定义时用了interrupt m修饰符,系统编译时把对应函数转化为中断函数,自动加上程序头段和尾段,并按51系统中断的处理方式自动把它安排在程序存储器中的相应位置。 在该修饰符中,m的取值为0~31,对应的中断情况如下: 0——外部中断0 1——定时/计数器T0 2——外部中断1 3——定时/计数器T1 4——串行口中断 5——定时/计数器T2 其它值预留。 C51编译器从绝对地址8m+3处产生一个中断向量,其中m为中断号,也即interrupt后面的数字。该向量包含一个到中断函数入口地址的绝对跳转。 【例】编写一个用于统计外中断0
[单片机]
不同数据类型的延时函数控制LED灯闪烁
//实例8:用不同数据类型控制灯闪烁时间 #include reg51.h //包含单片机寄存器的头文件 /****************************************************** 函数功能:用整形数据延时一段时间 ******************************************************/ void int_delay(void) //延时一段较长的时间 { unsigned int m; //定义无符号整形变量,双字节数据,值域为0~65535 for(m=0;m 36000;m++) ; //空操作 } /*************
[单片机]
c51中定时器工作时如何使用T0脚输入脉冲信号?
嵌入式系统中,定时器是一种常用的设备,可以实现各种时间控制功能,如计时、计数、产生中断等。8051单片机中有两个定时器:T0和T1,其中T0定时器主要用于计时和计数操作,可以通过T0脚输入脉冲信号来控制定时器的工作。 T0脚是单片机的P3.4口,既可以作为普通的输入输出口,也可以作为T0定时器的外部输入引脚。当T0脚作为定时器的外部输入引脚时,可以通过输入的脉冲信号来控制定时器的计数。在使用T0脚输入脉冲信号时,需要采取一些措施来确保信号的稳定性和正确性。 首先,需要确定输入脉冲信号的频率。在使用T0脚输入脉冲信号时,需要将信号的频率与定时器的工作频率相匹配。具体来说,当定时器使用外部时钟源时,其工作频率为外部时钟源频率的一半,因
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved