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<avr/io.h>
#include<util/delay.h>
#include<inttypes.h>
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<<TWPS1)|(0<<TWPS0); // Setting prescalar bits
// 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<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR & (1<<TWINT))); // Wait till start condition is transmitted
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<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR & (1<<TWINT))); // wait till restart condition is transmitted
while((TWSR & 0xF8)!= 0x10); // Check for the acknowledgement
}
void TWI_write_address(unsigned char data)
{
TWDR=data; // Address and write instruction
TWCR=(1<<TWINT)|(1<<TWEN); // Clear TWI interrupt flag,Enable TWI
while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
while((TWSR & 0xF8)!= 0x18); // Check for the acknowledgement
}
void TWI_read_address(unsigned char data)
{
TWDR=data; // Address and read instruction
TWCR=(1<<TWINT)|(1<<TWEN); // Clear TWI interrupt flag,Enable TWI
while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte received
while((TWSR & 0xF8)!= 0x40); // Check for the acknowledgement
}
void TWI_write_data(unsigned char data)
{
TWDR=data; // put data in TWDR
TWCR=(1<<TWINT)|(1<<TWEN); // Clear TWI interrupt flag,Enable TWI
while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
while((TWSR & 0xF8) != 0x28); // Check for the acknowledgement
}
void TWI_read_data(void)
{
TWCR=(1<<TWINT)|(1<<TWEN); // Clear TWI interrupt flag,Enable TWI
while (!(TWCR & (1<<TWINT))); // Wait till complete TWDR byte transmitted
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<<TWINT)|(1<<TWEN)|(1<<TWSTO);
while(!(TWCR & (1<<TWSTO))); // Wait till stop condition is transmitted
}
While the code of the Slave chip is:
#include<avr/io.h>
#include<util/delay.h>
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<<TWEN)|(1<<TWINT);
// 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<<TWEA)|(1<<TWEN)|(1<<TWINT);
while (!(TWCR & (1<<TWINT))); // Wait for TWINT flag
}
}
void TWI_read_slave(void)
{
// Clear TWI interrupt flag,Get acknowledgement, Enable TWI
TWCR= (1<<TWINT)|(1<<TWEA)|(1<<TWEN);
// Wait for TWINT flag
while (!(TWCR & (1<<TWINT)));
// 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<<TWEA)|(1<<TWEN)|(1<<TWINT);
// Wait for TWINT flag
while (!(TWCR & (1<<TWINT)));
}
}
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.