|
|
View previous topic :: View next topic |
Author |
Message |
longmenok
Joined: 23 Oct 2006 Posts: 12
|
what different 18F4431 and 16F877A in I2c |
Posted: Wed Feb 28, 2007 9:49 am |
|
|
hello everyone, I have some question wish to solve in there.
I have getting 2 pics to communicate via I2C. master is 16F877A,slave is 18f4431.I've modified two examples and now have working code when master and slave are both 16F877A, but when slave is 18f4431, the I2c can't work,
I think 18F4431 register can't be setup correctly. But where wrong in my code?
This is pasted straight from my working programs.
Thanks to everyone. I am say sorry to everyone for my english.
slave code
//#include <16F877A.h>
#include <18F4431.h>
#define I2C_SDA PIN_C4
//define I2C_SCL PIN_C3
#define I2C_SCL PIN_C5
#define brake PIN_B5
#define dir PIN_D1
#define SLAVE_ADDR 0xa0 // Even number, address to be sent to slave pic,
// must match. Note read address is slave address + 1.
#fuses HS,PROTECT,NOLVP,NOPUT,BROWNOUT
#use delay(clock=12000000)
#use fast_io(c)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(slave, sda=I2C_SDA, scl=I2C_SCL,address=SLAVE_ADDR, FORCE_HW, SLOW)
//#include <motor.h>
void trimite_QEI();
void start_motor();
void stop_motor();
void posi_dir();
void navi_dir();
void trimite_I2C(unsigned int8 comanda, unsigned int8 valoare1, unsigned int8 valoare2,
unsigned int8 valoare3, unsigned int8 valoare4);
// Registers and bits associated with i2c Sync Serial Port it is for 877A
/*
#byte SSPADD = 0x93 // Slave address held here
#byte SSPCON1= 0x14 // SSP control reg 1
#byte SSPBUF = 0x13 // Buffer for SSP data
#byte SSPSTAT= 0x94 // SSP status reg
*/
//it is for 18f4431 I think the key of problem
//and in datasheet page 214-215 sspstat address is 94H, sspcon is 14H
//what means is it?
#byte SSPBUF = 0xFC9 // Buffer for SSP data
#byte SSPADD = 0xFC8 // Slave address held here
#byte SSPSTAT= 0xFC7 // SSP status reg
#byte SSPCON = 0xFC6 // SSP control reg 1
// SSPSTAT bits
#bit BF = SSPSTAT.0 // Buffer full status bit. Read-only bit.
// Receive mode 1 = SSPBUF full.
// Tx mode 1 = data transmit in progress, SSPBUF full.
// 0 = complete, SSPBUF empty.
// (does not include ack and stop bits in either case)
#bit UA = SSPSTAT.1 // User needs to update addr. in SSPADD, 10 bit mode only.
#bit R_W = SSPSTAT.2 // Holds read/write status from last address match, valid
// to next start,stop, or not /ack bit.
// Slave mode 1 = read, Master mode transmit in progress.
#bit START=SSPSTAT.3 // Start bit (S) has been detected last
#bit STOP= SSPSTAT.4 // Stop bit (P) has been detected last
#bit D_A = SSPSTAT.5 // Data/addr bit. 1 = last byte received or transmitted
// was data.
#bit CKE = SSPSTAT.6 // 0 = input levels are i2c specs, 1 = SMB specs.
#bit SMP = SSPSTAT.7 // Slew rate control. 1 = disabled for 100kHz or 1MHz modes
/*
// SSPCON bits it is for 877A Slave mode 7 bits
#bit SSPM0 = SSPCON1.0 // SSP mode bits 0
#bit SSPM1 = SSPCON1.1 // " 1
#bit SSPM2 = SSPCON1.2 // " 1
#bit SSPM3 = SSPCON1.3 // " 0
#bit CKP = SSPCON1.4 // Clock, 1 = enable clock, 0 = clock stretch
#bit SSPEN = SSPCON1.5 // SSP enable bit
#bit SSPOV = SSPCON1.6 // Receive overflow indicator bit. In receive mode, a
// byte is received while the SSPBUF is holding
// previous byte. Must clear in software.
#bit WCOL = SSPCON1.7 // Write collision detect bit. In slave mode, 1 means
// SSBUF written while transmitting previous word.
// Must clear in software.
*/
// SSPCON bits it is for 4431 Slave mode 7 bits
#bit SSPM0 = SSPCON.0 // SSP mode bits 0
#bit SSPM1 = SSPCON.1 // " 1
#bit SSPM2 = SSPCON.2 // " 1
#bit SSPM3 = SSPCON.3 // " 0
#bit CKP = SSPCON.4 // Clock, 1 = enable clock, 0 = clock stretch
#bit SSPEN = SSPCON.5 // SSP enable bit
#bit SSPOV = SSPCON.6 // Receive overflow indicator bit. In receive mode, a
// byte is received while the SSPBUF is holding
// previous byte. Must clear in software.
#bit WCOL = SSPCON.7 // Write collision detect bit. In slave mode, 1 means
// SSBUF written while transmitting previous word.
// Must clear in software.
#byte TRISC = 0x87
#byte PIR1 = 0x0c
#bit SSPIF = PIR1.3 // SSP interrupt flag bit
#define BUF_LEN 5
unsigned int8 buf[BUF_LEN]; // Buffer for data to be received or transmitted
int8 buf_index,command,data,duty,add=0;
// Possible i2c states, SSPSTAT for the four relevant bits
#define STATE1 0x09 // D/A=0,S=1,R/W=0,BF=1. Master tx, slave addr
#define STATE2 0x29 // D/A=1,S=1,R/W=0,BF=1. Master tx, data
#define STATE3 0x0C // D/A=0,S=1,R/W=1,BF=0. Master rx, slave addr+1
#define STATE4 0x2C // D/A=1,S=1,R/W=1,BF=0. Master rx, data with ack
#define STATE5 0x28 // D/A=1,S=1,R/W=0,BF=0. Master rx, data with nack (high)
#define STATE6 0x30 // D/A=1
// i2c interrupt handler
#int_SSP
void SSP_isr()
{
// Loop while flag set
while(SSPIF==1)
{
//state=i2c_isr_state();
// Keep only bits D/A, S, R/W, BF
switch (SSPSTAT & 0x2d)
{
case(STATE1):
// Master write operation, address byte in SSPBUF.
// Clear the data buffer. Keep Master waiting by clock stretching
// for this to finish before it sends data byte(s). Otherwise
// SSPBUF will be full and an acknowledge will not be generated
// by the slave i2c hardware.
CKP = 0; // Hold SCL low
for (buf_index = 0; buf_index <BUF_LEN>= BUF_LEN) buf_index = 0; // Wrap around
CKP = 1; // Allow master to continue by re-enabling SCL
break;
case(STATE3):
// Master has begun new read operation by initiating a START or RESTART
// then sending Slave address (read) byte, now in SSPBUF.
// Looks like clock enable bit CKP cleared on interrupt, so must
// set it again to allow Master to clock data byte out.
CKP = 0; // Make Master wait by holding SCL low
////////////////////////////////////////
// Aici poti sa verifici ce ai primit //
////////////////////////////////////////
buf_index = 0; // Reset buffer index
while(BF)
{
//Asteapta ca BF sa fie 0
}
do
{
WCOL=0;
//i2c_write(buf[buf_index]);
SSPBUF = buf[buf_index];// Load 1st byte from data buffer
printf("\n\r send3 ");
printf("%u ",buf[buf_index]);
}
while(WCOL);
buf_index++;
CKP = 1; // Enable SCL for Master to shift byte out
break;
case(STATE4):
// Master read operation, last byte was data, SSPBUF empty.
// Move next byte to SSPBUF and SSPSR.
// Same comment for CKP bit as in STATE3.
CKP = 0; // Make Master wait by holding SCL low
while(BF)
{
//Asteapta ca BF sa fie 0
}
do
{
WCOL=0;
//i2c_write(buf[buf_index]);
SSPBUF = buf[buf_index];// Get next byte from data buffer
printf("\n\rsend4");
printf(" %x ",buf[buf_index]);
}
while(WCOL);
buf_index++;
if (buf_index >= BUF_LEN) buf_index = 0; // Wrap around
CKP = 1; // Enable SCL for Master to shift byte out
break;
case(STATE5):
// A nack (high) was received from Master in response to data
// byte received from Slave (last byte). Slave i2c logic is reset,
// and waits for next Master operation.
SSPEN=0;
SSPEN=1;
break;
default:
// Error, trap here. Watchdog will reset pic (must be enabled, and
// watchdog timer cleared in other loops).
printf("\n\rEroare: 0x%X",SSPSTAT);
while(true);
break;
}
SSPIF = 0;
}
}
void main()
{
output_float(I2C_SDA);
output_float(I2C_SCL);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE)
{
while(!command);
switch(command) {
///setup PWM duty
case 0x08: duty=data;
printf("data8 %u",data);
break;// Gain commands to limit max. gain in
// send QEI
case 0x09: trimite_QEI();
case 0x11: duty=data;
printf("data17 %u ",data);
break;// Gain commands to limit max. gain in
case 0x12:
case 0x13: posi_dir();
printf("direction");
case 0x14: navi_dir();
printf("direction");
case 0x15: start_motor();
case 0x16: stop_motor();
case 0x17:
case 0x18:
case 0x19:
case 0x1A:
case 0x1B:
case 0x1C:
case 0x1D:
case 0x1E:
case 0x80: // inches, centimetres or uS
case 0x81:
case 0x82: // multi_range(); // 2byte multi-ping data
// seq = 0; // reset address change sequence
break;
case 0x83:
case 0x84:
case 0x85: // ann_range(); // 2byte 1st, 1byte multi-pings
//seq = 0; // reset address change sequence
break;
case 0xa0: // seq = 1; // start of sequence to change address
break;
case 0xaa: //if(seq==1) ++seq; // 2nd of sequence to change address
// else seq = 0;
break;
case 0xa5: // if(seq==2) ++seq; // 3rd of sequence to change address
//else seq = 0;
break;
case 0xe0: // if seq=3 user is changing sonar I2C address
}
command = 0;
}
}
void trimite_QEI()
{
int16 number,quadhigh;
int8 CAP2BUFL,CAP2BUFH;
number=0x1234;
CAP2BUFL=0x0d;
CAP2BUFH=0x0c;
//add=12;
printf("start QEI ");
for (buf_index = 0; buf_index <BUF_LEN>>8) ;//H
buf[2]=number & 0x00ff; //L
buf[3]=CAP2BUFH;
buf[4]=CAP2BUFL;
//buf[5]=add;
}
void start_motor(){
output_low(brake);
}
void stop_motor(){
output_high(brake);
}
void posi_dir(){
output_low(dir);
}
void navi_dir(){
output_high(dir);
}
master code
Code: | #include <16F877A.h>
#fuses HS,NOWDT,PROTECT,NOLVP,NOPUT,BROWNOUT
#use delay(clock=12000000)
#use fast_io(C)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW, SLOW)
#define SLAVE_ADDR 0xa0
//#include <math.h>
short int status=0;
//function of i2c by int8
void trimite_primeste_I2C(unsigned int8 comanda, unsigned int8 valoare1, unsigned int8 valoare2,
unsigned int8 valoare3, unsigned int8 valoare4);
void trimite_I2C(unsigned int8 comanda, unsigned int8 valoare1, unsigned int8 valoare2,
unsigned int8 valoare3, unsigned int8 valoare4);
void primeste_I2C();
void main()
{
printf("\n\rStart...");
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
//Se verifica daca exista modulul de relee de frecventa atasat
i2c_start();
status=i2c_write(SLAVE_ADDR);
i2c_stop();
if(status==1)
printf("\n\rModulul Relee de Frecventa - OFF.");
if(status==0)
printf("\n\rModulul Relee de Frecventa - ON.");
delay_ms(100);
if(status==0)
{
// trimite_primeste_i2c(127,128,129,130,131);
// trimite_I2C(64,65,128,129,255);
//primeste_i2c();
}
while(TRUE)
{
// trimite_primeste_I2C(64,65,128,129,255);
trimite_i2c(9,0,0,0,0);
delay_ms(1000);
primeste_i2c();
}
}
void trimite_primeste_I2C(unsigned int8 comanda, unsigned int8 valoare1, unsigned int8 valoare2,
unsigned int8 valoare3, unsigned int8 valoare4)
{
unsigned int8 rxbuf[5]; // Buffer for data received back from the slave pic
int8 i=0;
// Clear the Master receive buffer
for(i=0;i<5;i++)
rxbuf[i] = 0;
// Send some numbers to the slave pic buffer. Slave clears it's buffer
// each time round when address match occurs.
// Small delays are to allow time for slave to get to and from
// interrupt handler.
i2c_start();
i2c_write(SLAVE_ADDR); // Must match address of slave pic
delay_us(10);
i2c_write(comanda); //Trimite comanda
delay_us(10);
i2c_write(valoare1);
delay_us(10);
i2c_write(valoare2);
delay_us(10);
i2c_write(valoare3);
delay_us(10);
i2c_write(valoare4);
delay_us(10); //i2c_stop();
//delay_ms(5);
// Now read back the numbers without releasing i2c bus,
// could do a STOP here and a new START.
i2c_start(); // A restart
i2c_write(SLAVE_ADDR + 1); // Slave read address
for(i=0; i<4; i++)
{
//output_high(I2C_SDA);
//output_low(I2C_SCL);
rxbuf[i] = i2c_read(); // Note that Slave may be delaying response
// by holding SCL low. i2c_read() monitors
// SCL and takes care of this.
}
rxbuf[4] = i2c_read(0); // Last one nack (high), resets slave i2c
// logic. Very important, i2c bus will hang
// otherwise.
i2c_stop(); // Release the i2c bus
printf("\n\r send and read8 ");
for(i=0; i<=4; i++)
{
printf(" %u",rxbuf[i]);
}
}
void primeste_I2C()
{
unsigned int8 rxbuf[5]; // Buffer for data received back from the slave pic
int8 i=0;
// Clear the Master receive buffer
for(i=0;i<5;i++)
rxbuf[i] = 0;
// Now read back the numbers without releasing i2c bus,
// could do a STOP here and a new START.
i2c_start(); // A restart
i2c_write(SLAVE_ADDR + 1); // Slave read address
for(i=0; i<4; i++)
{
rxbuf[i] = i2c_read();
}
rxbuf[4] = i2c_read(0);
i2c_stop();
printf(" \n\rread slave ");
for(i=0; i<=4; i++)
{
printf(" %u ",rxbuf[i]);
}
}
void trimite_I2C(unsigned int8 comanda, unsigned int8 valoare1, unsigned int8 valoare2,
unsigned int8 valoare3, unsigned int8 valoare4)
{
unsigned int8 rxbuf[5]; // Buffer for data received back from the slave pic
int8 i=0;
// Clear the Master receive buffer
for(i=0;i<5>> 8;
rxbuf[3]=valoare3;
rxbuf[4]=valoare4;
// Send some numbers to the slave pic buffer. Slave clears it's buffer
// each time round when address match occurs.
// Small delays are to allow time for slave to get to and from
// interrupt handler.
i2c_start();
i2c_write(SLAVE_ADDR); // Must match address of slave pic
delay_us(10);
i2c_write(comanda); //Trimite comanda
delay_us(10);
i2c_write(valoare1);
delay_us(10);
i2c_write(valoare2);
delay_us(10);
i2c_write(valoare3);
delay_us(10);
i2c_write(valoare4);
delay_us(10); //
i2c_stop();
printf("\n\r send ");
for(i=0; i<=4; i++)
{
printf(" %u ",rxbuf[i]);
}
//delay_ms(5);
} |
Last edited by longmenok on Thu Mar 01, 2007 5:32 am; edited 1 time in total |
|
|
Ttelmah Guest
|
|
Posted: Wed Feb 28, 2007 11:08 am |
|
|
It just means that this was an early 18F data sheet, and they copied the page from the ones used for the 16F, and didn't remove the old heading. They have avoided this on latter data sheets by not having the address in these pages at all...
Tidy up your code. Remove all the 877 references, so we don't have to wade through hundreds of 'not used' lines, and I expect it'll start working!...
However, worth looking at the fuse SSP_RC...
Best Wishes |
|
|
longmenok
Joined: 23 Oct 2006 Posts: 12
|
|
Posted: Thu Mar 01, 2007 5:42 am |
|
|
sorry ,there are a lots of waste lines ,
This is pasted straight from my sample working programs
Thanks!!!
slave code
Code: |
#include <18F4431.h>
#fuses HS,PROTECT,NOLVP,NOPUT,BROWNOUT
#use delay(clock=12000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(slave, sda=PIN_C4 , scl=PIN_C5,address=0xa0 , FORCE_HW, SLOW)
[b]//it is for 18f4431 I think the key of problem[/b]
[b]#byte SSPBUF = 0xFC9 // Buffer for SSP data
#byte SSPADD = 0xFC8 // Slave address held here
#byte SSPSTAT= 0xFC7 // SSP status reg
#byte SSPCON = 0xFC6 // SSP control reg 1 [/b]
// SSPSTAT bits
#bit BF = SSPSTAT.0 // Buffer full status bit. Read-only bit.
// Receive mode 1 = SSPBUF full.
// Tx mode 1 = data transmit in progress, SSPBUF full.
// 0 = complete, SSPBUF empty.
// (does not include ack and stop bits in either case)
#bit UA = SSPSTAT.1 // User needs to update addr. in SSPADD, 10 bit mode only.
#bit R_W = SSPSTAT.2 // Holds read/write status from last address match, valid
// to next start,stop, or not /ack bit.
// Slave mode 1 = read, Master mode transmit in progress.
#bit START=SSPSTAT.3 // Start bit (S) has been detected last
#bit STOP= SSPSTAT.4 // Stop bit (P) has been detected last
#bit D_A = SSPSTAT.5 // Data/addr bit. 1 = last byte received or transmitted
// was data.
#bit CKE = SSPSTAT.6 // 0 = input levels are i2c specs, 1 = SMB specs.
#bit SMP = SSPSTAT.7 // Slew rate control. 1 = disabled for 100kHz or 1MHz modes
// SSPCON bits it is for 4431 Slave mode 7 bits
#bit SSPM0 = SSPCON.0 // SSP mode bits 0
#bit SSPM1 = SSPCON.1 // " 1
#bit SSPM2 = SSPCON.2 // " 1
#bit SSPM3 = SSPCON.3 // " 0
#bit CKP = SSPCON.4 // Clock, 1 = enable clock, 0 = clock stretch
#bit SSPEN = SSPCON.5 // SSP enable bit
#bit SSPOV = SSPCON.6 // Receive overflow indicator bit. In receive mode, a
// byte is received while the SSPBUF is holding
// previous byte. Must clear in software.
#bit WCOL = SSPCON.7 // Write collision detect bit. In slave mode, 1 means
// SSBUF written while transmitting previous word.
// Must clear in software.
#byte TRISC = 0x87
#byte PIR1 = 0x0c
#bit SSPIF = PIR1.3 // SSP interrupt flag bit
#define BUF_LEN 5
unsigned int8 buf[BUF_LEN];
int8 buf_index;
// Possible i2c states, SSPSTAT for the four relevant bits
#define STATE1 0x09
#define STATE2 0x29
#define STATE3 0x0C
#define STATE4 0x2C
#define STATE5 0x28
#define STATE6 0x30
#int_SSP
void SSP_isr()
{
while(SSPIF==1)
{
switch (SSPSTAT & 0x2d)
{
case(STATE1):
CKP = 0; // Hold SCL low
for (buf_index = 0; buf_index <BUF_LEN>= BUF_LEN) buf_index = 0; // Wrap around
CKP = 1; // Allow master to continue by re-enabling SCL
break;
case(STATE3):
CKP = 0; // Make Master wait by holding SCL low
buf_index = 0; // Reset buffer index
do
{
WCOL=0;
SSPBUF = buf[buf_index];// Load 1st byte from data buffer
}
while(WCOL);
buf_index++;
CKP = 1; // Enable SCL for Master to shift byte out
break;
case(STATE4):
CKP = 0; // Make Master wait by holding SCL low
do
{
WCOL=0;
SSPBUF = buf[buf_index];// Get next byte from data buffer
}
while(WCOL);
buf_index++;
if (buf_index >= BUF_LEN) buf_index = 0;
CKP = 1;
break;
case(STATE5):
SSPEN=0;
SSPEN=1;
break;
default:
while(true);
break;
}
SSPIF = 0;
}
}
void main()
{
output_float(I2C_SDA);
output_float(I2C_SCL);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
while(TRUE)
{
while(!command);
switch(command) {
case 0x08: duty=data;
break;
// send QEI
case 0x09: trimite_QEI();
}
command = 0;
}
} |
master code
Code: |
#include <16F877A.h>
#fuses HS,NOWDT,PROTECT,NOLVP,NOPUT,BROWNOUT
#use delay(clock=12000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW, SLOW)
#define SLAVE_ADDR 0xa0
short int status=0;
void trimite_I2C(unsigned int8 comanda, unsigned int8 valoare1, unsigned int8 valoare2,
unsigned int8 valoare3, unsigned int8 valoare4);
void primeste_I2C();
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(TRUE)
{
trimite_i2c(9,0,0,0,0);
delay_ms(1000);
primeste_i2c();
}
}
void primeste_I2C()
{
unsigned int8 rxbuf[5]; // Buffer for data received back from the slave pic
int8 i=0;
// Clear the Master receive buffer
for(i=0;i<5;i++)
rxbuf[i] = 0;
// Now read back the numbers without releasing i2c bus,
// could do a STOP here and a new START.
i2c_start(); // A restart
i2c_write(SLAVE_ADDR + 1); // Slave read address
for(i=0; i<4; i++)
{
rxbuf[i] = i2c_read();
}
rxbuf[4] = i2c_read(0);
i2c_stop();
printf(" \n\rread slave ");
for(i=0; i<=4; i++)
{
printf(" %u ",rxbuf[i]);
}
}
void trimite_I2C(unsigned int8 comanda, unsigned int8 valoare1, unsigned int8 valoare2,
unsigned int8 valoare3, unsigned int8 valoare4)
{
unsigned int8 rxbuf[5]; // Buffer for data received back from the slave pic
int8 i=0;
// Clear the Master receive buffer
for(i=0;i<5>> 8;
rxbuf[3]=valoare3;
rxbuf[4]=valoare4;
i2c_start();
i2c_write(SLAVE_ADDR); // Must match address of slave pic
delay_us(10);
i2c_write(comanda); //Trimite comanda
delay_us(10);
i2c_write(valoare1);
delay_us(10);
i2c_write(valoare2);
delay_us(10);
i2c_write(valoare3);
delay_us(10);
i2c_write(valoare4);
delay_us(10); //
i2c_stop();
printf("\n\r send ");
for(i=0; i<=4; i++)
{
printf(" %u ",rxbuf[i]);
}
//delay_ms(5);
} |
|
|
|
Ttelmah Guest
|
|
Posted: Thu Mar 01, 2007 7:55 am |
|
|
Have you tried the fuse I mentioned?.
Best Wishes |
|
|
|
|
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
|