|
|
View previous topic :: View next topic |
Author |
Message |
AntonioB
Joined: 25 Oct 2007 Posts: 7 Location: Puebla Mexico
|
I2C multi byte Master-Slave |
Posted: Thu Oct 25, 2007 12:48 pm |
|
|
Hi there, im been using PICS for a time now, but im new using the I2C comunication, im trying now just to send 3 bytes of information from master(18F4550) to the slave(18F4550), then store them in the slave in to a buffer and use that data to display the values in a LCD.
The LCD its working just fine, it reads bytes and so, but the problem is that i cant reade the 3 bytes, i just get 1 right and the ohter apeear as -96
so i have been searching for a post where they use multiple bytes but i didnt find any one, maybe u can help me out guys, ill be very gratful, thanks to all.
Here is the code. i just send to bytes for now,
MASTER
Code: |
#include <18F4550.h> //PIC utilizado
#fuses HS,NOWDT,NOPROTECT,NOLVP //Configuramos los fuses
#use delay (clock=4000000) //Oscilador a 4Mhz
#use fast_io(b) //Optimizamos E/S del PORTB
#use fast_io(c) //Optimizamos E/S del PORTC
#use i2c(master, sda=PIN_B0, scl=PIN_B1) // Configure Device as Master
//Programa principal
void main(void) {
while(true){
i2c_start();
i2c_write(0xA0); //Slave adress
DELAY_MS(100);
i2c_write(0x0A); //first data to be display
DELAY_MS(100);
i2c_write(0x0F); //second data to be display
DELAY_MS(500);
i2c_stop();
DELAY_MS(200);
}
}
|
THen the SLAVE, that also displays the data
Code: |
#include <18F4550.h> //PIC utilizado
#fuses HS,NOWDT,NOPROTECT,NOLVP //Configuramos los fuses
#use delay (clock=4000000) //Oscilador a 4Mhz
#use fast_io(b) //Optimizamos E/S del PORTB
#use fast_io(c) //Optimizamos E/S del PORTC
#use i2c(slave,address=0xa0,sda=PIN_B0, scl=PIN_B1,slow) // Configure Device as Slave
#include "lcd.c" //Incluyo LCD.C
BYTE bufferTemp [3],state,incoming;
//char temp=0x05;
//=========interrupcion para I2C======
#INT_SSP
void i2c_interupt (void)
{
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) //First received byte
bufferTemp[0] = incoming;
if(state == 2) //Second received byte
bufferTemp[1] = incoming;
}
}
//Meotodo para desplegar tecto y temperatura en LCD
void lcd_desplegar(void) {
while(TRUE){ //Condicion para que siempre se ejecute el metodo
printf(lcd_putc,"Temperatura1:%d",buffertemp[0]); //imprime el texto1 junto con el valor de la varibale temp
delay_ms(1000); //retaro
lcd_putc( "\f"); //borra display
printf(lcd_putc,"Temperatura2:%d",buffertemp[1]); //imprime el texto1 junto con el valor de la varibale temp
delay_ms(1000); //retaro
lcd_putc( "\f");
printf(lcd_putc,"Temperatura3:%d",buffertemp[2]); //imprime el texto1 junto con el valor de la varibale temp
delay_ms(1000); //retaro
lcd_putc( "\f");
}
}
//Programa principal
void main(void) {
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);//interruptions
buffertemp[0]=0x01;
buffertemp[1]=0x02;
buffertemp[2]=0x03;
lcd_init(); //inicialisa el LCD
lcd_desplegar();//llama al metodo para deslpegar texto en LCD
}
|
I have already try multiple ways, but no one works, the most i can do its to read succesfully one byte but no more, thanks for your help. |
|
|
Ttelmah Guest
|
|
Posted: Thu Oct 25, 2007 4:00 pm |
|
|
Series of things.
First, get rid of the 'slow' declaration in the slave. The slave has _nothing to do with I2C timing_. If you want to use 'slow', this needs to be in the master.
Next, you need to read the byte whenever the I2C_ISR_STATE is below 80. Read the byte, then test the state, to work out where to put it.
Obviously, presumably you do have pull-up resistors on the bus?.
I'd shorten the delays rather massively.
ex_slave.c, shows how to handle an indexed transfer to an address. If you simply reset your counter, then use:
Code: |
#INT_SSP
void ssp_interupt ()
{
//Only have variabled that need to be 'global', global.
//reduces risk of data getting accidentally corrupted...
BYTE incoming, state;
static int address;
state = i2c_isr_state();
if(state <0x80>2) address=2; //prevent overrun
}
}
if(state == 0x80) //Master is requesting data
{
i2c_write(0); //Dummy return to ensure I2C doesn't get confused
}
}
|
Best Wishes |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Fri Oct 26, 2007 9:36 am |
|
|
I've never used the i2c_isr_state() command but perhaps the answer to my question might help AntonioB a bit.
The help file states that a value of 1-0x7F means the Master has written data. Does this value increment starting from 1 with each byte that is written or is it some kind of arbitrary value? Also, a value of 0x81-0xFF means a transmission is finished and ACK'd and a write needs to be performed. Does this value increment just like the first question I posed?
I've always manipulated the registers directly and I'm just curious about this command.
Ronald
If the world were to start spinning faster, would be all start losing weight? |
|
|
AntonioB
Joined: 25 Oct 2007 Posts: 7 Location: Puebla Mexico
|
|
Posted: Mon Oct 29, 2007 5:21 pm |
|
|
ok, thanks alot for your answer im going to check that, thanks |
|
|
Guest
|
|
Posted: Tue Oct 30, 2007 4:43 pm |
|
|
The code now works just right, I just change the state condition, and now I can send and receive data thanks for the help.
Code: |
#INT_SSP
void i2c_interupt (void)
{
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 0) //First received byte
bufferTemp[0] = incoming;
if(state == 1) //Second received byte
bufferTemp[1] = incoming;
if(state== 2)
bufferTemp[2] = incoming;
if(state== 3)
bufferTemp[3] = incoming;
if(state== 4)
bufferTemp[4] = incoming;
if(state== 5)
bufferTemp[5] = incoming;
if(state== 6)
bufferTemp[6] = incoming;
}
if (state == 0x80)
{
i2c_write(0);
}
} |
|
|
|
|
|
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
|