/* **************************************************************************** SourceBoost C Code Processor: PIC16F877A Filename: I2C_Master_1.c Author: RSABear Date: 8 January 2008 Version: 1.00 Description: Use Hardware UART - RS232 Use Hardware MSSP - I2C I2C Master Code ****************************************************************************** Hardware: LED on RA2 - PIN 2 4.0MHz Crystal on PINs 13 & 14 100K Pull-up Resistor from PIN1 to Vdd Maxim DS275 Chip RX-Out - PIN 26 TX-In - PIN 25 SLAVE 16F887A - Address 0xF0 PIN 23 - SDA PIN 18 - SCL SLAVE 24FC512 - Address 0xA0 PIN 23 - SDA PIN 18 - SCL Revision History: 10 January 2008 - Ver 1.00 Modified: **************************************************************************** */ #include <system.h> #include <stdlib.h> #include <string.h> #include <i2c_driver.h> #include <icd2.h> // Set the 16F877A device configuration bits - Page // External 4.0Mhz Crystal Oscillator #pragma DATA _CONFIG, _CPD_OFF & _DEBUG_ON & _PWRTE_ON & _LVP_OFF & _BODEN_ON & _PWRTE_ON & _WDT_OFF & _XT_OSC // 4.0 Mhz #pragma CLOCK_FREQ 4000000 #define FOSC 4000000 #define spBAUD 9600 #define fSPBCLK (FOSC) // UART Baud rate generator clock (high speed) // #define fSPBCLK (FOSC / 4) // UART Baud rate generator clock (low speed) #define SPBRG_VAL ((fSPBCLK / (spBAUD * 16L)) - 1L) // bit_time FOSC / 4 / BAUDRATE #define bit_time 104 // 9600 baud at 4MHz // Hardware dependant defines RC6 & 7 #define RX_PIN 7 #define TX_PIN 6 // **** START OF DEFAULTS USED FOR HARDWARE USART **** //////////////////////////////////////////////////////////////////////////// // USART hardwareware implementation template argument values //////////////////////////////////////////////////////////////////////////// // variables cannot be passed as template arguments. The following constants map to // the PIC registers and PIC's USART register locations. These constants are // then used by the templated functions. When moving between PIC families the // register mapping must be changed to map to the corresponding physical register // // PIC16F877A defaults for hardware USART support // DS30292C-page 95 (TX) & DS30292C-page 104 (RX) #define TX_PORT PORTC #define TX_TRIS TRISC #define TX_BIT TX_PIN #define RX_PORT PORTC #define RX_TRIS TRISC #define RX_BIT RX_PIN #define e_SPBRG SPBRG #define e_RCREG RCREG #define e_TXREG TXREG #define e_TXSTA TXSTA #define e_RCSTA RCSTA #define e_TXIF_PIR PIR1 #define e_RCIF_PIR PIR1 #define e_TXIF_BIT TXIF #define e_RCIF_BIT RCIF #define MODE (USART_reset_wdt | USART_HW) // **** END OF DEFAULTS USED FOR HARDWARE USART **** #include "rs232_driver.h" //////////////////////////////////////////////////////////////////////////// // i2c hardwareware implementation template arguments //////////////////////////////////////////////////////////////////////////// #define i2c_ARGS 3, e_MSSP_PORT, e_MSSP_TRIS, 4, e_MSSP_PORT, e_MSSP_TRIS, e_SSPCON1, e_SSPCON2, \ e_SSPSTAT, e_SSPBUF, e_SSPIF_BIT, e_SSPIF_PIR, \ e_BCLIF_BIT, e_BCLIF_PIR, 7, e_SSPADD, (i2c_reset_wdt | i2c_SMP |i2c_HW) // variables cannot be passed as template arguments. The following constants map to // the PIC registers and PIC's i2c register locations. These constants are // then used by the templated functions. #define e_MSSP_PORT PORTC #define e_MSSP_TRIS TRISC #define e_SSPCON1 SSPCON #define e_SSPCON2 SSPCON2 #define e_SSPSTAT SSPSTAT #define e_SSPADD SSPADD #define e_SSPBUF SSPBUF #define e_SSPIF_PIR PIR1 #define e_BCLIF_PIR PIR2 #define e_SSPIF_BIT SSPIF #define e_BCLIF_BIT BCLIF //////////////////////////////////////////////////////////////////////////// // I2C Device constants //////////////////////////////////////////////////////////////////////////// // define External I2C slave (Hardware) addresses #define xff_slave 0x06 // Base address of 16F877A device #define xee_slave 0xA0 // Base address of the EEPROM //////////////////////////////////////////////////////////////////////////// // Read from the External EEPROM //////////////////////////////////////////////////////////////////////////// // s is a pointer to the destination buffer to data read from the EEPROM // HW_address is the hardware address of the i2c device // ic2_addr is the target internal address within the External EEPROM // count is the number of bytes to be read starting at i2c_addr void read_XEE(char *s, char HW_address, unsigned short i2c_addr, unsigned short count) { short i; i2c_start(); i2c_write(HW_address); // send XEE i2c address i2c_write(i2c_addr >> 8); // send XEE internal HIGH address i2c_write((char) i2c_addr & 0x00ff); // send XEE internal LOW address i2c_restart(); // send i2c_restart // sending XEE read command via i2c_write i2c_write(HW_address | 0x01); // send device address + RD to I2C device // XEE read loop for (i=0;i<count-1;i++) *s++ = i2c_read(0); *s++ = i2c_read(1); *s = 0; i2c_stop(); } //////////////////////////////////////////////////////////////////////////// // Write to the External EEPROM //////////////////////////////////////////////////////////////////////////// // s is a pointer to the string to be written to the EEPROM // HW_address is the hardware address of the i2c device // ic2_addr is the target internal address within the External EEPROM // count is the number of bytes to be written starting at i2c_addr void write_XEE(char *s, char HW_address, unsigned short i2c_addr, unsigned short count) { short i; i2c_start(); i2c_write(HW_address); // send XEE i2c address i2c_write(i2c_addr >> 8); // send XEE internal HIGH address i2c_write((char) i2c_addr & 0x00ff); // send XEE internal LOW address // XEE write loop for (i=0;i<count;i++) i2c_write(*s++); i2c_stop(); } //////////////////////////////////////////////////////////////////////////// // Read from the External 16F877A device //////////////////////////////////////////////////////////////////////////// // s is a pointer to the destination buffer to data read from the EEPROM // HW_address is the hardware address of the i2c device // ic2_addr is the target internal address within the External EEPROM // count is the number of bytes to be read starting at i2c_addr void read_XFF(char *s, char HW_address, unsigned short i2c_addr, unsigned short count) { short i; // First write the Address for the memory location to read to the device HW_address <<= 1; // Shift the 7-bit address Left by 1 HW_address &= 0xFE; // LSB = 0 for address/data write operation i2c_start(); i2c_write(HW_address); // send XEE i2c address i2c_write(i2c_addr >> 8); // send XEE internal HIGH address i2c_write((char) i2c_addr & 0x00ff); // send XEE internal LOW address i2c_restart(); // send i2c_restart // sending XEE read command via i2c_write i2c_write(HW_address | 0x01); // send device address + RD to I2C device // XEE read loop for (i=0;i<count-1;i++) *s++ = i2c_read(0); *s++ = i2c_read(1); *s = 0; i2c_stop(); } //////////////////////////////////////////////////////////////////////////// // Write to the External 16F877A device //////////////////////////////////////////////////////////////////////////// // s is a pointer to the string to be written to the EEPROM // HW_address is the hardware address of the i2c device // ic2_addr is the target internal address within the External device // count is the number of bytes to be written starting at i2c_addr void write_XFF(char *s, char HW_address, unsigned short i2c_addr, unsigned short count) { short i; HW_address <<= 0x01; // Shift the 7-bit address Left by 1 HW_address &= 0xFE; // LSB = 0 for address/data write operation i2c_start(); i2c_write(HW_address); // send XFF i2c address i2c_write(i2c_addr >> 8); // send XFF internal HIGH address i2c_write((char) i2c_addr & 0x00ff); // send XFF internal LOW address // XFF write loop for (i=0;i<count;i++) i2c_write(*s++); i2c_stop(); } void writes(char *source) { while (*source != 0) // wait until tx register is empty putc(*source++); } // Declare some logic defintions for later use #define SET 1 #define CLEAR 0 #define RESET 0 #define TRUE 1 #define FALSE 0 #define ZERO 0 char buffer[32]; char value[32]; char *ee_mesg = "i2c Test String"; char *ff_mesg = "i2c Test String"; char *s1; char *str_value; char i, val_h, val_l; unsigned int int_value; unsigned short i2c_addr; // used for internal addressing for the target I2C device char i_counter, c_data; void main() { char i_counter; adcon0 = 0x00; // Switch the ADC Unit Off ccp1con = 0x00; // Switch the comparator unit off trisa = 0x00; porta = 0x00; // User entertainment - show the RESET/REBOOT for ( i_counter = 1; i_counter < 20; i_counter++ ) { porta.0 = 0; delay_ms(50); porta.0 = 1; delay_ms(50); } clear_bit(porta , 0); // RS232 Communications uart_init(1,SPBRG_VAL); // set high speed divisor mode and divisor value - 9600 puts("PIC16F877A I2C Master"); delay_ms(100); // I2C Communications //#define I2C_divisor 0x7E #define I2C_divisor 0x09 //I2C_divisor ((4000000/100000)/4) - 1) = 9 = 0b00001001 // set the divisor for the I2C clock // for software I2C emulation this can be any value (such as 1) i2c_init(I2C_divisor); /* /////////////////////////////////////////////////////////////////////////// // Write/Read test of the EEPROM followed by the Microchip 16F877A device ////////////////////////////////////////////////////////////////////////// // Write to address 0x0000 of the EEPROM i2c_addr = 0x0000; puts("ee ->"); puts(ee_mesg); write_XEE(ee_mesg, xee_slave, i2c_addr, strlen(ee_mesg)+1); // The External EEPROM requires a delay to finish // programming the flash before it can be accessed again delay_ms(50); // Read 16 bytes from address 0x0000 in External EEPROM i2c_addr = 0x0000; s1 = &buffer[0]; // point s1 to the work buffer read_XEE(s1, xee_slave, i2c_addr, 16); puts("ee <-"); puts(s1); */ //***************************************************************************** // Write to the 16F877A, 1 bit, slave address 0x06 i2c_addr = 0x0000; puts("ff ->"); puts(ff_mesg); write_XFF(ff_mesg, xff_slave, i2c_addr, strlen(ff_mesg)+1); // The External device requires a delay to finish // programming the flash before it can be accessed again delay_ms(50); puts("ff <-"); // Read 16 bytes from address 0x0000 of the 16F877A i2c_addr = 0x0000; s1 = &buffer[0]; // point s1 to the work buffer read_XFF(s1, xff_slave, i2c_addr, 16); puts(s1); while(TRUE) { // For some strange reason toggle_bit() does not work... delay_ms(200); porta.0 = 0; delay_ms(200); porta.0 = 1; // Not required // if (kbhit()) // { // putc(getc()); // Get the input character from the UART // } // End Keyboard Hit } // End While Loop } // End main()
Copyright © 2006 SourceBoost Technologies