/********************************************************************** * File demo_int.C - Rel. 1.1 compile with uC/51 V. 1.10.10 * * GRIFO(R) via Dell'Artigiano 8/6 40016 S. Giorgio di Piano (BO) * * Cards: GPC 554 d.s. 100997 and DEB01 or TIO16 * * Tel. +39 051 892052 Fax. +39 051 893661 * * http://www.grifo.com http://www.grifo.it * * sales@grifo.it tech@grifo.it grifo@grifo.it * * by Graziano Gaiba del 26.09.03 * ********************************************************************** This half duplex software serial has been inspired by source RS232_C2.C (C) 2002 WWW.WICKENHAEUSER.COM in folder \src\rs232_c. To make it work on GPC(r) 554 reception interrupt has been moved to pin P3.2 (/Int0). For compatibility, timer 0 is used. */ #include #include #include "reg552.h" #include "demo_int.h" #define TRBIT TR0 #define THREG TH0 #define TLREG TL0 #define TENA ET0 #define TXPIN P3.4 #define RXPIN P3.2 #define LF 0x0A #define CRET 0x0D // Driver in Assembler #asm ; *** Calculate: BDxyz =XTAL/12/xyz *** ; (XTAL/12) is the Timers input clock, the divider is either an 8 bit or an 16 bit number ; In the SLOW-MODE the timer is running as 16 bit timer, FAST uses the 8 bit mode. BAUD_CNT = CPU_SPEED/12/BAUDRATE SLOWMODE = BAUD_CNT > 200 ; Determine Timer Mode ; Local variables .segment _com2data, sclass dram, notext c2stat: .ds.b 1 ; Status (Steps of 2) c2byte: .ds.b 1 ; Sent/Received Byte .segment _int0, org $03 int0_irq: ljmp int0 ; jump to 'bigger' code space .segment _t0_irq, org $b ; Fix segment @ $000B t0_irq: ; no .export required! ljmp timer ; jump to 'bigger' code space .segment _com2 ; this is the 'bigger' codespace int0: mov c2stat,#24 ; Receive Byte! clr EX0 ; Disable INT0 .if SLOWMODE BD32F = - BAUD_CNT*3/2+50 mov THREG,#(BD32F)>>8 mov TLREG,#(BD32F)&255 .else mov TLREG,#256-(BAUD_CNT*3)/2+50 ; Skip Startbit and add. Cycles .endif clr TF0 ; Clear IRQ-Flag setb TRBIT ; Timer RUN setb TENA ; Enabele IRQ clr IE0 ; Clear Edge-Flag reti timer: .if SLOWMODE BD11F = -BAUD_CNT+12 mov THREG,#(BD11F)>>8 mov TLREG,#(BD11F)&255 .endif push PSW push ACC push DPL push DPH mov DPTR,#stab inc c2stat mov A,c2stat ; Get Status movc A,@A+DPTR push ACC ; Highbyte mov A,c2stat ; Get Status 2 dec A ; swap H/L inc c2stat movc A,@A+DPTR push ACC ; Lowbyte ret ; jumpto... tx_done: mov c2stat,#0 ; Ready again clr TRBIT ; Timer STOP setb EX0 ; enable INT0 sjmp t1_x tx_stopbit: setb TXPIN sjmp t1_x tx_startbit: clr TXPIN ; Ok sjmp t1_x tx_bit: mov A,c2byte rrc A mov TXPIN,C mov c2byte,A ; LSB first t1_x: pop DPH pop DPL pop ACC pop PSW reti rx_bit: mov C,RXPIN ; Get Bit mov A,c2byte rrc A mov c2byte,A ; insert Bit rx_stopbit: ; nothing to do! sjmp t1_x rx_done: mov c2stat,#128 ; Char Ready clr TRBIT ; Timer STOP clr IE0 ; Clear Edge-Flag setb EX0 ; enable INT0 sjmp t1_x ; *** Jump-Table stab: .dc.w tx_done ; 0 NIX ; * SEND .dc.w tx_startbit ; 2 .dc.w tx_bit ; 4 0 Transmit 8 Bits .dc.w tx_bit ; 6 1 .dc.w tx_bit ; 8 2 .dc.w tx_bit ; 10 3 .dc.w tx_bit ; 12 4 .dc.w tx_bit ; 14 5 .dc.w tx_bit ; 16 6 .dc.w tx_bit ; 18 7 .dc.w tx_stopbit ; 20 .dc.w tx_done ; 22 ; * RECEIVE .dc.w rx_bit ; 24 0 Receive 8 Bits .dc.w rx_bit ; 26 1 .dc.w rx_bit ; 28 2 .dc.w rx_bit ; 30 3 .dc.w rx_bit ; 32 4 .dc.w rx_bit ; 34 5 .dc.w rx_bit ; 36 6 .dc.w rx_bit ; 38 7 .dc.w rx_stopbit ; 40 .dc.w rx_done ; 42 ; * Send Byte over simulated COM2 .export _com2_putc _com2_putc: clr TENA ; Timer IRQ dis. clr EX0 ; INT0 IRQ dis. (transmitting!) mov c2byte,R7 ; Set Char mov c2stat,#2 ; Start Transmitting .if SLOWMODE mov THREG,#255 mov TLREG,#200 .endif clr TF0 ; Clear IRQ-Flag setb TRBIT ; Timer RUN setb TENA ; Enable IRQ ; * Wait polling until sent! ?c2p1: mov A,c2stat anl A,#127 ; Mask MSB jnz ?c2p1 ; wait until sent ret ; * Get Byte from simulated COM2 .export _com2_getc _com2_getc: mov A,c2stat ; Get Status cjne A,#128,_com2_getc ; 128: Byte received mov R7,c2byte ; get Byte mov R6,#0 mov c2stat,R6 ; Clear Status ret .export _com2_init ; * Got Byte from simulated COM2? .export _com2_kbhit _com2_kbhit: mov R7,#0 mov R6,#0 mov A,c2stat ; Get Status cjne A,#128,?c2k1 ; 128: Byte received inc R7 ; If Byte was 0: return 1 ?c2k1: ret ; * Init COM2 _com2_init: clr ET0 ; Timer 0 IRQ disable clr EX0 ; INT0 IRQ disable orl IP, #%00000011 setb IT0 ; INT0 Falling Edge anl TMOD,#$F0 .if SLOWMODE orl TMOD,#$01 ; Timer 0 Mode 1 (16 Bit Counter) .else orl TMOD,#$02 ; Timer 0 Mode 3 (8 Bit Reload) mov TH0,#256-BAUD_CNT ; Reload Value .endif mov c2stat,#0 ; Status Ready! clr IE0 ; Clear Edge-Flag setb EX0 ; enable INT0 ret #endasm // This definition is not to be seen by default, because it needs // So we include it manually... extern int _doprnt( void (*iofunk)(uchar) reentrant, far char* pfmt, va_list (fap)); void com2_printf(far char* pfmt, ...){ va_list(ap); va_start(ap,pfmt); _doprnt(com2_putc , pfmt, ap); // And send it to COM2... } void iniser(unsigned long baud) /* Initialise serial port with: Bit x chr = 8 Stop bit = 1 Parity = None Baud rate = baud using timer 1 as baud rate generator. */ { SCON=0x052; // Modo 1, receiver enabled TMOD&=0x00F; // Timer 1 in auto-reload mode TMOD|=0x020; TR1=0; // Stop TIMER 1 TH1=256-((2*22118400)/(384*baud)); // baud at 14.7456 MHz PCON=PCON|0x080; // Set SMOD=1 for higher baud rate TR1=1; // Start TIMER 1 } void ritardo(unsigned int rit) /* Software delay of rit milliseconds, calibrated for 22.1184 MHz, according to the CPU installed. */ { unsigned int r; do { for (r=0 ; r<150 ; r++); rit--; } while (rit>0); } void clrscr(void) /* Generic clear screen */ { unsigned char r; putc(CRET); for (r = 0 ; r < 25 ; r++) { putc(LF); // Sends 25 Line Feed } //endfor } void main(void) { unsigned char dato; ritardo(2); iniser(19200); com2_init(); TI=RI=0; ES=1; EA=1; clrscr(); // Clears the screen puts(""); puts("********* Demo to use half duplex software serial on CN3B **********"); puts(""); puts("To make the demo work correctly, connect an external RS 232 serial device"); puts("to CN3B configured like this: Baud Rate = 19200, Data Bit = 8, Stop Bit = 1,"); puts("No Parity"); puts(""); puts("Press a key to continue..."); while(! kbhit()) // Wait for key pressed ; getc(); // Remove key from serial buffer puts(""); puts("Charcters received from external RS 232 device go to the monitor,"); puts("characters typed on PC keyboard go to external device,"); puts("press F on PC to quit."); com2_printf("********* Demo to use half duplex software serial on CN3B **********\n"); do { if(kbhit()) // If key pressed on PC { com2_putc(dato=getc()); // Get it and send it to the terminal } if(com2_kbhit()) // If software serial got a byte... putc(com2_getc()); // ...read it and print it. } while(toupper(dato)!='F'); // Exit if 'f' or 'F' pressed puts("Infinite Loop"); while(1) ; }