При отправке байта по I2C Proteus досылает сдвинутый вправо байт, а контроллер получает байт, сдвинутый влево
Посылка по I2C на запись или изменение значения регистра на запись должна выглядеть следующим образом:
S <адрес> <регистр>[ <значение>] P
При этом не должно быть никаких сдвигов. Однако если отлаживать на отладчике I2C Proteus, то он досылает байт, сдвинутый побитово вправо, а контроллер получает байт, сдвинутый влево. Собираю из Atmel Studio 7, SDK встроенный. Как побороть данную проблему?
Код обработчика прерываний от I2C
ISR(TWI_vect)
{
//cli();
switch(TW_STATUS)
{
case TW_SR_DATA_ACK:
// received data from master, call the receive callback
// расчет на то, что при приеме данных первым байтом
// будет регистр, куда будут записываться данные
I2C_recv(TWDR, is_data_recv);
if (is_data_recv == 0) {
is_data_recv = 1;
I2C_ack();
}
else I2C_nack();
//TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_ST_SLA_ACK:
// master is requesting data, call the request callback
I2C_req();
//TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_ST_DATA_ACK:
// master is requesting data, call the request callback
I2C_req();
//TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_BUS_ERROR:
// some sort of erroneous state, prepare TWI to be readdressed
TWCR = 0;
//TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_SR_STOP:
is_data_recv = 0;
I2C_on_stop();
//TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
default:
//TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
}
//sei();
//TWCR |= (1<<TWINT);
TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEN);
}
Код callback
// Прием по I2C регистров/данных
void i2c_receive_cb(uint8_t byte_received, uint8_t is_data) {
if (is_data == 0) regaddr = byte_received;
else regdata = byte_received;
}
// Выдача данных при задание одного из регистров на чтение
void i2c_response_cb() {
uint8_t data_out = 0;
//uint8_t ack = 0;
switch (regdata)
{
case GET_ANALOG:
data_out = (data_block % 2 == 0 ? analog_h[data_block] : analog_l[data_block]);
data_block++;
if (data_block > 15) {
data_block = 0;
I2C_nack();
}
else {
I2C_ack();
}
//ack = 0;
break;
case GET_ERRORS:
data_out = 0x66; // Выдача кода ошибки
I2C_nack();
}
I2C_transmitByte(data_out);
}
// Применение данных из регистра на запись, или сброс счетчика блоков данных
void i2c_on_stop_cb() {
data_block = 0;
}
