I2C Slave doesn't send data

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to send the letter 'g' from a slave node to the master node and output the value on the master node PORTA.

 

Master Code:

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

void i2c_init(void){
	TWSR = 0x00;
	TWBR = 0x47;
	TWCR = 0x04;
}

void i2c_write(unsigned char data){
	TWDR = data;
	TWCR = (1<<TWINT)|(1<<TWEN);
	while((TWCR & (1<<TWINT)) == 0);
}

unsigned char i2c_read(unsigned char isLast){
	if(isLast == 0)
		TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
	else
		TWCR = (1<<TWINT)|(1<<TWEN);
	while((TWCR & (1<<TWINT)) == 0);
	return TWDR;
}

void i2c_start(void){
	TWCR = (1<<TWINT)|(1<<TWSTA)|(11<<TWEN);
	while((TWCR & (1<<TWINT)) == 0);
}

void i2c_stop(){
	TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

int main(void) {

    DDRA = 0xFF;
    unsigned char i = 0;

    i2c_init();
    i2c_start();
    i2c_write(0b11010000);
    i = i2c_read(1);
    PORTA = i;
    i2c_stop();

    while (1);
    return 0;
}

 

Slave Code:

#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

unsigned char i2c_recieve(unsigned char isLast){
    if(isLast == 0)
        TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
    else
        TWCR = (1<<TWINT)|(1<<TWEN);
    
    while((TWCR & (1<<TWINT))==0);
    return (TWDR);
}

void i2c_send(unsigned char data){
    TWDR = data;
    TWCR = (1<<TWINT)|(1<<TWEN);
    while((TWCR & (1<<TWINT))==0);
}

void i2c_initSlave(unsigned char slaveAddress){
    TWCR = 0x04;
    TWAR = slaveAddress;
    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
}

void i2c_listen(){
    while((TWCR & (1<<TWINT))==0);
}

int main(void) {

    i2c_initSlave(0xD0);
    i2c_listen();
    i2c_send(0b00011000);
    
    while (1);
    return 0;
}

 

When I try to run this code the output on PORTA is 11010000. I am using Proteus Simulator so I used the I2C debugger and it shows that the Slave node isn't sending the data. My question is how to make the Slave node send the data to the Master node?

This topic has a solution.
Last Edited: Sat. Jul 9, 2022 - 07:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mahmoud899 wrote:

i = i2c_read(1);

How many times you do this? For permanent monitoring, Master should read every 40ms, or so.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Take two Arduinos.   Run one as Master.  The other as Slave.  Verify that everything works.  i.e. correct pullups, correct connections.

 

Replace the Arduino Master with your code in #1.   Verify that the Master-Slave is still working 100%.

 

Replace the Arduino Slave with the "slave" code from #1.    Debug your project.

 

I would never dream of writing Master and Slave from scratch.   Always start with proven code.   Replace one side at a time.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suspect that your problem is that the initialization of the slave is setting the slave address to 0xD0.  This is the I2C-TWI  shifted slave-address with the read/write flag in bit 0. 

Try using address 0x68 in the slave initialization function.   0x68 shifted left by one bit is 0xD0: ( 1101_0000   is 110_1000 shifted 1 bit left).

 

What is your AVR device?  Always tell us what chip it is.

 

Also tell us the provenance of your code.  Where did it come from?   Did you write it after referring to the CPU  data sheet?  Is is an example demo from a web site?  Is it a snippet of code from a product currently being manufactured and upgraded?

 

Is this a school homework project? If so, then tell us the level of the class (beginning year_electrical eng dept of Bozo State University, USA) and the title:author of the main textbook.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
i2c_write(0b11010000);
    i = i2c_read(1);

Problem #1 is you are sending an address+W instead of an address+R. You end up treating your previously sent address as a read return value so you get PORTA set to the address (your master read essentially turns into a write using the value already in TWDR).