|
|
View previous topic :: View next topic |
Author |
Message |
funmix
Joined: 27 Mar 2007 Posts: 33
|
I2C not working in 18F4520[error] |
Posted: Wed Apr 04, 2007 6:45 am |
|
|
The below program work fine for 18F4520 master with 16F877A slave.
When i replace 16F877A with 18F4520 as slave, i got the i2c_read() value display in hyperterminal is FFFF, no matter what value i enter, master display FFFF.
p/s: I have re-configure those special function register value for different chips
Appreciate if someone can help to solve this.
This code is taken from code library i2c master and slave multibyte
Code: |
//master.c
#include <18F4520.H>
// 10-bit A/D conversion
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=20000000)
#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7,brgh1ok)
#include <input.c>
#define EEPROM_SDA PIN_C4
#define EEPROM_SCL PIN_C3
#define SLAVE_ADDRESS 0x02
#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL, FORCE_HW)
void
initI2C()
{
output_float(EEPROM_SCL);
output_float(EEPROM_SDA);
}
void
writeI2C(INT16 word)
{
i2c_start();
delay_us(16);
i2c_write(SLAVE_ADDRESS); /* Device Address */
delay_us(16);
i2c_write(word & 0x00ff);
delay_us(16);
i2c_write((word & 0xff00) >> 8);
delay_us(16);
i2c_stop();
}
INT16
readI2C()
{
BYTE b1=0, b2=0;
i2c_start(); // restart condition
i2c_write(SLAVE_ADDRESS + 1);
b1 = i2c_read(1);
delay_us(16);
b2 = i2c_read(0);
delay_us(16);
i2c_stop();
return make16(b2, b1);
}
INT16 gethexword() {
BYTE lo,hi;
hi = gethex();
lo = gethex();
return make16( hi,lo );
}
void main() {
int cmd;
INT16 value;
initI2C();
printf("i2c master 01 APRIL 2007\n\r\n\r");
do {
do
{
printf("\r\n[R]ead or [W]rite: ");
cmd=getc();
cmd=toupper(cmd);
putc(cmd);
if(cmd!='R' && (cmd!='W'))
{
value =0;
printf("\r\nStupid ah! Please retype!!");
}
} while ( (cmd!='R') && (cmd!='W') );
if(cmd=='R')
{
value = 0;
value = readI2C();
printf("\r\nValue: %lX\r\n",value );
} else if(cmd=='W')
{
printf("\r\nNew 16-bit value: ");//2 bytes
value = gethexword();
printf("\n\r");
writeI2C(value);
}
} while (TRUE);
}
|
slave
Code: |
#include <16F877A.H>
// 10-bit A/D conversion
#device ADC=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use Delay(Clock=20000000)
#use rs232(baud=19200,xmit=PIN_C6,rcv=PIN_C7,brgh1ok)
unsigned char read_i2c(void);
void i2c_interrupt_handler(void);
void i2c_initialize(void);
void i2c_error(void);
void write_i2c(unsigned char transmit_byte);
#INT_SSP
void ssp_interupt ()
{
i2c_interrupt_handler();
}
/* 16f87X bytes */
/* Change it per chip */
#byte PIC_SSPBUF=0x13
#byte PIC_SSPADD=0x93
#byte PIC_SSPSTAT=0x94
#byte PIC_SSPCON1=0x14
#byte PIC_SSPCON2=0x91
/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP 0x80
#define PIC_SSPSTAT_BIT_CKE 0x40
#define PIC_SSPSTAT_BIT_DA 0x20
#define PIC_SSPSTAT_BIT_P 0x10
#define PIC_SSPSTAT_BIT_S 0x08
#define PIC_SSPSTAT_BIT_RW 0x04
#define PIC_SSPSTAT_BIT_UA 0x02
#define PIC_SSPSTAT_BIT_BF 0x01
#define PIC_SSPCON1_BIT_WCOL 0x80
#define PIC_SSPCON1_BIT_SSPOV 0x40
#define PIC_SSPCON1_BIT_SSPEN 0x20
#define PIC_SSPCON1_BIT_CKP 0x10
#define PIC_SSPCON1_BIT_SSPM3 0x08
#define PIC_SSPCON1_BIT_SSPM2 0x04
#define PIC_SSPCON1_BIT_SSPM1 0x02
#define PIC_SSPCON1_BIT_SSPM0 0x01
#define PIC_SSPCON2_BIT_GCEN 0x80
#define PIC_SSPCON2_BIT_ACKSTAT 0x40
#define PIC_SSPCON2_BIT_ACKDT 0x20
#define PIC_SSPCON2_BIT_ACKEN 0x10
#define PIC_SSPCON2_BIT_RCEN 0x08
#define PIC_SSPCON2_BIT_PEN 0x04
#define PIC_SSPCON2_BIT_RSEN 0x02
#define PIC_SSPCON2_BIT_SEN 0x01
#define RX_BUF_LEN 32
#define NODE_ADDR 0x02 /* I2C address of the slave node */
unsigned char slave_buffer[RX_BUF_LEN];
int buffer_index;
int comms_error;
int debug_state;
void i2c_initialize(void)
{
/* Set up SSP module for 7-bit */
PIC_SSPCON1 = 0x36; /* 0011 0110 */
PIC_SSPADD = NODE_ADDR; /* Set the slave's address */
PIC_SSPSTAT = 0x00; /* Clear the SSPSTAT register. */
enable_interrupts(INT_SSP); /* Enable MSSP interrupts. */
}
void i2c_interrupt_handler(void)
{
unsigned char i2c_mask = 0x2D; /* 0010 1101 */
unsigned char temp_sspstat;
unsigned char this_byte;
unsigned char tx_byte;
int x;
/* Mask out the unnecessary bits */
temp_sspstat = PIC_SSPSTAT & i2c_mask;
switch (temp_sspstat)
{
/* Write operation, last byte was an address, buffer is full */
case 0x09: /* 0000 1001 */
/* Clear the receive buffer */
for (x=0; x<RX_BUF_LEN; x++)
{
slave_buffer[x] = 0x00;
}
buffer_index = 0; /* Clear the buffer index */
this_byte = read_i2c(); /* Do a dummy read of PIC_SSPBUF */
debug_state = 1;
break;
/* Write operation, last byte was data, buffer is full */
case 0x29: /* 0010 1001 */
/* Point to the buffer */
this_byte = read_i2c(); /* Get the byte from the SSP */
slave_buffer[buffer_index] = this_byte; /* Put it into the buffer */
buffer_index++; /* Increment the buffer pointer */
/* Get the current buffer index */
/* Subtract the buffer length */
/* Has the index exceeded the buffer length? */
if (buffer_index >= RX_BUF_LEN)
{
buffer_index = 0; /* Yes, clear the buffer index. */
}
debug_state = 2;
break;
/* Read operation; last byte was an address, buffer is empty */
case 0x0C: /* 0000 1100 */
buffer_index = 0; /* Clear the buffer index */
/* Point to the buffer */
tx_byte = slave_buffer[buffer_index]; /* Get byte from the buffer */
write_i2c(tx_byte); /* Write the byte to PIC_SSPBUF */
buffer_index++; /* increment the buffer index */
debug_state = 3;
break;
/* Read operation; last byte was data, buffer is empty */
case 0x2C: /* 0010 1100 */
/* Get the current buffer index */
/* Subtract the buffer length */
/* Has the index exceeded the buffer length? */
if (buffer_index >= RX_BUF_LEN)
{
buffer_index = 0; /* Yes, clear the buffer index */
}
/* Point to the buffer */
/* Get the byte */
tx_byte = slave_buffer[buffer_index];
write_i2c(tx_byte); /* Write to PIC_SSPBUF */
buffer_index++; /* increment the buffer index */
debug_state = 4;
break;
/* A NACK was received when transmitting data back from the master. */
/* Slave logic is reset in this case. R_W=0, D_A=1, and BF=0. */
/* If we don't stop in this state, then something is wrong!! */
case 0x28: /* 0010 1000 */
debug_state = 5;
break;
/* Something went wrong!! */
default:
i2c_error();
break;
}
}
void i2c_error(void)
{
comms_error = 1;
printf ("I2C ERROR!\r\n");
}
void write_i2c(unsigned char transmit_byte)
{
unsigned char write_collision = 1;
while (PIC_SSPSTAT & PIC_SSPSTAT_BIT_BF) /* Is BF bit set in PIC_SSPSTAT? */
{
/* If yes, then keep waiting */
}
while (write_collision)
{
/* If not, then do the i2c_write. */
PIC_SSPCON1 &= ~PIC_SSPCON1_BIT_WCOL; /* Clear the WCOL flag */
PIC_SSPBUF = transmit_byte;
/* Was there a write collision? */
if (PIC_SSPCON1 & PIC_SSPCON1_BIT_WCOL)
{
/* Yes there was a write collision. */
write_collision = 1;
}
else
{
/* NO, there was no write collision. */
/* The transmission was successful */
write_collision = 0;
}
}
PIC_SSPCON1 |= PIC_SSPCON1_BIT_CKP; /* Release the clock. */
}
/* This function returns the byte in SSPBUF */
unsigned char read_i2c(void)
{
return PIC_SSPBUF;
}
void main(void)
{
debug_state = 0;
i2c_initialize();
enable_interrupts(GLOBAL);
printf("i2c slave 01 APRIL 2007\n\r\n\r");
while (1)
{
if (debug_state)
{
printf ("debug state = %d\r\n", debug_state);
debug_state = 0;
}
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 04, 2007 11:20 am |
|
|
Quote: | p/s: I have re-configure those special function register value for different chips |
Post those statements so we can see if they are correct. |
|
|
funmix
Joined: 27 Mar 2007 Posts: 33
|
|
Posted: Wed Apr 04, 2007 5:30 pm |
|
|
Code: |
#byte PIC_SSPBUF=0xfc9
#byte PIC_SSPADD=0xfc8
#byte PIC_SSPSTAT=0xfc7
#byte PIC_SSPCON1=0xfc6
#byte PIC_SSPCON2=0xfc5
|
I used 4.7k pullup register for I2C bus. Crystal running at 20Mhz. |
|
|
tom_hanks
Joined: 04 Apr 2007 Posts: 20
|
|
Posted: Tue Apr 24, 2007 4:02 am |
|
|
i guess you need to do following change...
and may be you need to remove a while loop of BF in write_I2C...
Code: |
unsigned char read_i2c(void)
{
if(PIC_SSPSTAT & PIC_SSPSTAT_BIT_BF)
{
PIC_PIR1 = 0x47 & PIC_PIR1;
return PIC_SSPBUF;
}
}
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|