#include <mega128.h>
#include <delay.h>
#include <stdio.h>
unsigned char ucNack=0;
unsigned char ucHibyte=0;
unsigned char ucLobyte=0;
unsigned char lo_byte=0;
unsigned char hi_byte=0;
void nops(unsigned char num)
{
unsigned char i;
for(i=0 ; i<num ;i++)
{
delay_us(1);
}
}
void twi_init(void)
{
DDRD |= 0x03; // Set SCL, SDA to output
PORTD |= 0x03; // Set SCL, SDA High
}
void twi_start(void)
{
DDRD |= 0x02; // Set SDA to output
PORTD = 0x03; // Set SCL, SDA High
delay_us(10);
PORTD &= 0xFD; // Clear SDA
delay_us(1);
PORTD &= 0xFE; // Clear SCL
delay_us(10);
}
void twi_stop(void)
{
DDRD |= 0x02; // Set SDA to output
PORTD &= 0xFD; // Clear SDA Low
PORTD &= 0xFE; // Clear SCL Low
delay_us(10);
PORTD |= 0x01; // Set SCL High
delay_us(10);
PORTD |= 0x02; // Set SDA High
}
void twi_clock(void)
{
PORTD |= 0x01; // Set SCL High
delay_us(10); // Small delay
PORTD &= 0xFE; // Clear SCL Low
delay_us(10);
}
unsigned char twi_ackn(void)
{
unsigned char ackn = 0; // Temp RAM for Ackn flag
PORTD &= 0xFE; // Clear SCL Low
DDRD &= 0xFD; // Set SDA to input
PORTD |= 0x01; // Clock the ACK bit
delay_us(10);
if((PIND & 0x02) == 0x02) ackn=1; // Check the ACK bit on SDA
else ackn =0;
nops(7);
//printf("ackn= : %d \n", ackn);
PORTD &= 0xFE; // Clear SCL Low
delay_us(10);
DDRD |= 0x02;
PORTD &= 0xFD; // Clear SDA Low
return ackn; // Return our ACK bit
}
void write_twi_byte(unsigned char byte)
{
unsigned char i;
DDRD |= 0x02; // Set SDA to output
PORTD &= 0xFE; // Clear SCL Low
delay_us(10);
for (i=0; i<8 ; i++)
{
delay_us(5);
if((byte & 0x80)==0x80) PORTD |= 0x02; // Set SDA High
else PORTD &= 0xFD; // Clear SDA Low
PORTD |= 0x01; // Set SCL High, Clock data
delay_us(10);
byte = byte << 1; // Shift data in buffer right one
delay_us(10); // Small delay
PORTD &= 0xFE; // Clear SCL
nops(12); // Small delay
delay_us(10);
}
PORTD &= 0xFD; // Clear SDA Low
if(twi_ackn()==1) ucNack=1;
// while(twi_ackn()); // Check for acknowledge from I2C device
}
unsigned char read_twi_byte(unsigned char ch)
{
unsigned char i, buff=0;
DDRD |= 0x02; // Set SDA to Output
PORTD &= 0xFD;
nops(2);
for(i=0; i<8; i++)
{
buff <<= 1;
DDRD &= 0xFD; // Set SDA to input
PORTD |= 0x01; // Set SCL High, Clock bit out
delay_us(10);
nops(10); // Small delay
delay_us(10);
// Read data on SDA pin
if ((PIND & 0x02)==0x02) {
buff |= 0x01;
}
PORTD &= 0xFE; // Clear SCL
delay_us(10);
nops(12); // Small delay
}
DDRD |= 0x02; // Set SDA to Output
if(ch==0) // Ack
{
PORTD &= 0xFD; // Clear SDA Low
twi_clock();
}
else // No Ack
{
PORTD |= 0x02; // Clear SDA High
twi_clock();
nops(8); // Small delay
PORTD &= 0xFD; // Clear SDA Low
nops(4); // Small delay
PORTD |= 0x02; // Clear SDA High
}
return buff;
}
void read_data(unsigned char add)
{
ucHibyte=0;
ucLobyte=0;
twi_start();
write_twi_byte(0x38); //slave address
delay_us(10);
write_twi_byte(0x38);
delay_us(10);
twi_start();
delay_us(10);
write_twi_byte(0x39);
delay_us(10);
ucLobyte=read_twi_byte(0);
delay_us(10);
ucHibyte=read_twi_byte(1);
delay_us(10);
twi_stop();
if (ucNack==1) printf("\n\rNo Ack!!!");
else {
printf("\n\rRead Data[%02X] = %02X %02X \n\r", add, ucLobyte, ucHibyte);
}
ucNack=0;
}
void main(void)
{
// USART0 initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART0 Receiver: Off
// USART0 Transmitter: On
// USART0 Mode: Asynchronous
// USART0 Baud Rate: 57600
UCSR0A=0x00;
UCSR0B=0x08;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x10;
printf("asdf");
twi_init();
while(1){
read_data(0x38);
delay_ms(100);
}
}