/* ********************************************************************** ** Program: Wee51e.c - Version : 1.4 - 02 October 2003 ** ** Compiler: uC/51 Ver. 1.10.10 ** ** Board: K51-AVR and 89c51 or compatible ** ** Firm: grifo(r) ITALIAN TECHNOLOGY ** ** Via Dell' Artigiano 8/6 40016 San Giorgio di Piano (BO) ** ** Tel.+39 051 892 052 Fax +39 051 893 661 ** ** http://www.grifo.com http://www.grifo.it ** ** sales@grifo.it tech@grifo.it grifo@grifo.it ** ** ** ** Written by: Graziano Gaiba ** ********************************************************************** This program allows to write to a serial EEPROM on IC4 (max 24c08), with addresses ranging from &H400 to &H7ff, addresses from &H0 to &H0FF are taken by IC7 (RTC PCF8583) while addresses from &H100 to &H3FF are free space. At start the program shows the address where to write, through keys T1 and T2 the value in incremented or decremented. Through key T3 the address is accepted, then the value to write is selected through T1 and T2, as last press key T3 to write. Whenever a key is pressed, an acoustic signal is emitted. After the operation is terminated the selected address and the written data are shown one after the other. 05.06.2000 by Adriano Pedrielli (for K51 alone) (Original version in BASCOM 8051) 01.10.2003 by Graziano Gaiba Translation in uC/51. */ #include #include #include #define FALSE 0x00 // Boolean values #define TRUE 0xFF #define LF 0x0A #define CRET 0x0D /***************** Addresses list for Saa1064 ***********************/ #define Saa1064 0x38 // Slave address SAA1064 #define Wsaa1064 0x70 // Slave address SAA1064 in Write #define Rsaa1064 0x71 // Slave address SAA1064 in Read #define Ctb 0x00 // Ind. Control byte #define Dig1 0x01 // Ind. Digit 1 #define Dig2 0x02 // Ind. Digit 2 #define Dig3 0x03 // Ind. Digit 3 #define Dig4 0x04 // Ind. Digit 4 /************************************************************************/ #define Wee 0xA0 // Slave address 24cXX in Write #define Ree 0xA1 // Slave address 24cXX in Read // Inizialization od SAA1064 #define saa1064_init_length 0x06 // Inizialization sequence length const unsigned char saa1064_init[]={ Ctb, // Points control register 0x27, // = 0b00100111 // bit0 =1 dynamic mode // bit1 =1 digit 1+3 not blanked // bit2 =1 digit 2+4 not blanked // bit3 =0 no test segment // bit4 =0 no 3mA segment current // bit5 =1 6mA segment current // bit6 =0 no 12mA segment current // bit7 =0 indifferent 48, // writes 'i' 84, // writes 'n' 0, // writes DY3 off 0 // writes DY4 off }; // Codes to convert a figure from 0 to F in 7 segments coding const unsigned char cifra_7seg[]={0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F, 0x77,0x7C,0x39,0x5E,0x79,0x71}; // I2C BUS management globals bit unsigned char SDA @ 0xB6; // Pin SDA=P3.6 bit unsigned char SCL @ 0xB7; // Pin SCL=P3.7 // Management of keys and buzzer bit unsigned char T1 @ 0x90; // P1.0 bit unsigned char T2 @ 0x91; // P1.1 bit unsigned char T3 @ 0x92; // P1.2 bit unsigned char BUZ @ 0xB5; // P3.5 /********* General utilities and hardware section management ***********/ void iniser(unsigned long baud) /* Initialize 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, enable receiver TMOD&=0x00F; // Timer 1 in auto-reload TMOD|=0x020; TR1=0; // Stop TIMER 1 TH1=256-((2*11059200)/(384*baud)); // baud 14.7456 MHz PCON=PCON|0x080; // SetSMOD=1 for higher baud rates TR1=1; // Start TIMER 1 } void clrscr(void) /* Clear the screen of a generic console */ { unsigned char r; putc(CRET); for (r = 0 ; r < 25 ; r++) { putc(LF); // Sends 25 Line Feed } //endfor } void waitkey(void) /* Shows a message and waits for a key pressed */ { printf("hit a key to continue.."); getc(); puts(""); } void ritardo(unsigned int rit) /* Performs a software delay of rit milliseconds, calibrated on a CPU Clock 11 MHz. */ { unsigned int r,rit1ms; rit1ms=100; // Sperimental value for delay of 1 msec. with 80c32 do { for (r=0 ; r0); } void riti2c(void) /* Delay for I2CBUS synchronous communication. */ { #asm nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop #endasm } void starti2c(void) /* Start sequence for I2C BUS */ { SCL = 0; // Start sequence SDA = 1; riti2c(); SCL = 1; SDA = 0; riti2c(); SCL = 0; } void stopi2c(void) /* Stop sequence for I2C BUS */ { SCL = 0; // Stop sequence SDA = 0; riti2c(); SCL = 1; SDA = 1; riti2c(); SCL = 0; } void wri2c_bit(unsigned char i2cbit) /* Serializes bit D0 of i2cbit on I2C BUS */ { SCL = 0; // Set SDA and generates positive impulse on SCL SDA = i2cbit; riti2c(); SCL = 1; riti2c(); SCL = 0; } unsigned char rdi2c_bit(void) /* Deserializes a bit from I2C BUS and stores it in D0 of returned value*/ { unsigned char biti2c; SDA = 1; // Prevents conflicts on SDA acquisition SCL = 0; // Assures status of SCL riti2c(); SCL = 1; // Generates positive impulse on SCL and reads SDA biti2c = SDA; riti2c(); SCL = 0; return biti2c; } void wri2c_byte(unsigned char i2cbyte) /* Serializes byte i2cbyte to I2C BUS */ { unsigned char b; for (b = 1; b <= 8; b++) { if ((i2cbyte & 0x80) == 0) // Test and set bit b wri2c_bit(0); else wri2c_bit(1); i2cbyte = i2cbyte << 1; } } unsigned char rdi2c_byte(void) /* Deserializes byte from I2C BUS and stores it in returned value */ { unsigned char b,tmp; tmp = 0; for (b = 1; b <= 8; b++) { tmp = tmp << 1; tmp = tmp | rdi2c_bit(); // Reads and stores bit b } return tmp; } unsigned char wr_i2c(unsigned char i2csla,unsigned char i2cadd,unsigned char i2cdat) /* Writes byte i2cdat to address i2caddr of I2C BUS device with slave address in i2csla. Returns boolean flag indicating result of operation: 0=OK,1=error. */ { unsigned char i2cris; i2cris = 0; // Set OK as result starti2c(); // Start sequence wri2c_byte(i2csla); // Slave address+W i2cris = i2cris | rdi2c_bit(); // Check ACK on slave address+W wri2c_byte(i2cadd); // Address i2cris = i2cris | rdi2c_bit(); // Check ACK on address wri2c_byte(i2cdat); // Data i2cris = i2cris | rdi2c_bit(); // Check ACK on data stopi2c(); // Stop sequence return i2cris; // Result of operation } unsigned char rd_i2c(unsigned char i2csla,unsigned char i2cadd,unsigned char *i2cdat) /* Reads byte and returns it as result from address i2caddr of I2C BUS device with slave address in i2csla. Returns boolean flag indicating result of operation: 0=OK,1=error. */ { unsigned char i2cris; i2cris = 0; // Set OK as result starti2c(); // Start sequence wri2c_byte(i2csla); // Slave address+W i2cris = i2cris | rdi2c_bit(); // Check ACK on slave address+W wri2c_byte(i2cadd); // Address i2cris = i2cris | rdi2c_bit(); // Check ACK on address starti2c(); // Start sequence wri2c_byte(i2csla | 0x01); // Slave address+R i2cris = i2cris | rdi2c_bit(); // Check ACK on slave address+R *i2cdat = rdi2c_byte(); // Reads data stopi2c(); // Stop sequence return i2cris; // Result of operation } // Send to indicated slave address (as first parameter) number of bytes indicated // (as third parameter) stored from address indicated (as second parameter). // If number of bytes is 0, it does nothing. // Returns boolean flag indicating result of operation: // 0=OK,1=error. unsigned char i2c_invia(unsigned char slave, unsigned char *dati, unsigned char ndati) { unsigned char i2cris, i; if(! ndati) // If ndati is zero, exits return 0; i2cris=0; starti2c(); // Start sequence wri2c_byte(slave); // Slave address+W i2cris|=rdi2c_bit(); // Check ACK on slave address+W i=0; while(ndati--) // Send ndati bytes { wri2c_byte(dati[i++]); i2cris|=rdi2c_bit(); // Check ACK } stopi2c(); // Stop sequence return i2cris; // Return result } // Send to indicated slave address (as first parameter) number of bytes indicated // (as third parameter) stored from address indicated (as second parameter),then // expects to receive as answer indicated number of bytes (fourth parameter) and // stores them starting from address previously specified in second parameter. // Returns boolean flag indicating result of operation: // 0=OK,1=error. unsigned char i2c_ricevi(unsigned char slave, unsigned char *dati, unsigned char ndati_out, unsigned char ndati_in) { unsigned char i2cris, i; if((! ndati_in) && (! ndati_out)) // Se ndati_in e ndati_out sono zero,esce return 0; i2cris=0; // Invia i dati starti2c(); // Start sequencet wri2c_byte(slave); // Slave address+W i2cris|=rdi2c_bit(); // Check ACK on slave address+W i=0; while(ndati_out--) // Send ndati_out bytes { wri2c_byte(dati[i++]); // Send data i2cris|=rdi2c_bit(); // Check ACK } // Riceve i dati starti2c(); wri2c_byte(slave | 0x01); // Slave address+W i2cris|=rdi2c_bit(); // Check ACK on slave address+R i=0; while(ndati_in--) // Reads ndati_in bytes { dati[i++]=rdi2c_byte(); // Get data if(ndati_in) { wri2c_bit(0); // Send ACK } else { wri2c_bit(1); // Last data read, send NACK } } stopi2c(); // Stop sequence return i2cris; // Return the result } void demo_init(void) { unsigned char i; // Wait SAA1064 to turn on do { starti2c(); wri2c_byte(Rsaa1064); rdi2c_bit(); i = rdi2c_byte(); wri2c_byte(1); // Not Acknowledge stopi2c(); } while(i); // Send SAA1064 initialization sequence i2c_invia(Wsaa1064, saa1064_init, saa1064_init_length); } // Converts a value from 0 to 255 in two 4 bit hexadecimal figures void cifre(unsigned char v, unsigned char *c1, unsigned char *c2) { *c1=(v & 0xf0) >> 4; *c2=v & 0x0f; } /******** Converts a figure in range from 0 to F in 7 segments ******** This procedure converts a figure in range from 0 to F in 7 segments format, if value is greater than F the display is off. Parameters: Input : value in the range from 0 to F Outout : value in 7 segments format. ************************************************************************/ unsigned char digit(unsigned char n) { if(n < 16) { return cifra_7seg[n]; // reads value from table } else { return 0; // If value greater than 15 turn off display } } /************************* Visualizes a byte in HEX *********************** This procedure visualizes hexadecimal value of a byte in the two rightmost displays. E.g.: 255= FFH, 32= 20H etc. Parameters: Input: number to show in hexadecimal Output: nothing **************************************************************************/ void vis_byte(unsigned char t) { unsigned char h, l; cifre(t, &h, &l); // decomposition of value of t in 2 nibbles starti2c(); // Start sequence wri2c_byte(Wsaa1064); // Slave address rdi2c_bit(); // Check ACK on slave address+R wri2c_byte(Dig1); // First digit rdi2c_bit(); wri2c_byte(0); // Turn OFF DY1 rdi2c_bit(); wri2c_byte(0); // Turn OFF DY2 rdi2c_bit(); wri2c_byte(digit(h)); // Transforms in "7 segments" and send to DY3 rdi2c_bit(); wri2c_byte(digit(l)); // Transforms in "7 segments" and send to DY4 rdi2c_bit(); stopi2c(); // Stop sequence } /************************ Visualizes a word in HEX ************************ This procedure visualizes hexadecimal value of a word. The first two displays show (DY1 e DY2) high byte, while last two (DY3 e DY4) show low byte. E.g.s: 65535= FFFFH, 257= 101H etc. Parameters: Input: number to show in hexadecimal Output: nothing **************************************************************************/ void vis_word(unsigned int t) { unsigned char h, l; // decomposition of high byte of t in 2 nibbles cifre(t>>8, &h, &l); starti2c(); // Start sequence wri2c_byte(Wsaa1064); // Slave address rdi2c_bit(); // Check ACK on slave address+R wri2c_byte(Dig1); // First digit rdi2c_bit(); wri2c_byte(digit(h)); // Write in DY1 most significant nibble rdi2c_bit(); wri2c_byte(digit(l)); // Write in DY2 next nibble rdi2c_bit(); // decomposition of low byte of t in 2 nibbles cifre(t & 0xff, &h, &l); wri2c_byte(digit(h)); // Write in DY3 most significant nibble rdi2c_bit(); wri2c_byte(digit(l)); // Write in DY4 next nibble rdi2c_bit(); stopi2c(); // Stop sequence } // Activate buzzer for specified time, in milliseconds void buzzer(unsigned int t) { BUZ=0; ritardo(t); BUZ=1; } // Performs debouncing on T1 and returns its status: // 1 if pressed // 0 if not pressed unsigned char debounceT1(void) { unsigned char status; unsigned int steps; if(T1) // If T1 not pressed... { return 0; // ...return it is not pressed } else { status=1; // Indicates that it is pressed steps=20; // Check for 20 times while(status) { if(T1) // If T1 not pressed... { status=0; // ...exit loop } if(! steps--) // If steps controls made... { break; // ...exit } ritardo(5); // Delay between controls } return status; // Returns status of T1 } } // Performs debouncing on T2 and returns its status: // 1 if pressed // 0 if not pressed unsigned char debounceT2(void) { unsigned char status; unsigned int steps; if(T2) // If T2 not pressed... { return 0; // ...return it is not pressed } else { status=1; // Indicates that it is pressed steps=20; // Check for 20 times while(status) { if(T2) // If T2 not pressed... { status=0; // ...exit loop } if(! steps--) // If steps controls made... { break; // ...exit } ritardo(5); // Delay between controls } return status; // Restituisce lo stato di T2 } } void main(void) { unsigned char v; unsigned int add; ritardo(2); iniser(19200); TI=0; RI=0; // Comment next lines if using serial line in polling (SIOTYPE=p or k) ES=1; // Enable interrupt serial port EA=1; // Enable all interrupts clrscr(); demo_init(); // Peripherals initialization add=0x400; // EEPROM base address v=0; // Data to write while(T3) // Loop until T3 pressed { vis_word(add); // Show current address if(debounceT1()) // If T1 pressed { add++; // Increment address buzzer(50); // Buzzer beeps for 50 milliseconds } if(debounceT2()) // If T2 pressed { add--; // Decrement address buzzer(50); // Buzzer beeps for 50 milliseconds } } while(T3==0) // Attende il rilascio di T3 ; while(T3) // Loop until T3 pressed { vis_byte(v); // Show current data if(debounceT1()) // If T1 pressed { v++; // Increment data buzzer(50); // Buzzer beeps for 50 milliseconds } if(debounceT2()) // If T2 pressed { v--; // Decrement data buzzer(50); // Buzzer beeps for 50 milliseconds } } while(T3==0) // Wait for T3 released ; wr_i2c(((add & 0x0700) >> 7) | Wee, add & 0xff, v); // Write to slave address of EEPROM, // plus specified address data byte in v while(TRUE) // Visualizes value written and address // where it has been written alternatively { vis_byte(v); ritardo(1000); vis_word(add); ritardo(1000); } }