I am a mechanical engineer with the desire of learning electronics stuff.
I am working on these days at learning the TWI(I2C) communication in Atmega32. With a lot of internet search I have managed to get a tutorial explaining how I can make a mutual communication between a pair of Atmega32 chips.
Here is the code of the Master chip
#include
#include
#include
void TWI_start(void);
void TWI_repeated_start(void);
void TWI_init_master(void);
void TWI_write_address(unsigned char);
void TWI_read_address(unsigned char);
void TWI_write_data(unsigned char);
void TWI_read_data(void);
void TWI_stop(void);
unsigned char address=0x20, read=1, write=0;
unsigned char write_data=0x01, recv_data;
int main(void)
{
_delay_ms(2000);
DDRB=0xff;
TWI_init_master(); // Function to initialize TWI
while(1)
{
if(write_data==0x00)
write_data=1;
// Function to send start condition
TWI_start();
// Function to write address and data direction bit(write) on SDA
TWI_write_address(address+write);
// Function to write data in slave
TWI_write_data(write_data);
// Function to send stop condition
TWI_stop();
_delay_ms(10); // Delay of 10 mili second
TWI_start();
// Function to write address and data direction bit(read) on SDA
TWI_read_address(address+read);
TWI_read_data();
// Function to read data from slave
TWI_stop();
_delay_ms(1000);
write_data = write_data * 2;
}
}
void TWI_init_master(void) // Function to initialize master
{
TWBR=0x01; // Bit rate
TWSR=(0< // SCL freq= F_CPU/(16+2(TWBR).4^TWPS)
}
void TWI_start(void)
{
// Clear TWI interrupt flag, Put start condition on SDA, Enable TWI
TWCR= (1< while(!(TWCR & (1< while((TWSR & 0xF8)!= 0x08); // Check for the acknowledgement
}
void TWI_repeated_start(void)
{
// Clear TWI interrupt flag, Put start condition on SDA, Enable TWI
TWCR= (1< while(!(TWCR & (1< while((TWSR & 0xF8)!= 0x10); // Check for the acknowledgement
}
void TWI_write_address(unsigned char data)
{
TWDR=data; // Address and write instruction
TWCR=(1<
while (!(TWCR & (1< while((TWSR & 0xF8)!= 0x18); // Check for the acknowledgement
}
void TWI_read_address(unsigned char data)
{
TWDR=data; // Address and read instruction
TWCR=(1< while (!(TWCR & (1< while((TWSR & 0xF8)!= 0x40); // Check for the acknowledgement
}
void TWI_write_data(unsigned char data)
{
TWDR=data; // put data in TWDR
TWCR=(1< while (!(TWCR & (1< while((TWSR & 0xF8) != 0x28); // Check for the acknowledgement
}
void TWI_read_data(void)
{
TWCR=(1< while (!(TWCR & (1< while((TWSR & 0xF8) != 0x58); // Check for the acknowledgement
recv_data=TWDR;
PORTB=recv_data;
}
void TWI_stop(void)
{
// Clear TWI interrupt flag, Put stop condition on SDA, Enable TWI
TWCR= (1< while(!(TWCR & (1< }
While the code of the Slave chip is:
#include
#include
void TWI_init_slave(void);
void TWI_match_read_slave(void);
void TWI_read_slave(void);
void TWI_match_write_slave(void);
void TWI_write_slave(void);
unsigned char write_data,recv_data;
int main(void)
{
DDRB=0xff;
TWI_init_slave(); // Function to initialize slave
while(1)
{
//Function to match the slave address and slave direction bit(read)
TWI_match_read_slave();
// Function to read data
TWI_read_slave();
// Togglem the receive data
write_data=~recv_data;
//Function to match the slave address and slave direction bit(write)
TWI_match_write_slave();
// Function to write data
TWI_write_slave();
}
}
// Function to initialize slave
void TWI_init_slave(void)
{
// Fill slave address to TWAR
TWAR=0x20;
}
void TWI_write_slave(void) // Function to write data
{
// Fill TWDR register with the data to be sent
TWDR= write_data;
// Enable TWI, Clear TWI interrupt flag
TWCR= (1< // Wait for the acknowledgement
while((TWSR & 0xF8) != 0xC0);
}
// Function to match the slave address and slave
void TWI_match_write_slave(void)dirction bit(write)
{
// Loop till correct acknowledgement have been received
while((TWSR & 0xF8)!= 0xA8)
{
// Get acknowledgment, Enable TWI, Clear TWI interrupt flag
TWCR=(1< while (!(TWCR & (1< }
}
void TWI_read_slave(void)
{
// Clear TWI interrupt flag,Get acknowledgement, Enable TWI
TWCR= (1< // Wait for TWINT flag
while (!(TWCR & (1< // Wait for acknowledgement
while((TWSR & 0xF8)!=0x80);
// Get value from TWDR
recv_data=TWDR;
// send the receive value on PORTB
PORTB=recv_data;
}
//Function to match the slave address and slave direction bit(read)
void TWI_match_read_slave(void)
{
// Loop till correct acknoledgement have been received
while((TWSR & 0xF8)!= 0x60)
{
// Get acknowlegement, Enable TWI, Clear TWI interrupt flag
TWCR=(1<
// Wait for TWINT flag
while (!(TWCR & (1< }
}
The code works well in simulation for the very first phase of MasterTransmitter-SlaveReceiver.
However, for the second phase of MasterReceiver-SlaveTransmitter, the simulation seems to show no action and even doesn't step to the MasterTransmitter-SlaveReceiver mode.
Answer
The function TWI_match_read_slave()
looks wrong to me. You have to enable TWAR and TWCR before checking if the slave has done self-addressing.
void TWI_slave_Rx_init()
{
TWBR=1;
//Setting up the SCL frequency by writing a value in TWBR
TWSR|=(0< //Fscl= Fcpu/(16+2*(TWBR)*(4^TWPS))
TWAR=0b00000010;
//The first seven bits indicate the slave address
TWCR|=(1< TWCR|=(1<
//Enabling Acknowledge function
while (!(TWCR & (1< //Wait for the interrupt to be cleared as it will indicate the successful reception
while(TWCR&(0xF8)!=(0x60));
//Checking if the self-address+W has been received and ACK has been sent
}
This is how it should be as setting TWEA alone doesn't mean you've sent the acknowledge bit.
Setting TWEA will generate an acknowledge pulse ONLY IF the following conditions are met:
No comments:
Post a Comment