/* ********************************************************************** * File: GMBIOBE.C - Rel. 1.1 with uC/51 V. 1.20.04 * * Boards: GMB HR168 + GMM AC Zero * * 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 07.06.05 * ********************************************************************** 07/06/05: GMBIOBE.C - Rel. 1.1 - By Graziano Gaiba This demo allows to use immediately relays outputs available on CN3 and CN4 and buffered inputs available on CN1 and CN2. Through the console can be set 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 "canarye.h" #include #include #include #define FALSE 0x00 // Boolean value #define TRUE 0xFF #define LF 0x0A // ASCII codes #define CRET 0x0D // Global variables for I2C BUS management near unsigned char resi2c; // I2C BUS error variable bit unsigned char SDA @ 0xA1; // SDA pin bit unsigned char SCL @ 0xA0; // SCL pin// Global variables for interrupts management near unsigned int nint0,nint1; // 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 functions and card hw sections management functions ****************************************************************************/ unsigned char divappr(unsigned long divid,unsigned long divis) /* Procedure that calculates the 8 bit integer quotient, correctly approximated, between the dividend and the divisor passed as parameters, by using the successive subtractions tecnique. This function is used to reserve the 2K of code required by the same librari functions. */ { unsigned char d; d=0; // Set quotient to zero while (divid>=divis) { divid=divid-divis; d++; } //endwhile divis=divis>>1; // Halves divisor to check the remainder if (divid>=divis) d++; //endif return d; } void init_cpu(void) /* Perform some specific initialization of CPU SFRs */ { EA=0; // Ensures interrupt disabled CKCON=0x00; // Set X1 clock mode = standard mode AUXR=0x0C; // Selects ERAM on external data area EECON=0x00; // Disables internal EEPROM } void iniser(unsigned long baud) /* Initializes the serial line with: Bit x chr = 8 Stop bit = 1 Parity = None Baud rate = baud using timer 1 as baud rate generator. */ { SCON=0x052; // Mode 1, enables receiver TMOD&=0x00F; // Timer 1 in auto-reload mode TMOD|=0x020; TR1=0; // Stops TIMER 1 TH1=(unsigned char)(256-divappr((2*14745600),(384*baud))); // 14.7456 MHz PCON=PCON|0x080; // Sets SMOD=1 for high baud rates TR1=1; // Starts TIMER 1 TI=1; // Sets end of transmission bit for optimized console (SIOTYPE=k) } 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); // Transmit 25 Line Feeds } //endfor } void delay(unsigned int del) /* Executes a software delay of del milliseconds, calibrated on a 14.7456 MHz CPU Clock */ { unsigned int r,dt1ms; dt1ms=100; // Experimental value for 1 msec. delay do { for (r=0 ; r0); } void setP01234inp(void) /* Sets all the lines of all the ports (P1,P2,P3,P4) in input. */ { P0=0xFF; // Setta Port 0 in INPUT dr=P0; ADCF=0x00; // Sets P1.x as I/O port P1=0xFF; // Sets Port 1 as INPUT dr=P1; P2=0xFF; // Sets Port 2 as INPUT dr=P2; P3=0xFF; // Sets Port 3 as INPUT dr=P3; P4=0xFF; // Sets Port 4 as INPUT dr=P4; } 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) */ { if ((dat&0x01)!=0) // Determines and sets P1.4=OUT A1 status P1_4=0; else P1_4=1; //endif if ((dat&0x02)!=0) // Determines and sets P1.5=OUT A2 status P1_5=0; else P1_5=1; //endif if ((dat&0x04)!=0) // Determines and sets P1.6=OUT A3 status P1_6=0; else P1_6=1; //endif if ((dat&0x08)!=0) // Determines and sets P1.7=OUT A4 status P1_7=0; else P1_7=1; //endif //endif if ((dat&0x10)!=0) // Determines and seto P4.0=OUT C1 status P4_0=0; else P4_0=1; //endif if ((dat&0x20)!=0) // Determines and set P4.1=OUT C2 status P4_1=0; else P4_1=1; //endif if ((dat&0x40)!=0) // Determines and set P2.2=OUT D1 status P2_2=0; else P2_2=1; //endif if ((dat&0x80)!=0) // Determines and set P1.3=OUT D2 status P1_3=0; else P1_3=1; //endif } unsigned char getinpbuf1(void) /* Gets the status of the 8 buffered input lines on connector CN1 that are common to COM 1 and returns it */ { unsigned char dato; dato=P3; // Gets current current dato=dato & 0xFC; // Masks P3.1 and P3.0 if (P1_1!=0) // Acqiures and adds P1.1 status dato=dato | 0x01; if (P1_2!=0) // Acqiures and adds P1.2 status dato=dato | 0x02; return(dato); // Resturns obtained value } unsigned char getinpbuf2(void) /* Gets the status of the 8 buffered input lines on connector CN2 that are common to COM 2 and returns it */ { return(P0); // Restituisce dato ottenuto } void riti2c(void) /* Performs a delay for syncronous I2CBUS communication. The delay is sufficient for a 22 MHz clock, X1 modality */ { #asm nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop #endasm } void starti2c(void) /* Generates start sequence for I2C BUS */ { SCL=0; // Start sequence SDA=1; riti2c(); SCL=1; SDA=0; riti2c(); SCL=0; //endif } void stopi2c(void) /* Generates stop sequences for I2C BUS */ { SCL=0; // Stop sequence SDA=0; riti2c(); SCL=1; SDA=1; riti2c(); SCL=0; //endif } void wri2c_bit(unsigned char i2cbit) /* Serializes the D0 bit of i2cbit, on I2CBUS */ { SCL=0; // Sets SDA and generates positive pulse on SCL SDA=i2cbit; riti2c(); SCL=1; riti2c(); SCL=0; //endif } unsigned char rdi2c_bit(void) /* Deserializes one bit from I2CBUS and saves it on lsb of the returned value */ { unsigned char biti2c; SDA=1; // Avoids conflicts in SDA acquisition SCL=0; // Ensures SCL status riti2c(); SCL=1; // Generates positive pulse on SCL and reads SDA biti2c=SDA; riti2c(); SCL=0; //endif return biti2c; } void wri2c_byte(unsigned char i2cbyte) /* Serializes the i2cbyte byte on I2CBUS */ { unsigned char b; for (b = 1; b <= 8; b++) { if ((i2cbyte & 0x80) == 0) // Determines and sets b bit wri2c_bit(0); else wri2c_bit(1); i2cbyte = i2cbyte << 1; } } unsigned char rdi2c_byte(void) /* Deserializes one byte from I2CBUS and saves it in the returned value */ { unsigned char b,tmp; tmp = 0; for (b = 1; b <= 8; b++) { tmp = tmp << 1; tmp = tmp | rdi2c_bit(); // Gets and saves b bit } return tmp; } unsigned char wr_i2c(unsigned char i2csla,unsigned char i2cadd,unsigned char i2cdat) /* Writes the i2cdat byte to i2caddr address of the I2CBUS device that have the slave address i2csla. Returns a boolean flag that signals the operation result: 0=right,1=wrong */ { unsigned char i2cres; i2cres = 0; // Sets right result starti2c(); // Supplies start sequence wri2c_byte(i2csla); // Supplies slave address+W i2cres = i2cres | rdi2c_bit(); // Checks ACK on slave address+W wri2c_byte(i2cadd); // Supplies address i2cres = i2cres | rdi2c_bit(); // Check ACK on address wri2c_byte(i2cdat); // Supplies data i2cres = i2cres | rdi2c_bit(); // Check ACK on data stopi2c(); // Supplies stop sequence return i2cres; // Returns operation result } unsigned char peekb(unsigned int addr) /* Reads the byte from addr address of external data area and returns it */ { return *(xdata unsigned char *)addr; // Gets byte from location } void rd_ee(unsigned int eeaddr,unsigned char *eedat) /* Reads the eedat byte from eeaddr address of internal EEPROM */ { AUXR=0x2E; // Deselects ERAM and increase MOVX duration EECON=0x02; // Selects microprocessor EEPROM on external data area *eedat=peekb(eeaddr); // Performs EEPROM reading AUXR=0x0C; // Selects ERAM on external data area EECON=0x00; // Disables microprocessor EEPROM } /**************************************************************************** Interrupts service routines ****************************************************************************/ IRQ_VECTOR(ris_int0,IRQ_INT0); // Sets /INT0 vector void ris_int0(void) interrupt { nint0++; // /INT0 service routine: increments counter } IRQ_VECTOR(ris_int1,IRQ_INT1); // Sets /INT1 vector void ris_int1(void) interrupt { nint1++; // /INT1 service routine: increments counter } /**************************************************************************** Main program ****************************************************************************/ void main(void) { init_cpu(); // Initializes the used CPU iniser(19200); // Initializes serial line for console with timer 1 setP01234inp(); // Sets Port 0,1,2,3,4 as INPUT clrscr(); // Selects used Mini Module puts("Demo buffered I/O management of GMB HR168 in uC/51 - Rel. 1.1 with GMM AC Zero"); do { rd_ee(0x07F8,&dr); } while (dr!=0); for(;;) { puts("I->Optocoupled inputs on CN1 and CN2"); puts("O->Relay outputs on CN3 and CN4"); printf("Section (I,O):"); do { choice=toupper(getc()); } while ((choice!='I') && (choice!='O')); putc(choice); puts(""); if (choice=='I') { dr=ADCF; // Sets P1.1 and P1.2 as I/O ports dw=dr & 0xF9; ADCF=dw; puts("Management of 16 optocoupled input lines: connect to CN1 and CN3 NPN or PNP"); puts("signals with each common pin on pin 9 of connector of the group it belongs"); puts("(pin9 of CN1=COM1, pin 9 of CN2=COM2)."); puts("Acquisition is running, press a key to exit"); do { dr=getinpbuf1(); // Acuires and formats opto in status hlp=getinpbuf2(); printf("%2X %2X\r",dr,hlp);// Shows acquired status delay(50); // Avoids overflow on console } while(!kbhit()); getc(); puts("\n\rThe signals connected to CN1 perform functions as interrupts, counters, PCA"); puts("clock, etc."); puts("Interrupts acquisition is running, press a key to exit"); puts("IN 3 IN 4"); P3_2=1; // Sets P3.2=/INT0 as input P3_3=1; // Sets P3.3=/INT1 as input nint0=0; // Reset interrupt counters nint1=0; EX0=1; // Enables EX0 for /INT0 IT0=1; // Selects falling edge EX1=1; // Enables EX1 for /INT1 IT1=1; // Selects falling edge IPH0=0x05; // Sets higher priority (3) for /INT0 and IPL0=0x01; // middle high priority (2) for /INT1 and IPH1=0x00; // low priority (0) for other interrupts IPL1=0x00; EA=1; // Enables interrupts do { printf("%4X %4X\r",nint0,nint1); // Shows interrupt counters delay(50); // Avoids overflow on console } while (! kbhit()); getc(); EA=0; // Disables interrupts EX0=0; EX1=0; puts("\n\rHardware counter visualization. Press a key to exit"); puts("IN 5"); P3_4=1; // Sets P3.4=T0 as input TR0=0; // Disables Timer Counter 0 TL0=0x00; // Resets current counter value TH0=0x00; TMOD=(TMOD & 0xF0) | 0x05; // Sets Timer 0 as 16 bits Counter (mode 1) TR0=1; // Enables Timer Counter 0 do { val=(TH0 << 8) | TL0; // Acquires Timer Counter 0 printf("%4X\r",val); // Shows read combination } while (! kbhit()); getc(); TR0=0; // Disables Timer Counter 0 } else { dr=ADCF; // Sets P1.4..P1.7 as I/O ports dw=dr & 0x0F; ADCF=dw; puts("8 relays output lines management: on CN3 and CN4 the contacts A1 and A2,"); puts("B1 and B2, C1 and C2 are normally open and they are connected to respective"); puts("common A, B, C or D when set by software."); puts("Relay of contact D2 can be driven by signal of pin 30 of Mini Module (default)"); puts("or by signal of pin 16, according to the connection of J10."); puts("This demo can work only with default connection (J10 in 3-4)."); puts("For further information please refer to manual of GMB HR168."); do { printf("\rLines combination (0..255,0 to exit):"); inputse(input, 8); // Gets unsigned char dw=(unsigned char)atoi(input); setoutbuf(dw); // Formats and sets relay outputs status } while (dw!=0); puts("\n\rThe signals connected to CN3 perform PCA functions (timers, PWM"); puts("generation, etc)."); puts("The A1 output is enabled about at 1 Hz and 50% duty cicle; press a key to exit"); P1_4=1; // Sets P1.4=OUT A1 high to allow PCA setting TR0=0; // Disable Timer Counter 0 TL0=0x00; // Reset current value TH0=0x00; TMOD=TMOD & 0xF0; // Sets timer 0 as 13 bits Timer (mode 0) TR0=1; // Enables Timer Counter 0 CMOD=0x04; // Run in idle, Tmr 0 ovr, no interrupt CCON=0x40; // Enables PCA timer/counter CCAPM1=0x42; // Enables PWM on PCA module 1 with 50% duty cycle CCAP1H=0x80; while (! kbhit()); getc(); TR0=0; // Disables Timer Counter 0 CCON=0x00; // Disables PCA timer/counter CCAPM1=0x00; // Disables PWM on PCA module 1 } // endif } //endfor (;;) // End of endless loop }