Итак, я пытаюсь установить соединение между ATMEGA328p в качестве мастера и чипом EEPROM 24LC256 с использованием протокола I2C.
Код:
#define FOSC 16000000UL
#define START 0x08
#define MT_SLA_ACK 0x18
#define MT_SLA_NACK 0x18
#define DEV_ADDR 0x50
typedef enum result_t{FAIL, SUCCESS}result;
void Debug_LED_ON()
{
PORTD|=1<<PD4; //Turn on LED on PIN4 of PORTD
}
void set_clock(int freq_in_khz)
{
TWCR = 1<<TWEN; //Enable TWI module
TWSR |=(1<<TWPS0); //Prescaler set to 4
TWBR = FOSC/freq_in_khz;
TWBR -= 16;
TWBR /= 8; //2*Prescaler_value
}
void send_start()
{
TWCR= ( (1<<TWINT) | (1<<TWEN) | (1<<TWSTA) ); //send START
while( !(TWCR & (1<<TWINT)) ) ; //wait for TWINT flag SET
}
void send_stop()
{
TWCR= ( (1<<TWINT) | (1<<TWEN) | (1<<TWSTO) ); //send STOP
//while( !(TWCR & (1<<TWINT)) ) ; //wait for TWINT flag SET
}
result check_start_status()
{
if ((TWSR & 0xF8) == START )
return SUCCESS;
else
return FAIL;
}
void send_address(char addr_w)
{
TWDR=addr_w; //7bit address + W bit (write bit)
TWCR = (1<<TWINT) | (1<<TWEN); //Clear TWINT bit to start transmission of address
while (!(TWCR &(1<<TWINT))); //wait for TWINT flag SET
}
result check_MT_slave_ack()
{
if ((TWSR & 0xF8) == MT_SLA_ACK )
return SUCCESS;
else
return FAIL;
}
result check_MT_slave_nack()
{
if ((TWSR & 0xF8) == MT_SLA_NACK )
return SUCCESS;
else
return FAIL;
}
void transmit_data(char data)
{
TWDR=data;
TWCR = (1<<TWINT) | (1<<TWEN); //Clear TWINT bit to start transmission of Data on the bus
while (!(TWCR &(1<<TWINT))); //wait for TWINT flag SET
}
int main (void)
{
DDRC=0xff;
PORTC=0x30; //Enable internal pullups on PORTC PINS SDA(PC4) , SCL(PC5)
DDRD=0xFF; //Port D as output
set_clock(100); //setting clock 100KHz
send_start();
if(check_start_status()==FAIL)
Debug_LED_ON();
send_address(DEV_ADDR << 1);
if(check_MT_slave_ack()==FAIL)
Debug_LED_ON();
transmit_data(0x00);
if(check_MT_slave_ack()==FAIL) //fails here!
Debug_LED_ON();
return 0;
}
Думаю, что-то не так с кодом или с тем, как я отправляю адрес! Биты A2, A1, A0 24LC256 установлены на землю, поэтому адрес устройства 0x50 << 1.
Адрес устройства теперь отправляется правильно, теперь, когда я отправляю MSB адреса на чип, куда я хочу записать данные, это не удается!
Значение, которое вы устанавливаете в send_address()
функции, смещено на один бит. Адрес чипа 0x50
представляет собой 7-битное число, которое необходимо сдвинуть на 1 бит вверх при отправке по шине I2C (самый младший бит — флаг чтения/записи). Таким образом, вы должны использовать send_address(0xa0)
(то есть 0x50<<1
) в своем коде или выполнять send_address()
функцию сдвига внутри.
Под «когда я отправляю адрес +/W, я не получаю ни ACK, ни NACK», вы имеете в виду, что ваш код зависает в while (!(TWCR &(1<<TWINT)));
цикле внутри send_address()
? Если да, то это другая проблема, не связанная с указанным выше адресом.
Абель Том