I2C en atmega328p

0

Estoy intentando ejecutar un dispositivo I2C con el atmega328p (en una placa personalizada). He leído la hoja de datos y escribí el código "exactamente" como se muestra en él: aquí está el código:

#define F_CPU 1000000
#define SCL_CLOCK 50000
#define BAUD 9600
#define MYUBRR    F_CPU/8/BAUD-1
#define TWIMUX  0x1C 


#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <util/twi.h>
#include <avr/interrupt.h>


// printf to debug 
static int uart_putchar(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,_FDEV_SETUP_WRITE);
// initializing the UART 
void init_uart(unsigned short uValue  ){
    // setting the baud rate
    UBRR0H =(unsigned char)  ( uValue>> 8);  // 0x00
    UBRR0L =(unsigned char) uValue;  // 0x0C
    // enabling TX & RX
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    UCSR0A = (1<<UDRE0)|(1<<U2X0);
    UCSR0C =  (1 << UCSZ01) | (1 << UCSZ00);    // Set frame: 8data, 1 stop

}

void init_i2c(void ) {
     uint8_t   twst;
     TWSR = 0;                         // no prescaler
     TWBR = ((F_CPU/SCL_CLOCK)-16)/2; 
     TWCR = (1<<(TWINT))|(1<<TWSTA )|(1<<TWEN);
     printf("TWCR 0x%x \n",TWCR);
     while(!(TWCR & (1<< TWINT)));
     printf(" Start condition has been transmitted \n");
     if( (TWSR&0xF8) != TW_START){
         printf(" Error \n");
     }
     // Setting Address 
     TWDR = 0x1C; 
     // cleating TWCR 
     TWCR = (1<<TWINT) |(1<<TWEN);
    if ((TWSR & 0xF8) != TW_MT_SLA_ACK){
         printf(" Error at TWSR   0x%x\n", TWSR);  // here is the problem !!!!!!!!!  TWSR value should be 0x18
         return; 
    }       
 }


static int uart_putchar(char c, FILE *stream)
{
    if (c == '\n')
    uart_putchar('\r', stream);
    while ( !( UCSR0A & (1<<UDRE0)) );
    UDR0 = c;
    return 0;
}
int main(void)
{
    unsigned short i = 0 ; 
    // UART init and printf 
    init_uart(MYUBRR);
    stdout = &mystdout;
    sei();
    init_i2c();


    while(1){

    }

    return 0;
}

Comopuedeverenlasalida,¡tengounerrorconelvalorTWSR!Primero,penséquelafrecuencianoestáconfiguradacorrectamente,perolahemedidoydefinitivamenteesde50kHz.HemedidoSDAySCLyaquíestálafotodelalcance:

por lo que he aprendido, ambos cables deben estar en alto? ¡He enchufado una placa arduino en este chip y funcionó bien! así que el problema está definitivamente en la configuración, (mi código).

¿Alguna idea de cómo podría resolver esto?

gracias de antemano!

    
pregunta Engine

1 respuesta

1

Después de esta línea:

TWCR = (1<<TWINT) |(1<<TWEN);

Debe esperar a que se establezca el bit TWINT:

while (!(TWCR & (1<<TWINT)));

Esto en la etapa 4 en la tabla en la página 216 de la hoja de datos.

Sin esta línea, su código comprueba el ACK al inicio de la transmisión, no cuando se ha completado.

En general, siempre que haga algo que cambie el estado del bus i2c (enviar un bit de inicio, enviar una dirección, enviar / recibir datos), debe esperar hasta que el hardware i2c indique que ha procesado el cambio y está listo para continuar.

    
respondido por el jfowkes

Lea otras preguntas en las etiquetas