Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 8374

Interfacing (DSI, CSI, I2C, etc.) • I2C communication issue between Raspberry Pi 4 and ATtiny1627

$
0
0
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.

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



Viewing all articles
Browse latest Browse all 8374

Trending Articles