51单片机KEIL汇编嵌入C语言,程序防干扰设计WSPQQ:245641047看过许多资料,有讲解C嵌入汇编的,汇编嵌入C语言,但是不够详细,经过慢慢调试,发现汇编调用C函数,设置很方便,适合初学者学习汇编和C混合调用,并通过设置C文件编译为SRC文件,可起到学习汇编的作用!下面是我调试时的例子:文件中包含C函数声明和调用;中断处理语句和出错处理函数以及未用到的程序存储区调用出错处理函数,可防止外部电磁干扰时程序跑飞,进入中断或未使用的入口地址。程序跑飞有好多种,比如受外部干扰,打开中断,进入中断入口地址;或进入未使用的入口地址,程序一直执行下去;在这种情况下,软件看门狗程序或许也不能是程序跳转到主函数入口地址,需要添加软件抗干扰程序。闲话就不絮叨了,程序如下:第一个实例:汇编文件KEIL_ASM_C.A文件程序:EXTRNCODE(CALL1);声明外部C51函数ORG0000H;程序开始地址LJMPSTART;转STARTORG0003H;外中断0中断入口RETI;中断返回ORG000BH;定时器T0中断入口RETI;返回ORG0013H;外中断1入口地址RETI;中断返回ORG001BH;定时器T1中断入口RETI;中断返回ORG0023H;串行口中断入口RETI;中断返回ORG002BH;定时器T2中断入口RETI;中断返回;***************************;**;*初始化程序*;**;****************************CLEARMEMIO:CLRA;清ADECA;A为#0FFHMOVP1,A;端口置1MOVP2,A;端口置1MOVP3,A;端口置1MOVSP,#70H;设堆栈基址为70HMOVIE,#00H;关所有中断RET;*************************************;**;*主程序*;**;*************************************START:LCALLCLEARMEMIO;上电初始化;MAIN:MOVP0,#0FHLCALLCALL1MOVP0,#0F0HLCALLCALL1LJMPMAINNOP;PC值出错处理NOP;LJMPERR;重新初始化启动;;****************************;ERR(出错处理)程序;;****************************ERR:CLREA;关中断MOVDPTR,#ERR1;准备返回地址PUSHDPL;压栈PUSHDPH;RETI;中断返回ERR1:MOV56H,#0AAH;建立上电标志(出错标志)MOV57H,#55HMOVA,#00H;准备返回地址PUSHACC;压栈PUSHACCRETI;中断返回NOPNOPLJMPERR;软件陷阱;ORG07FAHNOPNOPNOPLJMPERR;软件陷阱;END;程序结束KEIL_ASM_C_ASM.C文件程序如下:#pragmacodesmall//选择小端存储器模式#defineucharunsignedcharvoidcall1(void)//延时函数{uchari,j,t;for(t=20;t0;t--)for(i=200;i0;i--)for(j=150;j0;j--);}这只是简单的使用汇编调用C函数,可实现P0口延时1.3秒左右变换闪烁一次。下面介绍汇编调用C函数,实现TIMER0,TIMER1,TOMER2,串口中断,可以让大家体会到汇编调用C函数是非常实用的,并能增强抗干扰能力!!!KEIL_TASK_C_MAIN.ASM程序如下:EXTRNCODE(INIT_MAIN);声明外部C51函数EXTRNCODE(INT_TIMER0);声明外部C51函数EXTRNCODE(INT_SERIAL_RX);声明外部C51函数EXTRNCODE(INT_TIMER1);声明外部C51函数ORG0000H;程序开始地址LJMPSTART;转STARTORG0003H;外中断0中断入口RETI;中断返回ORG000BH;定时器T0中断入口LJMPINT_T0;返回ORG0013H;外中断1入口地址RETI;中断返回ORG001BH;定时器T1中断入口LJMPINT_T1;返回ORG0023H;串行口中断入口LJMPINT_SERIAL;中断返回ORG002BH;定时器T2中断入口RETI;中断返回;***************************;**;*初始化程序*;**;****************************CLEARMEMIO:CLRA;清ADECA;A为#0FFHMOVP0,A;端口置1MOVP1,A;端口置1MOVP2,A;端口置1MOVP3,A;端口置1MOVSP,#70H;设堆栈基址为70HMOVIE,#00H;关所有中断RETNOPNOPLJMPERR;软件陷阱;*************************************;**;*主程序*;**;*************************************START:LCALLCLEARMEMIO;上电初始化;MAIN:MOVP0,#0FFH;P0口控制SSR,低电平导通,SSR工作LCALLINIT_MAINLJMPMAINNOP;PC值出错处理NOP;LJMPERR;重新初始化启动;;****************************;INT_T0定时器0中断程序;;****************************INT_T0:NOPNOPLCALLINT_TIMER0RETINOPNOPNOPLJMPERR;软件陷阱;****************************;INT_SERIAL串口中断程序;;****************************INT_SERIAL:NOPNOPLCALLINT_SERIAL_RXRETINOPNOPNOPLJMPERR;软件陷阱;****************************;INT_T1定时器1中断程序;;****************************INT_T1:NOPNOPLCALLINT_TIMER1RETINOPNOPNOPLJMPERR;软件陷阱;****************************;****************************;ERR(出错处理)程序;;****************************ERR:CLREA;关中断MOVDPTR,#ERR1;准备返回地址PUSHDPL;压栈PUSHDPH;RETI;中断返回ERR1:MOV56H,#0AAH;建立上电标志(出错标志)MOV57H,#55HMOVA,#00H;准备返回地址PUSHACC;压栈PUSHACCRETI;中断返回NOPNOPLJMPERR;软件陷阱;;********************************************;未占用存储空间调用ERR函数程序;;********************************************ORG07FAHNOPNOPNOPLJMPERR;软件陷阱;END;程序结束关键的C函数KEIL_ASM_C_INC.C程序如下所述:#pragmacodesmall#includereg52.h#defineucharunsignedcharsbitLED_T0=P1^0;sbitLED_T1=P1^1;sbitPIN_WDI=P3^4;//变量定义uchartemp,count0=0,count1,count_s;ucharflag_S=0,flag_P=0,flag_N=0;/***************************************************11059200[12*(65536-19456)]=11059200/(12*46080)=1/20函数功能:TIMER0初始化,Timer0清看门狗,50ms产生中断入口参数:void**************************************************/voidinit_timer0(void){TMOD|=0x01;//timer0mode1TH0=0x4C;TL0=0;IE|=0x92;TCON|=0x10;//opentimer0}/***************************************************函数功能:Timer0中断入口参数:interrupt1**************************************************/voidint_timer0()//interrupt1using1{count0++;TH0=0x4C;TL0=0;PIN_WDI=1;PIN_WDI=0;if(count0=20){LED_T0=~LED_T0;count0=0;}}/**************************************************Timer2串口波特率发生器T2CON位定义7-0TF2EXF2RCLKTCLKEXEN2TR2C/~T2CP/~RL2EXEN2=0时,T2EX引脚信号不起作用RCLK/TCLK=1时,CP/~RL2位不起作用,作为波特率发生器11059200/(32*36)=9600bps***************************************************函数功能:串口初始化11.0592MHZ入口参数:void**************************************************/voidinit_serial(void){PCON&=0x7F;//波特率不加倍nodoublebaudrate,SMOD1=0ofPCONSCON=0x50;//允许串口接收8-bitUART,mode1,REN=1T2CON&=0xF0;//EXEN2=0,TR2=0,C/T2=0;CP/RL2=0T2CON|=0x34;//TIMER2作为波特率发生器,RCLK=1,,TCKL=1,TR2=1RCAP2H=0x0FF;RCAP2L=0x0DC;//reloadbaud9600IE|=0x090;//EA=1,ES=1}/***************************************************函数功能:串口发送字符入口参数:ch**************************************************/voidserial_tx(ucharch){SBUF=ch;while(TI==0);//等待串口传送完毕TI=0;}/***************************************************使用时出现未知警告函数功能:串口发送字符串入口参数:数组指针*spoint**************************************************//*voidserial_tx_string(uchar*spoint){while(*spoint!='\0')//结束符{serial_tx(*spoint);spoint++;}}*//***************************************************函数功能:串口中断入口参数:interrupt4**************************************************/voidint_serial_rx()//interrupt4using3{ucharrx_ch;if(RI==0