//PIC16F877A MPLAB XC8
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
// End of configuration
#include <xc.h>
#define _XTAL_FREQ 20000000
#define Baud_rate 9600
#define SLAVE_ADDRESS 0xA0
#define POINTER_ADDRESS 0x00
#define error 1
//Initializing UART module for PIC16F877A
void Initialize_UART(void)
{
TRISC6 = 0; // TX Pin set as output
TRISC7 = 1; // RX Pin set as input
SPBRG = ((_XTAL_FREQ/16)/Baud_rate) - 1;
BRGH = 1; // for high baud_rate
SYNC = 0; // Asynchronous
SPEN = 1; // Enable serial port pins
TXEN = 1; // enable transmission
CREN = 1; // enable reception
TX9 = 0; // 8-bit reception selected
RX9 = 0; // 8-bit reception mode selected
}
//Function to send one byte of date to UART
void UART_send_char(char c)
{
while(!TXIF); // Wait till the transmitter register becomes empty
TXREG = c; //load the char to be transmitted into transmit reg
}
// Sends null-terminated ASCII string
void UART_send_string(char* p)
{
char c;
while((c = *p) != '\0')
{
UART_send_char(c);
p++;
}
}
void i2c_init(void)
{
TRISCbits.TRISC3 = 1; // SCL as input
TRISCbits.TRISC4 = 1; // SDA as input
SSPCONbits.SSPM = 0b1000; // Master mode using SSPADD as baud control
SSPADD = 49; //100kHz clock @ 20MHz Fosc
SSPCONbits.SSPEN = 1; //enable SSP
}
// Send an I2C START
void i2c_start(void)
{
SEN = 1;
while (SEN);
}
// Send an I2C STOP
void i2c_stop(void)
{
PEN = 1;
while (PEN);
}
// Send an I2C REPEATED START
void i2c_restart(void)
{
RSEN = 1;
while (RSEN);
}
//Send one byte. Return ACK and NAK for I2C Bus
__bit i2c_SendByte(unsigned char dat)
{
SSPBUF = dat;
while (R_W);
return ACKSTAT;
}
//Receive one byte. flag=0 to send ACK, or 1 to send NAK
unsigned char i2c_ReceiveByte(unsigned char flag)
{
RCEN = 1;
ACKDT = (__bit)flag;
while (RCEN);
ACKEN = 1;
while (ACKEN);
return SSPBUF;
}
//Return 0 if no error
unsigned char WriteSlave(unsigned char slave_address, unsigned char pointer_address, unsigned char size, unsigned char * ptr)
{
i2c_start(); // Send a start
//send the I2C slave address low R/W bit
if (i2c_SendByte(slave_address & 0xfe))
{
i2c_stop();
return error; //return error
}
//send the device register address
if (i2c_SendByte(pointer_address))
{
i2c_stop();
return error;
}
for (; size>0; --size)
{
if (i2c_SendByte(*ptr++))
{
i2c_stop();
return error;
}
}
i2c_stop();
return 0; //no error
}
unsigned char ReadSlave(unsigned char slave_address, unsigned char pointer_address, unsigned char size, unsigned char * ptr)
{
i2c_start();
//Send the I2C slave address, R/W bit high)
if (i2c_SendByte(slave_address | 0x01))
{
i2c_stop();
return error;
}
for (; size>0; --size)
{
unsigned char flag = (size == 1);
*ptr++ = i2c_ReceiveByte(flag);
}
i2c_stop();
return 0; //Return 0 if all OK, 1 if bus error
}
unsigned char BinToAsc(unsigned char BinValue)
{
BinValue &= 0x0F;
if(BinValue > 9) BinValue += 7;
return(BinValue + '0');
}
void main(void)
{
unsigned char SlaveSend, SlaveRead;
unsigned char Slave_data[] = { 0x01,0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
unsigned char Slave_Read_data[8];
Initialize_UART(); //Initialize UART module
SlaveSend = WriteSlave(SLAVE_ADDRESS, POINTER_ADDRESS, 8, Slave_data);
SlaveRead = ReadSlave(SLAVE_ADDRESS, POINTER_ADDRESS, 8, Slave_Read_data);
while (1);
}