Hi everyone, I’m trying to communicate a Raspberry Pi 4 with an ATtiny1627 microcontroller via I2C. When I run the command sudo i2cdetect -y 1 on the Raspberry Pi, it correctly detects the ATtiny1627 and shows its I2C address (0x0C).
The problem comes when I try to send data from the Raspberry Pi (master) to the ATtiny1627 (slave). For example, when I execute sudo i2cget -y 1 0x0C, the first time it returns a wrong value like 0x32, but if I execute it again, it returns 0xFF.
Additionally, I’m using the ATtiny1627 to measure temperatures from several temperature sensors. Each sensor is associated with a specific register address in the slave. Every time I want to read a specific sensor, I send a command from the Raspberry Pi with the corresponding register address, for example using i2c.read_byte_data(i2c_addr, 0) (to obtain the microcontroles address) or i2c.read_i2c_block_data(i2c_addr, 0x55, 4).
The issue is that when I execute these commands (that request a specific register), the Raspberry Pi throws an error and completely loses communication with the microcontroller. After that, if I run sudo i2cdetect -y 1 again, it scans the bus but doesn’t detect any device anymore.
I think the problem might be that when the master sends a command with a register address, it is not being correctly handled in the interrupt routine I programmed in the slave: ISR(TWI0_TWIS_vect) { ... }.
Does anyone know why this might be happening or how I could fix it? Thank you very much for your help! I will attach the slave code below.
The problem comes when I try to send data from the Raspberry Pi (master) to the ATtiny1627 (slave). For example, when I execute sudo i2cget -y 1 0x0C, the first time it returns a wrong value like 0x32, but if I execute it again, it returns 0xFF.
Additionally, I’m using the ATtiny1627 to measure temperatures from several temperature sensors. Each sensor is associated with a specific register address in the slave. Every time I want to read a specific sensor, I send a command from the Raspberry Pi with the corresponding register address, for example using i2c.read_byte_data(i2c_addr, 0) (to obtain the microcontroles address) or i2c.read_i2c_block_data(i2c_addr, 0x55, 4).
The issue is that when I execute these commands (that request a specific register), the Raspberry Pi throws an error and completely loses communication with the microcontroller. After that, if I run sudo i2cdetect -y 1 again, it scans the bus but doesn’t detect any device anymore.
I think the problem might be that when the master sends a command with a register address, it is not being correctly handled in the interrupt routine I programmed in the slave: ISR(TWI0_TWIS_vect) { ... }.
Does anyone know why this might be happening or how I could fix it? Thank you very much for your help! I will attach the slave code below.
Code:
main.c:#include "mcc_generated_files/mcc.h"#include <util/delay.h>#include "ADC_toVoltage_Temperature.h"#include "temperature.h"#include "i2c_Temperature.h"#include <avr/interrupt.h>#include <avr/io.h>#include <util/delay.h>/* Main application*/int main(void){ /* Initializes MCU, drivers and middleware */ SYSTEM_Initialize(); I2C0_Initialize(); // Inicializar I2C esclavo sei(); // Habilitar interrupciones globales Tt1 = 268.15; Tt3 = 268.15; Tt4 = 268.15; Tt5 = 268.15; //_delay_ms(500); ADC_SetVREF(); //Compute Vref while (1){ //thermocouples Tt1 = measure_Tt(1); Tt4 = measure_Tt(4); Tt5 = measure_Tt(9); //thermocouple or RTD bool RTD = false; if (RTD) Tt3 = measure_Tt(33); else Tt3 = measure_Tt(3); ADC_SetVREF(); //monitor supply voltage //_delay_ms(750); }}/** End of File*/Code:
twi0_slave.c:#include "../include/twi0_slave.h"#include <stdbool.h>#include <avr/io.h>#include <util/delay.h>#include <avr/interrupt.h>/* I2C Internal API's *//* Slave */bool I2C0_SlaveIsAddressInterrupt(void);bool I2C0_SlaveIsDataInterrupt(void);bool I2C0_SlaveIsStopInterrupt(void);void I2C0_SlaveOpen(void);void I2C0_SlaveClose(void);bool I2C0_SlaveDIR(void);char I2C0_SlaveReset(void);uint8_t I2C0_SlaveRead(void);char I2C0_SlaveWrite(uint8_t data);bool I2C0_SlaveIsNack(void);void I2C0_SlaveSendAck(void);void I2C0_SlaveSendNack(void);bool I2C0_SlaveIsBusCollision(void);bool I2C0_SlaveIsBusError(void);bool I2C0_SlaveIsTxComplete(void);// Read Event Interrupt Handlersvoid I2C0_ReadCallback(void);void (*I2C0_ReadInterruptHandler)(void);// Write Event Interrupt Handlersvoid I2C0_WriteCallback(void);void (*I2C0_WriteInterruptHandler)(void);// Address Event Interrupt Handlersvoid I2C0_AddressCallback(void);void (*I2C0_AddressInterruptHandler)(void);// Stop Event Interrupt Handlersvoid I2C0_StopCallback(void);void (*I2C0_StopInterruptHandler)(void);// Bus Collision Event Interrupt Handlersvoid I2C0_CollisionCallback(void);void (*I2C0_CollisionInterruptHandler)(void);// Bus Error Event Interrupt Handlersvoid I2C0_BusErrorCallback(void);void (*I2C0_BusErrorInterruptHandler)(void);uint8_t I2C0_Initialize(){ //SDASETUP 4CYC; SDAHOLD OFF; FMPEN disabled; TWI0.CTRLA = 0x00; //Debug Run TWI0.DBGCTRL = 0x00; //Slave Address TWI0.SADDR = 0x0C; //ADDRMASK 12; ADDREN enabled; TWI0.SADDRMASK = 0x19; //DIEN enabled; APIEN enabled; PIEN disabled; PMEN disabled; SMEN disabled; ENABLE enabled; TWI0.SCTRLA = TWI_DIEN_bm | TWI_APIEN_bm | TWI_ENABLE_bm; //ACKACT ACK; SCMD NOACT; TWI0.SCTRLB = 0x00; //Slave Data TWI0.SDATA = 0x00; //DIF disabled; APIF disabled; COLL disabled; BUSERR disabled; TWI0.SSTATUS = 0x00; I2C0_SetWriteCallback(NULL); I2C0_SetReadCallback(NULL); I2C0_SetAddressCallback(NULL); I2C0_SetStopCallback(NULL); I2C0_SetCollisionCallback(NULL); I2C0_SetBusErrorCallback(NULL); return 0;}void I2C0_Open(void){ I2C0_SlaveOpen();}void I2C0_Close(void){ I2C0_SlaveClose();}ISR(TWI0_TWIS_vect){ if (I2C0_SlaveIsBusCollision()) { I2C0_CollisionCallback(); return; } if (I2C0_SlaveIsBusError()) { I2C0_BusErrorCallback(); return; } if (I2C0_SlaveIsAddressInterrupt()) { I2C0_AddressCallback(); if (I2C0_SlaveDIR()) { // Master wishes to read from slave I2C0_ReadCallback(); I2C0_SlaveSendAck(); } return; } if (I2C0_SlaveIsDataInterrupt()) { if (I2C0_SlaveDIR()) { // Master wishes to read from slave if (!I2C0_SlaveIsNack()) { // Received ACK from master I2C0_ReadCallback(); I2C0_SlaveSendAck(); } else { // Received NACK from master I2C0_GotoUnaddressed(); } } else // Master wishes to write to slave { I2C0_WriteCallback(); } return; } // Check if STOP was received if (I2C0_SlaveIsStopInterrupt()) { I2C0_StopCallback(); I2C0_SlaveIsTxComplete(); // To check the status of the transaction return; } if (TWI0.SSTATUS & TWI_APIF_bm) { // Detección de start condition TWI0.SCTRLB = TWI_SCMD_RESPONSE_gc; } if (TWI0.SSTATUS & TWI_DIF_bm) { // Maestro solicita datos TWI0.SDATA = TWI0.SADDR; // Enviar dirección como respuesta TWI0.SCTRLB = TWI_SCMD_RESPONSE_gc; // Continuar transmisión }}uint8_t I2C0_Read(void){ return I2C0_SlaveRead();}void I2C0_Write(uint8_t data){ I2C0_SlaveWrite(data);}void I2C0_Enable(void){ I2C0_SlaveOpen();}void I2C0_SendAck(void){ I2C0_SlaveSendAck();}void I2C0_SendNack(void){ I2C0_SlaveSendNack();}void I2C0_GotoUnaddressed(void){ // Reset module I2C0_SlaveReset();}// Read Event Interrupt Handlersvoid I2C0_ReadCallback(void){ if (I2C0_ReadInterruptHandler) { I2C0_ReadInterruptHandler(); }}void I2C0_SetReadCallback(TWI0_callback handler){ I2C0_ReadInterruptHandler = handler;}// Write Event Interrupt Handlersvoid I2C0_WriteCallback(void){ if (I2C0_WriteInterruptHandler) { I2C0_WriteInterruptHandler(); }}void I2C0_SetWriteCallback(TWI0_callback handler){ I2C0_WriteInterruptHandler = handler;}// Address Event Interrupt Handlersvoid I2C0_AddressCallback(void){ if (I2C0_AddressInterruptHandler) { I2C0_AddressInterruptHandler(); }}void I2C0_SetAddressCallback(TWI0_callback handler){ I2C0_AddressInterruptHandler = handler;}// Stop Event Interrupt Handlersvoid I2C0_StopCallback(void){ if (I2C0_StopInterruptHandler) { I2C0_StopInterruptHandler(); }}void I2C0_SetStopCallback(TWI0_callback handler){ I2C0_StopInterruptHandler = handler;}// Bus Collision Event Interrupt Handlersvoid I2C0_CollisionCallback(void){ if (I2C0_CollisionInterruptHandler) { I2C0_CollisionInterruptHandler(); }}void I2C0_SetCollisionCallback(TWI0_callback handler){ I2C0_CollisionInterruptHandler = handler;}// Bus Error Event Interrupt Handlersvoid I2C0_BusErrorCallback(void){ if (I2C0_BusErrorInterruptHandler) { I2C0_BusErrorInterruptHandler(); }}void I2C0_SetBusErrorCallback(TWI0_callback handler){ I2C0_BusErrorInterruptHandler = handler;}/* Slave Configurations */void I2C0_SlaveOpen(void){ TWI0.SCTRLA |= TWI_ENABLE_bm;}void I2C0_SlaveClose(void){ TWI0.SCTRLA &= ~TWI_ENABLE_bm;}bool I2C0_SlaveIsBusCollision(void){ return TWI0.SSTATUS & TWI_COLL_bm;}bool I2C0_SlaveIsBusError(void){ return TWI0.SSTATUS & TWI_BUSERR_bm;}bool I2C0_SlaveIsAddressInterrupt(void){ return (TWI0.SSTATUS & TWI_APIF_bm) && (TWI0.SSTATUS & TWI_AP_bm);}bool I2C0_SlaveIsDataInterrupt(void){ return TWI0.SSTATUS & TWI_DIF_bm;}bool I2C0_SlaveIsStopInterrupt(void){ return (TWI0.SSTATUS & TWI_APIF_bm) && (!(TWI0.SSTATUS & TWI_AP_bm));}bool I2C0_SlaveDIR(void){ return TWI0.SSTATUS & TWI_DIR_bm;}void I2C0_SlaveSendAck(void){ TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc;}void I2C0_SlaveSendNack(void){ TWI0.SCTRLB = TWI_ACKACT_NACK_gc | TWI_SCMD_COMPTRANS_gc;}bool I2C0_SlaveIsNack(void){ return TWI0.SSTATUS & TWI_RXACK_bm;}bool I2C0_SlaveIsTxComplete(void){ TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc; return TWI0.SCTRLB;}uint8_t I2C0_SlaveRead(void){ return TWI0.SDATA;}char I2C0_SlaveWrite(uint8_t data){ TWI0.SDATA = data; TWI0.SCTRLB |= TWI_SCMD_RESPONSE_gc; return TWI0.SDATA;}char I2C0_SlaveReset(void){ TWI0.SSTATUS |= (TWI_DIF_bm | TWI_APIF_bm); TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc; return TWI0.SSTATUS;}Code:
i2c_temperature.c:#include "i2c_Temperature.h"float Tt1;float Tt3;float Tt4;float Tt5;uint8_t reg;int y = 0;uint8_t* temp;void read_reg() { reg = I2C0_Read();}void write_float() { switch (reg){ case 0x55: temp = (uint8_t*)&Tt1; break; case 0x57: temp = (uint8_t*)&Tt3; break; case 0x58: temp = (uint8_t*)&Tt4; break; case 0x59: temp = (uint8_t*)&Tt5; break; default: break; }}void send_data() { if (reg==0) { I2C0_Write(0x0C); return; } if (!y) write_float(); I2C0_Write(temp[y]); y++;}void clear() { y = 0; reg = 0;}Statistics: Posted by galder — Wed Apr 09, 2025 12:16 pm