/* ********************************************************************** * File GMBIOBE.C - Rel. 1.1 with uC/51 V. 1.20.04 * * Boards: GMB HR 84 + GMM 935 * * 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: GMBIOBE.C - Rel. 1.1 - By Graziano Gaiba This demo allows to use immediately relays outputs available on CN1 and buffered inputs available on CN6. Through the console can be setted the status of the four output relays or it can visualize the status of the eight NPN/PNP inputs. In addition, high level functions available on Mini Module are used: outputs driven by periodic automatic signals, inputs that generate interrupts, inputs counted by hardware, etc. 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 "89LPC935.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 // Global variables for interrupts management near unsigned int nint1,nint_t1; // 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 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); } /**************************************************************************** Interrupts service routines ****************************************************************************/ IRQ_VECTOR(ris_int1,IRQ_INT1); // Sets /INT1 vector void ris_int1(void) interrupt { nint1++; // /INT1 service routine: increments counter } IRQ_VECTOR(ris_int_t1,TIMER1); // Sets Timer 1 overflow vector void ris_int_t1(void) interrupt { nint_t1++; // Timer 1 overflow service routine: increments counter } /**************************************************************************** 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 GMM935 ds300803 + GMBHR84 ds220503"); // Internal control check(); puts(""); puts("I->Optocoupled inputs on CN6"); puts("O->Relay outputs on CN1"); printf("Section (I,O):"); do choice=toupper(getc()); while ((choice!='I') && (choice!='O')); putc(choice); puts(""); if (choice=='I') { puts("Management of 8 optocoupled input lines: connects to CN6 NPN or PNP signals"); puts("with relative + or - on pin 9=COM."); puts("Acquisition is running, press a key to exit"); do { dr=getinpbuf(); // Acuires and formats opto in status printf("%2X\r",dr); // Shows acquired status delay(50); // Avoids overflow on console } while(!kbhit()); getc(); puts("\n\rIN4 of CN6 is also trigger for INT 1."); puts("A transition H-L triggers the interrupt, which increments the counter."); puts("INT1"); P0_3=1; // Sets P0.3=/INT1 as input nint1=0; // Reset interrupt counters EX1=1; // Enables EX1 for /INT1 IT1=1; // Selects falling edge EA=1; // Enables interrupts do { printf("%4X\r",nint1); // Shows interrupt counters delay(50); // Avoids overflow on console } while (! kbhit()); getc(); EA=0; // Disables interrupts EX1=0; puts("\n\rTimer 1 is configured as hardware counter. IN8 is its trigger."); puts("Every overlow of Timer 1 triggers a counted interrupt."); puts("T1 N.INT"); TR1=0; // Stop Timer Counter P0M1 = P0M1 | 0x80; // Configures P0.7 (T1) as P0M2 = P0M2 & 0x7F; // input only TL1 = 0x00; // Reset counter TH1 = 0x00; TAMOD = TAMOD & 0xEF; // Set Timer Counter 1 in mode TMOD = TMOD & 0x0F; // 2,gate from TR1, as Counter TMOD = TMOD | 0x60; TL1 = 0xF0; // Starting value TH1 = 0xE1; // Autoreload value TR1=1; // Start Timer Counter 1 ET1=1; // Enable interrupt overflow of Timer 1 EA=1; // Enable interrupts do { // Shows counter of Timer 1 and numeber of overflow interrupts occoured printf("%2X %2X\r",TL1, nint_t1); } while (! kbhit()); getc(); TR0=0; // Stop Timer Counter 1 } else { clrscr(); puts("Management of 4 relays output signals: contacts A1,A2,B1,B2 of CN1 are"); puts("N.O. and are connected to corresonding common point A,B when closed by software."); do { printf("\rCombination of output lines status (0 to exit):"); inputse(input, 8); // Read unsigned char dw=(unsigned char)atoi(input); setoutbuf(dw); // Formats and sets relay outputs status } while (dw!=0); } } //endfor (;;) // End infinite loop }