/* ********************************************************************** * File: GMBTMPE.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: GMBTMPE.C - Rel. 1.1 - By Graziano Gaiba If GMB HR168 is provided with Real Time Clock, this demo allows to manage three time events that act on relays outputs of CN3 and CN4. In detail, it is possible to insert from console the action to perform and the time of activation for each of the three events; two time events allow to insert a combination for output relays, the third timer opens all the output relays. 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 #define FALSE 0x00 // Boolean value #define TRUE 0xFF #define LF 0x0A // ASCII codes #define CRET 0x0D #define RTCSLA 0xA0 // RTC PCF 8583 slave address // 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 // 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 waitkey(void) /* Shows messages and wait a key pressed */ { printf("Press a key to continue.."); getc(); puts(""); } void notavail(void) /* Shows message of resource not available on selected Mini Module and stops execution */ { printf("Resource not available."); for(;;); } 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); } unsigned char bintobcd(unsigned char d) /* Procedure that converts the binary coded byte d (0-99) into relative bcd code */ { d=((d/10)<<4)|(d%10); return d; } unsigned char bcdtobin(unsigned char d) /* Procedure that converts the bcd coded byte d into relative binary code (0-99) */ { d=((d>>4)*10)+(d&0x0F); return d; } 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 } 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 rd_i2c(unsigned char i2csla,unsigned char i2cadd,unsigned char *i2cdat) /* Reads the i2cdat byte from i2caddr address of 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(); // Check ACK on slave address+W wri2c_byte(i2cadd); // Supplies address i2cres = i2cres | rdi2c_bit(); // Check ACK on address starti2c(); // Supplies start sequence wri2c_byte(i2csla | 0x01); // Supplies slave address+R i2cres = i2cres | rdi2c_bit(); // Check ACK on slave address+R *i2cdat = rdi2c_byte(); // Reads data stopi2c(); // Supplies stop sequence return i2cres; // Returns operation result } void getrtc(unsigned char *wee,unsigned char *yea,unsigned char *mon,unsigned char *day,unsigned char *hou,unsigned char *min,unsigned char *sec) /* Acquires current date and time from Mini Module RTC and returns them on the function parameters */ { resi2c=rd_i2c(RTCSLA,0x02,&dr); // Reads and obtains seconds *sec=bcdtobin(dr); resi2c=rd_i2c(RTCSLA,0x03,&dr); // Reads and obtains minutes *min=bcdtobin(dr); resi2c=rd_i2c(RTCSLA,0x04,&dr); // Reads and obtains hours *hou=bcdtobin(dr); resi2c=rd_i2c(RTCSLA,0x05,&dr); // Reads and obtains day, year *day=bcdtobin(dr&0x3F); *yea=(dr&0xC0)>>6; resi2c=rd_i2c(RTCSLA,0x06,&dr); // Reads and obtains week day and month *wee=(dr&0xE0)>>5; *mon=bcdtobin(dr&0x1F); } void setrtc(unsigned char wee,unsigned char yea,unsigned char mon,unsigned char day,unsigned char hou,unsigned char min,unsigned char sec) /* Sets current date and time on Mini Module RTC with data passed in parameters, selecting 24 hours format and interrupt each second */ { resi2c=wr_i2c(RTCSLA,0x00,0x84); // Sets stop resi2c=wr_i2c(RTCSLA,0x01,0x00); // Sets hundreds of seconds resi2c=wr_i2c(RTCSLA,0x02,bintobcd(sec)); // Sets seconds resi2c=wr_i2c(RTCSLA,0x03,bintobcd(min)); // Sets minutes resi2c=wr_i2c(RTCSLA,0x04,bintobcd(hou)); // Sets hours, 24h format resi2c=wr_i2c(RTCSLA,0x05,(bintobcd(day)|(yea<<6))); // Sets day and year resi2c=wr_i2c(RTCSLA,0x06,(bintobcd(mon)|(wee<<5)));// Sets month, week day resi2c=wr_i2c(RTCSLA,0x07,0x00); // Sets timer resi2c=wr_i2c(RTCSLA,0x00,0x00); // Sets start } 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 } /**************************************************************************** Main program ****************************************************************************/ void main(void) { unsigned char wee,day,mon,yea,hou,min,sec; // Variables for RTC unsigned char t[3],o[3]; // Variables for time events 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 RTC management of GMB HR168 in uC/51 - Rel. 1.1 with GMM AC Zero"); do { rd_ee(0x07F8,&dr); } while (dr!=0); puts("This demo needs a Real Time Clock installed to work properly."); puts("If GMB HR168 or Mini Module feature the RTC press y, or press any other key..."); dr=getc(); if (dr=='y' || dr=='Y') // Verifies if RTC available { for (;;) // Endless loop { puts(""); // Space console puts("3 time events are managed with 1 second precision; for first two events it"); puts("is definible the output status on CN3 and CN4 while the third event"); puts("disables them."); for (dw=0;dw<3;dw++) { printf("\nTime %d (1..255,0 disable)? ",dw); inputse(input, 8); // Gets unsigned char t[dw]=(unsigned char)atoi(input); // Obtain and saves setting time if ((dw!=2) && (t[dw]!=0)) { printf("\nOutput status (0..255)? "); inputse(input, 8); // Gets unsigned char o[dw]=(unsigned char)atoi(input); // Obtain and saves output status } // endif } // endfor o[2]=0; // Arranges outputs status for third time event puts("\nElapsed seconds"); getrtc(&wee,&yea,&mon,&day,&hou,&min,&sec); // Acquire RTC dw=sec; // Initializes previous seconds hlp=0; // Resets elapsed seconds counter while ((t[0]+t[1]+t[2])!=0) // If at least one time event active { getrtc(&wee,&yea,&mon,&day,&hou,&min,&sec); // Acquire RTC if (sec!=dw) // If seconds changed { hlp++; // Increments elapsed seconds counter printf("%3d\r",hlp); // Shows elapsed seconds for (dw=0;dw<3;dw++) // Manages 3 time events { if (hlp==t[dw]) { setoutbuf(o[dw]); t[dw]=0; } // endif } // endfor dw=sec; // Update previous seconds } // endif } // endwhile puts(""); // Waits key pressed to exit waitkey(); } // endfor (;;) // End of endless loop } else { notavail(); // Resource not available on selected Mini Module } //endif }