Você está na página 1de 8

Tutorial - 3 TITLE : Interfacing C with Assembly using Cx51 Compiler Introduction :

The C programming language is a general-purpose programming language that provides code efficient, elements of structured programming, and a rich set of operator. C is not a big language and is not designed for any one particular area of application. Its generality combined with its absence restriction, makes C a convenient and effective programming solution for a wide variety of software takes. Many applications can be solved more easily and efficient with C than with other more specialized languages. The Cx51 optimizing C compiler is a complete implementation of the American National Standards Institute (ANSI) standards for the C language. Cx51 is a grouped-up implementation dedicated to generate extremely fast and compact code for 8051 microprocessor. Cx51 provides the flexibility of programming in C and the code efficiency and speed of assembly language. Following are some examples explaining the flexibility Cx51 provides in programming of 8051. 1) Generic 8051 Bit I/O Example Program This example program shows how to: Declare a special function Register (SFR) Declare a bit in bit-addressable SFR Configure an I/O port pin as an input Read an Input Pin Write an Output Pin

/*Definitions for P1 (8 bits). P1.0 and P1.1 */ sfr P1 = 0x90; /* SFR for P1*/ sbit P1-0 = P1^0; /* SFR for P1.0*/ sbit P1_1 = P1^1; /* SFR for P1.1*/ /* MAIN C function */ void main(void) { P1_1 = 0; /*Configure P1.0 as an input */ while(1) { P1_1 = P1_0; /* copy P1.0 to P1.1*/ } }

The interrupt attribute takes as an argument an integer constant in the 0 to 31 value range. Expressions with operators and the interrupt attribute are not allowed in function prototypes. The interrupt attribute affects the object code of the function as follows: The contents of the SFR, ACC,B,DPL,DPH, and PSW when required, are saved on the stack at function invocation time.

All working registers used in the interrupt function are stored on the stack if a register bank is not specified with the using attribute. The working register and special registers that were saved on the stack are restored before exiting the function. The function is terminated by the 8051 RETI instruction.

In addition, the Cx51 compiler generates the interrupt vector automatically. This example program shows how to configure timer/counter 0 as a 16-bit timer. It also shows how to configure interrupt associated with timer 0. An interrupt service routine (ISR) is invoked each time the timer overflows. The program makes the use of REG52.H, which is a header file which defines all the special function registers and similar entities of 8051. The copy of REG52.H is enclosed as the annexure. #include<reg52.h> static unsigned long overflow_count=0; /*MAIN C function*/ void main(void) { while(1) { /*Set Timer0 for 16-bit timer mode. The timer counts to 65535, overflows, and generates an interrupt.*/ TMOD=(TMOD & 0xF0)|0x01; TH0=0xFF; register*/ TL0=0xFF; ET0=1; TR0=1; /*Set T/C Mode*/ /*Load count in timer count /*Enable Timer 0 interrupts*/ /*register definition header file */ /*define a static variable*/

while(TF0==1) { EA=1; } } } void timer0_ISR (void) interrupt 1 { overflow_count++; TF0=0; } } /*Timer ISR*/

2) Generic 8051 Port I/O Example program This example program shows how to: Declare a Special Function Register(SFR) Configure an I/O Port as an Input Read an Input Port Write an Output Port /* Definitions for P1 (8 bits) and P3 (8 bits) */ Sfr P1=0x90; Sfr P3=0xB0; /* MAIN C function */ void main(void) { /*SFR definition for Port 1 */ /*SFR definition for Port 3 */

Unsigned char pval; P1=0xFF; while(1) { Pval=P1; P3=pval; } }

/* temp variable for port values */ /* Setup P1 for Input */ /* Read P1 into pval */ /* Write pval to P3 */

3) Generic 8051 Timer 0 Interrupt Service Routine The 8051 and its disadvantage provide a number of hardware interrupts that may be used For counting, timing, detecting external events, and sending and Receiving data using the serial interface. The standard interrupts found on an 8051 are listed in the following table: 0 EXTERNAL INT 0 1 TIMER/COUNTER 0 2 EXTERNAL INT 1 3 TIMER/COUNTER 1 4 SERIAL PORT 0003H 000BH 0013H 001BH 0023H

As 8051 vendors create new parts, more interrupts are added. The Cx51 compiler supports interrupt functions for 32 interrupts (0-31) in which 0-4 are the standard 8051 interrupts. The interrupt function attribute, when included in a declaration, specifies that the associated function is an interrupt Function. 4) Generic 8051 External Interrupt service routine This example program shows how to configure external interrupt 0. It also shows how to configure interrupt associated with external interrupt 0. An interrupt service routine (ISR) is invoked each time the interrupt is received .The program makes use of REG52.H #include<reg52.h> static unsigned long exo_isr_counter=0; /*MAIN C FUNCTION*/ void main(void) { INT0=1; INT0=1; EX0=1; EA=1; while(1) { } /*register definition header file*/ /*define static variable*/

} void exo_isr(void) interrupt 0 { exo_isr_counter++; }

/* Increment the interrupt count*/

5) C to Assembly and Assembly to C It is possible to access assembly routines from C routines and vice versa. Following programs illustrate this. The project consist of three files viz, main, c_func.c and a_func.a51.from which the latter is the assembly code file while the first two are c code.Code main.c calls a_func.a51 which in turn calls c_func.c. main.c extern void a_func(void); /*define the external function to be called*/

/*MAIN C function*/ void main(void) { while(1) a_func(); }

/*calling assembly program from C program*/

a_func.a51 /*C51 Directives*/

NAME A_FUNC ?PR?a_func?A_FUNC SEGMENT CODE EXTRNCODE(c_func) PUBLIC a_func RSEG ?PR?a_func?A_FUNC /*Assembly program*/ a_func: USING 0 LCALL c_func MOV A,#78h MOV B,#34h ADD A,B RET /*calling Cprogram from assembly program*/

END /*C subroutine called from assembly*/ c_func.c void c_func(void) { int I; I=P0; if(I<100) P1=P0; Else P2=P0; } Before Execution

After Execution

Before Execution

After Execution

6) Assembly code within C code It is possible to write an assembly code within a C code. This is required many cases when some time critical code written in C takes more time to execute when cross complied to assembly. This facility in Cx51 makes use of SRC directive. This directive should be included in C code and the part which is to be written in assembly should be between #pragma asm and #pragma endasm. On compiling this code instead of .obj, .src file is generated contains the C code translated into assembly with the assembly code between # pragma asm and #pragma endasm remaining without changing. This file can be saved with extension .a51 and can be treated as any assembly code. Following examples illustrates this #pragma SRC sfr P1=0x90; sbit P1_0=P1^0; sbit P1_1=P1^1; /*Main C code begins*/ void main(void) { P1_0=1; while(1) { /*Configure P1.0 as input*/ /*SFR for P1*/ /*SFR for P1.0*/ /*SFR for P1^1*/

P1_1=P1_0; #pragma asm mov a,#0ffh; #pragma endasm } }

/*Copy P1.0 to P1.1*/ /*Assembly code begins*/ /*Assembly code ends*/

Você também pode gostar