'****************************************************************** '* Name : k51ppoe.bas * '* Author : Graziano GAIBA * '* Date : 30/06/04 * '* Version : 1.1 * '* Board : GMM 876 + GMB HR84 + K51-AVR * '* Language : PIC BASIC Standard Ver. 1.45 * '* Society : Copyright (c) 2004 grifo(r) ITALIAN Technology * '* : All Rights Reserved * '* : Tel.: +39 051 892052 Fax: +39 051 893661 * '* : http://www.grifo.com http://www.grifo.it * '* : E-mail: grifo@grifo.it * '****************************************************************** ' ' This demo allows to drive an I2C BUS peripheral on board of K51-AVR, PCF8574, ' through mini-BLOCK module GMB HR84 and grifo(r) mini module. ' PCF 8574 is an I/O expander that allows to drive 8 TTL digital lines, both as ' input and as output, all the operations of read and write are performed ' through synchronous serial interface I2C BUS. ' This demo activates in sequence one line at a time, creating the classic bit ' shift to the right and to the left, and writes 'out' on the 7 segments ' display of K51-AVR, near the characters 'out'. ' ' For serial communication, the hardware serial port management code ' taken from example program Usart.bas is used, opportunely ' modified. ' ' ' ********************************************************************* ' * Definitions and Constants * ' ********************************************************************* ' ' PIC registers symbol INDF = 0 symbol FSR = $04 ' I/O Ports symbol PORTA = $05 symbol TRISA = $85 ' bank 1 symbol PORTB = $06 symbol TRISB = $86 ' bank 1 symbol PORTC = $07 symbol TRISC = $87 ' bank 1 ' I2C BUS symbol SSPCON2= $91 ' bank 1 symbol SSPBUF = $13 symbol SSPADD = $93 ' bank 1 symbol SSPCON1= $14 symbol SSPSTAT= $94 ' bank 1 ' symbol OPTION_REG = $81 ' bank 1 ' ' Registers used by hardware serial port management taken from ' demo Usart.bas del PIC Basic standard. ' USART registers Symbol PIR1 = $0C ' Peripheral Interrupt Flag register Symbol RCSTA = $18 ' Reception status and control register Symbol TXREG = $19 ' Data to send Symbol RCREG = $1A ' Data received Symbol TXSTA = $98 ' Transmission status and control register Symbol SPBRG = $99 ' Baud Rate Generator register ' ' ' Slave address and other constants ' Symbol Saa1064 = $38 ' Slave address SAA1064 Symbol Wsaa1064 = $70 ' Slave address SAA1064 in Write Symbol Rsaa1064 = $71 ' Slave address SAA1064 in Read ' ***************** Addresses of Saa1064 registers ********************* Symbol Ctb = $0 ' Control byte address Symbol Dig1 = $1 ' Digit 1 address Symbol Dig2 = $2 ' Digit 2 address Symbol Dig3 = $3 ' Digit 3 address Symbol Dig4 = $4 ' Digit 4 address ' ' ********************************************************************** ' 'Symbol Pcf8574 = $3C ' Slave address PCF8574A 'Symbol Wpcf8574 = $78 ' Slave address PCF8574A in Write 'Symbol Rpcf8574 = $79 ' Slave address PCF8574A in Read Symbol Pcf8574 = $24 ' Slave address PCF8574P Symbol Wpcf8574 = $48 ' Slave address PCF8574P in Write Symbol Rpcf8574 = $49 ' Slave address PCF8574P in Read ' ' ' ********************************************************************* ' * Variables used by the program * ' ********************************************************************* ' ' ' Used by USART SYMBOL UsartST = B0 ' USART status SYMBOL UsartOut = B1 ' Character to send symbol UsartIn = B2 ' Character received ' Value to be printed symbol Valore = B3 ' Generic use SYMBOL i = B4 SYMBOL c = B5 symbol z = B6 ' Hexadecimal data and addresses for I2C BUS symbol Slave_Address = B7 symbol Indirizzo = B8 symbol DatoIn = B9 symbol DatoOut = B10 symbol Dato = B11 ' Used to input an hexadecimal value symbol ValoreHex = B12 ' Mask used for bit shift symbol Maschera = B13 ' ' ' ********************************************************************* ' * Programma main * ' ********************************************************************* ' Main: gosub Module_init ' Initialisation for i=0 to 32 lookup i,("Shifts bits of PCF 8574 on CN1..."),usartout gosub charout next i gosub k51_init ' Initialisation of K51-AVR ' Loop forever Loop: maschera = $01 for i = 1 to 7 ' Generates I2CBUS Start... gosub i2cbusstart '...and waits for it to complete gosub i2cbussynch ' Send slave address datoout = Wpcf8574 gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Send address where to write data datoout = maschera ^ $FF gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Send stop gosub i2cbusstop '...and waits for it to complete gosub i2cbussynch maschera = maschera * 2 pause 2000 next i for i = 1 to 7 ' Generates I2CBUS Start... gosub i2cbusstart '...and waits for it to complete gosub i2cbussynch ' Send slave address datoout = Wpcf8574 gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Send address where to write data datoout = maschera ^ $FF gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Send stop gosub i2cbusstop '...and waits for it to complete gosub i2cbussynch maschera = maschera / 2 pause 2000 next i ' Loop forever goto loop end ' ' ' ********************************************************************* ' * Program end * ' ********************************************************************* ' ' ' Initialisation of GMM 876 Module_init: ' ' Initialise USART for 19200 Baud Poke SPBRG,64 ' Set baud rate to 19200 Poke RCSTA,%10010000 ' Enable serial port and continuous reception Poke TXSTA,%00100100 ' Enable transmission, asynchronous mode ' and high baud rate ' ' Initialisation for I2C BUS ' Configures RC3 and RC4 as inputs peek trisc, B0 bit3 = 1 bit4 = 1 poke trisc, B0 ' Activates module SSP in master I2C BUS mode, clock 50 kHz poke sspadd, $63 poke sspcon1, $28 ' Switch back to bank 0 before exiting from asm 'ASM 'ENDASM pause 500 return ' ' ' Initialisation of K51-AVR peripherals K51_init: ' ' Configuration of 7 segments display controller SAA 1064 ' ' Generates I2CBUS Start... gosub i2cbusstart '...and waits for it to complete gosub i2cbussynch ' ' Send slave address of SAA 1064 datoout = rsaa1064 gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' ' Reads status register of SAA 1064 gosub i2cbusget ' Send NOT acknowledge... peek sspcon2, B0 bit5 = 1 bit4 = 1 poke sspcon2, B0 '...and waits for it to complete gosub i2cbussynch ' ' Send stop gosub i2cbusstop '...and waits for it to complete gosub i2cbussynch ' if datoin <> 0 then k51_init ' Generates I2CBUS Start... gosub i2cbusstart '...and waits for it to complete gosub i2cbussynch ' ' Send Slave Address datoout = Wsaa1064 gosub i2cbussend ' ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' ' Point to control register datoout = Ctb gosub i2cbussend ' ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' datoout = %00100111 ' 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 gosub i2cbussend ' ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' datoout = 92 ' Write 'o' gosub i2cbussend ' ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' datoout = 28 ' Write 'u' gosub i2cbussend ' ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' datoout = 120 ' Write 't' gosub i2cbussend ' ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' datoout = 0 gosub i2cbussend ' DY4 off ' ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' ' Send stop gosub i2cbusstop '...and waits for it to complete gosub i2cbussynch return ' ' ' Write one byte to the address specified I2CBUSWrite: ' Genera I2CBUS Start... gosub i2cbusstart '...and waits for it to complete gosub i2cbussynch ' Send Slave Address datoout = slave_address gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Send address where to write data datoout = indirizzo gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Send data to write datoout = dato gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Send stop gosub i2cbusstop '...and waits for it to complete gosub i2cbussynch ' Esce return ' ' ' Read one byte from the specified address I2CBUSRead: ' Send I2CBUS Start... gosub i2cbusstart '...and waits for it to complete gosub i2cbussynch ' Send Slave Address datoout = slave_address gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Send address from where to read data datoout = indirizzo gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Send repeated I2CBUS Start... gosub i2cbusrepstart '...and waits for it to complete gosub i2cbussynch ' Send Slave Address for reading datoout = slave_address | $01 gosub i2cbussend ' If acknowledge is not received, print error message peek sspcon2, B0 if bit6 = 1 then notack ' Read data into variable DatoIn gosub i2cbusget ' Put data just read into variable Dato dato = datoin ' Send NOT acknowledge... peek sspcon2, B0 bit5 = 1 bit4 = 1 poke sspcon2, B0 '...and waits for it to complete gosub i2cbussynch ' Send stop gosub i2cbusstop '...and waits for it to complete gosub i2cbussynch ' Exit I2CBUSEsci: return ' ' ' Indicates that acknowledge has not been received NotACK: for i = 0 to 23 lookup i,("Acknowledge not received"), usartout gosub charout next i return ' ' ' Send I2C BUS start I2CBUSStart: peek sspcon2, B0 bit0 = 1 poke sspcon2, B0 return ' ' ' Send repeated I2C BUS start I2CBUSRepStart: peek sspcon2, B0 bit1 = 1 poke sspcon2, B0 return ' ' ' Send I2C BUS stop I2CBUSStop: peek sspcon2, B0 bit2 = 1 poke sspcon2, B0 return ' ' ' Send the value contained in DatoOut to I2C BUS I2CBUSSend: poke sspbuf, datoout gosub i2cbussynch return ' ' ' Read a data from I2C BUS and return it in DataIn I2CBUSGet: ' Enable receiver peek sspcon2, B0 bit3=1 poke sspcon2, B0 I2CBusGetLoop: peek sspcon2, B0 if bit3 = 1 then I2CBusGetLoop peek sspbuf, datoin return ' ' ' Waits for I2C to complete last requested operation I2CBUSSynch: peek pir1, B0 if bit3 = 0 then I2CBUSSynch bit3 = 0 poke pir1, B0 return ' ' ' Transforms hexadecimal value in variable Valore in ASCII ' characters and send them to the serial port. ' Valore must be in the range between 0 and 0FFh. StampaHex: usartout = valore / 16 gosub hexdecode gosub charout StampaNibbleHex: usartout = valore & $0F gosub hexdecode gosub charout return ' HexDecode: Lookup usartout,("0123456789ABCDEF"),usartout return ' HexEncode: lookDown usartin,("0123456789abcdef"),usartin return ' ' ' Send new line and carriage return control characters NLCR: usartout = 10 ' New Line gosub charout CR: usartout = 13 ' Carriage Return gosub charout return ' ' ' Prints two spaces DueSpazi: usartout = " " ' Space gosub charout gosub charout return ' ' ' Go to new line, print "Press a key..." then a new line again TastoPerUscire: gosub nlcr for z = 0 to 13 lookup z, ("Press a key..."),usartout gosub charout next z gosub nlcr return ' ' ' Ask for an hexadecimal value and return it in variable Dato InputDato: for z = 0 to 11 lookup z,("Data (Hex): "), usartout gosub charout next z gosub inputhex dato = valorehex return ' ' ' Ask for an hexadecimal address and return it in variable Slave_Address InputSlaveAddress: for z = 0 to 20 lookup z,("Slave Address (Hex): "), usartout gosub charout next z gosub inputhex slave_address = valorehex return ' ' ' Ask for an hexadecimal address and return it in variable Indirizzo InputIndirizzo: for z = 0 to 14 lookup z,("Address (Hex): "), usartout gosub charout next z gosub inputhex indirizzo = valorehex return ' ' ' Input an hexadecimal value in the range from 00 to FF then new line InputHex: gosub charin if usartin = 0 then InputHex usartout = usartin gosub charout usartin = usartin | $20 gosub hexencode valorehex = usartin * 16 InputHex2: gosub charin if usartin = 0 then InputHex2 usartout = usartin gosub charout usartin = usartin | $20 gosub hexencode valorehex = valorehex + usartin gosub nlcr return ' ' ' Subroutine that sends a character to USART transmitter ' (blocking) CharOut: Peek pir1,UsartST ' Read the Flag in UsartST = B0 If Bit4 = 0 Then charout ' Wait for transmission register to be ' empty Poke TXREG,Usartout ' Put character to send in transmission ' register Return ' Return to the caller ' ' ' Subroutine that gets a character from USART receiver ' (non blocking) CharIn: UsartIn = 0 ' Preset to no character received Peek PIR1,Usartst ' Read the Flag in UsartST = B0 If Bit5 = 0 Then ciret ' If reception flag is 0, exit Peek RCREG,UsartIn ' Or put the character received into ' in UsartIn = B1 ciret: Return ' Return to the caller