/* ********************************************************************** * File GMBSERE.C - Rel. 1.1 with uC/51 V. 1.20.04 * * Boards: GMB HR 84 + GMM 936 * * GRIFO(R) via Dell'Artigiano 8/6 40016 S. Giorgio di Piano (BO) * * Tel. +39 051 892052 Fax. +39 051 893661 * * http://www.grifo.com http://www.grifo.it * * by Graziano Gaiba date 06.06.05 * ********************************************************************** 06/06/05: GMBSERE.C - Rel. 1.1 - By Graziano Gaiba This demo is a simple example of communication capableto work with all electric protocols available on CN2 (RS 232, RS 422, RS 485, current loop or TTL). In detail, through low level functions, it is possible to program baud rate from console, then each character received from serial port is sent to the port itself; reception of character 'R' decides how to manage the communication direction (signal DIR) for RS 422 and RS 485. Note To avoid problems do not use complex operations on a single source line, especially inside procedures by using their parameters or their local variables. */ /**************************************************************************** Header, constant, data structure, etc. ****************************************************************************/ #include "89LPC936.h" #include #include #include #define FALSE 0x00 // Boolean value #define TRUE 0xFF #define LF 0x0A // ASCII codes #define CRET 0x0D #define RCINT 7372800 // Clock frequency from internal RC #define QZ11M 11059200 // Clock frequency from external crystal #define TOUTEEP 5000 // EEPROM management time out // General purpose global variables used by main and procedures near unsigned char choice,dr,dw,hlp; near unsigned int val; inear unsigned char input[9]; // Console input buffer /**************************************************************************** General purpose global variables, hw sections management ****************************************************************************/ near unsigned char i; near unsigned long baud; near unsigned long clk; // Clock della CPU /**************************************************************************** General purpose functions and card hw sections management functions ****************************************************************************/ unsigned char rd_ucfg1(void) /* Read the configuration byte UCFG1 from FLASH by using the IAP procedures of P89LPC932 Boot Rom code. Returns the read byte in the function name, with no checks for possible errors. This function generates an inevitable warning during compilation: the returned value is directly set by IAP procedure, not by C code. */ { #asm mov A,#$03 ; Uses Misc. Read command mov R7,#$00 ; Reads UCFG1 register lcall $0FF03 ; Calls IAP procedure at PGM_MTP address #endasm } unsigned char peekb(unsigned int addr) /* Reads a byte at address addr in external data area and returns it */ { return *(xdata unsigned char *)addr; // Fetch byte from address } // Check of internal peripharal correct status, eventually looping. // Uses general purpose variables st,t,m,ind,hlpw void check(void) { unsigned char st,s,t,m,ind; DEECON = 0x01; t = peekb(0xff); DEEADR = 0xFF; t = 1; ind = 0xF7; do { m = peekb(0x07); if(m & 0x80) { m = m & 0x03; ind = m + 0xF8; t = peekb(ind); } else { t = 0; } st = DEECON & 0x80; } while(st == 0); st = DEEDAT; do { s = peekb(ind++); if(ind == 0xFF) { ind = 0xF9; } do { m = s; if(! st) { t++; } } while(t <= m); } while(st != 0); } void init_cpu(void) /* Obtains the clock frequency of the CPU mounted on the card GMM 932 and save it in proper variable. Moreover performs necessary general initializations. */ { unsigned char M1, M2; EA=0; // Ensures all interrupts disabled P1M1 = 0; // Required for RS232 communication /* IN1 <- P0.0 IN2 <- P0.1 IN3 <- P0.2 IN4 <- P1.4 IN5 <- P0.3 IN6 <- P0.4 IN7 <- P0.5 IN8 <- P0.7 OUT A1 -> P1.6 OUT A2 -> P1.7 OUT B1 -> P2.1 OUT B2 -> P2.7 */ PT0AD = 0; // P0.1-5 as digital I/O, not analog input M1 = P0M1; // Set P0.0-5 and P0.7 as solo input M2 = P0M2; M1 = M1 | 0xDF; M2 = M2 & 0x40; P0M1 = M1; P0M2 = M2; M1 = P1M1; // Set P1.4 as input only and M2 = P1M2; // P1.6 and P1.7 as open drain output M1 = M1 | 0xD0; M2 = M2 | 0xC0; M2 = M2 & 0xEF; P1M1 = M1; P1M2 = M2; M1 = P2M1; // Set P2.1 and P2.7 as M2 = P2M2; // open drain output M1 = M1 | 0x82; M2 = M2 | 0x82; P2M1 = M1; P2M2 = M2; } void clrscr(void) /* Performs the clear screen function for a generic console */ { unsigned char r; putc(CRET); for (r = 0 ; r < 25 ; r++) { putc(LF); // Transmits 25 Line Feeds } //endfor } void waitkey(void) /* Shows a message on console and wait a key pressed */ { printf("Press a key to continue..."); getc(); puts(""); } void iniser(unsigned long baud, unsigned char stop) /* Initializes the serial line with: Bit x chr = 8 Stop bit = stop Parity = None Baud rate = baud using the internal baud rate generator and the clock frequency saved in global variable clk. */ { unsigned long divbr; PCON = PCON & 0xBF; // Resets bit SMOD0 to set mode if (stop==1) SCON=0x52; // Mode 1 (1 stop),No multiproc,Rx enable else SCON=0xDA; // Mode 3 (2 stop),No multiproc,Rx enable //endif BRGCON=0x02; // Sets passed baud rate divbr=baud << 4; // Calculates divisor for baud divbr=clk-divbr; divbr=divbr/baud; BRGR0=(unsigned char)(divbr & 0x00FF); divbr=divbr >> 8; BRGR1= (unsigned char)(divbr & 0x00FF); BRGCON=0x03; TI=1; // Sets end of transmission bit for optimized console (SIOTYPE=k) } void delay(unsigned int del) /* Executes a software delay of del milliseconds, calibrated on the clock frequency used by mini module, previously obtained and saved on global variable clk. */ { unsigned int r,del1ms; if (clk==RCINT) del1ms=335; // Experimental value for 1 msec. delay at 7.3728 MHz else del1ms=500; // Experimental value for 1 msec. delay at 11.0592 MHz //endif do { for (r=0 ; r0); } void setoutbuf(unsigned char dat) /* Sets status of the 4 buffered output lines with the value saved in low nibble of dat parameter; the setting is on the single bits of port 1 to avoid conflict on the other lines used in different section and it is in PNP logic (a bit setted to 1 in dat sets the micro lines to 0 and causes connection of the output contact) Correspondance between port and relay outputs is: OUT A1 -> P1.6 OUT A2 -> P1.7 OUT B1 -> P2.1 OUT B2 -> P2.7 */ { if ((dat&0x01)!=0) // Determines and sets P1.6=OUT A1 status P1_6=0; else P1_6=1; //endif if ((dat&0x02)!=0) // Determines and sets P1.7=OUT A2 status P1_7=0; else P1_7=1; //endif if ((dat&0x04)!=0) // Determines and sets P2.16=OUT A3 status P2_1=0; else P2_1=1; //endif if ((dat&0x08)!=0) // Determines and sets P2.7=OUT A4 status P2_7=0; else P2_7=1; //endif } unsigned char getinpbuf(void) /* Gets the status of the 8 buffered input lines and returns it Correspondance between port and NPN/PNP optocoupled inputs is: IN1 <- P0.0 IN2 <- P0.1 IN3 <- P0.2 IN4 <- P1.4 IN5 <- P0.3 IN6 <- P0.4 IN7 <- P0.5 IN8 <- P0.7 */ { // Reads ports status and complements it because the inputs are in complemented // logic, then returns the result. unsigned char statusP0, statusP1, val = 0; statusP0 = P0; statusP1 = P1; // Bits 0..2 of val val = (statusP0 & 0x07); // Bit 3 of val val |= (statusP1 & 0x10) >> 1; // Bits 4..6 of val val |= (statusP0 & 0x38) << 1; // Bit 7 of val val |= (statusP0 & 0x80); return(~val); } /**************************************************************************** Low level console management ****************************************************************************/ void putcar(unsigned char tra) /* Send a character to the serial line */ { while (!TI) // Wait for transmitter free continue; TI = 0; // Send character SBUF = tra; } unsigned char getcar(unsigned char *ric) /* Check for a character reception on serial line, in this case return it in parameter ric. */ { if (RI) { RI = 0; // Get and returns the character received *ric = SBUF; return(TRUE); } else return(FALSE); // No chr available //endif } /**************************************************************************** Main program ****************************************************************************/ void main(void) { init_cpu(); // Initialize CPU required sections clk=RCINT; // Set clock for RC internal (can be acquired only later) P0M1=P0M1 | 0x40; // Configures P0.6 in mode 3=Open Drain P0M2=P0M2 | 0x40; for (i=0 ; i<16 ; i++) // Delay for Hyperterminal start with DL1 blinking { P0_6=!P0_6; // Complements DL1 status delay(125); } //enfor dr=rd_ucfg1(); // Acquires user configuration byte dr=dr & 0x07; // Masks bits for CLK source configuration switch (dr) { case 0x00: clk=QZ11M; // Clock frequency by external crystal break; case 0x03: clk=RCINT; // Clock frequency by internal RC break; } iniser(19200, 1); // Initializes console serial line for(;;) { clrscr(); // Shows demo program menu printf("Demo 1.1 for GMM936 ds300803 + GMBHR84 ds220503"); // Internal control check(); puts(""); printf("Demo serial line on GMB HR84 in uC/51 - Rel. 1.1"); puts(""); puts("Configure serial line for required electric protocol following the user"); puts("manual indications and connect the signals to CN2."); puts("The demo continuosly checks the chr reception and when available it transmit"); puts("them back, through low level functions, until chr E is received that restores"); puts("communication with console at 19200 Baud. The R character reception"); puts("complements the status of DIR signal, used in RS422,RS485 communication"); puts("to manage the transmitter."); printf("Baud Rate="); inputse(input, 8); // Gets unsigned long baud=(unsigned long)atol(input); puts(""); printf("Stop Bit="); inputse(input, 8); // Gets unsigned char dw=(uchar)atoi(input); puts(""); delay(10); // Waits end of transmission of last chr iniser(baud, dw); // Initializes serial line with inserted baud rate dr=0; // Set as output (push pull) P2.0 P2M1 &= 0xFE; P2M2 |= 0x01; do { if (getcar(&dr)) // If chr received from serial port { if (dr=='R') { // Complement transmitter status P2_0 = P2_0 ^ 1; // through signal DIR=MM PIN 11 } // endif putcar(dr); // Send chr received } // endif } while (dr!='F'); // Wait to receive character F delay(10); // Wait completion of last char sending iniser(19200, 1); // Initialize serial console at 19200 Baud, 1 Bit stop } //endfor (;;) // End of endless loop }