Atmega168 och I2C

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
dmiller
Inlägg: 159
Blev medlem: 21 oktober 2010, 23:09:29

Atmega168 och I2C

Inlägg av dmiller »

Har för avsikt att kommunicera mellan 2 st Atmega168 med I2C.
Men för att ta ett steg i taget valde jag att skriva till en PCF8574AP (Remote 8-bit I/O expander) från Atmega168 master, för att testa och lärma mig mer om I2C. Detta för att vara säker på att mjukvaran i mastern fungerar som den skall.

Till det yttre verkar det fungera, skickar data till kretsen och de 8 lysdioderna tänds som de skall.

Men i statusregistret (TWSR) för TWI läser jag av koder som inte ens finns med i databladet (8-bit Atmel Microcontroller with 4/8/16K Bytes In- ystem Programmable Flash, Rev. 2545T–AVR–05/11), sida 224.

Koder som jag borde få efter att,
start skickat: 0x10
SLA_W skickat: 0x18
Data: 0x28

Koder som jag däremot får är,
start skickat: 0A
SLA_W skickat: 1A
Data: 2A

Och när jag kollar på SDA samt SCL med oscilloskopet ser START, ADRESS, och DATA okej ut, men STOPP verkar inte följa databladet:
Efter att DATA och ACK är skickad förblir SDA hög och SCL log. efter ytterligare 26 ms går SDA log under 500 us och därefter går båda höga, tills nästa telegram.

Kod i mastern:

Kod: Markera allt

#define F_CPU 8000000UL
#define SPEED 9600
#define LED_G1 0
#define LED_G2 1
#define LED_G3 2

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

int printCHAR(char character, FILE *stream);

FILE uart_str = FDEV_SETUP_STREAM(printCHAR, NULL, _FDEV_SETUP_RW);

int main(void)
{

	int TWI_TSM = 1;
	
	char data_ut = 33;
	
	DDRB = 0b11111111;
	DDRC = 0b11001111;
	DDRD = 0b11111111;
	
	PORTB = 0b11111111;
	PORTC = 0b11111111;
	PORTD = 0b11111111;

	wdt_disable();
	wdt_enable(WDTO_4S);

	// Init serial port
	USART_init(51);

	// Blinka vid uppstart
	PORTB = ~(1<<LED_G3) | (1<<LED_G2) | (1<<LED_G1);
	_delay_ms(100);
	PORTB = (1<<LED_G3) | ~(1<<LED_G2) | (1<<LED_G1);
	_delay_ms(100);
	PORTB = (1<<LED_G3) | (1<<LED_G2) | ~(1<<LED_G1);
	_delay_ms(100);
	PORTB = (1<<LED_G3) | (1<<LED_G2) | (1<<LED_G1);
	_delay_ms(100);


	// TWI init, SCL = 1945 Hz
	TWBR = 128;
	TWSR |= (1<<TWPS1);
	TWSR &= ~(1<<TWPS0);

	// printf...	
	stdout = &uart_str;

	while(1)
	{
		
		
		// TWI Start
		if(TWI_TSM == 1)
		{
			printf("1, TWSR = %d\n\r", TWSR);
			
			TWCR |= (1<<TWEN);
			TWCR |= (1<<TWSTA);
			TWCR &= ~(1<<TWSTO);
			TWCR |= (1<<TWINT);
			
			TWI_TSM = 2;
		}	
		

//		if((TWI_TSM == 2) && (TWCR & (1<<TWINT)) && (TWSR == 0x10))
		if((TWI_TSM == 2) && (TWCR & (1<<TWINT)))
		{
			printf("2, TWSR = %d\n\r", TWSR);

			TWI_TSM = 3;
		}			
			
		// TWI SLA_W
		if(TWI_TSM == 3)
		{
			
			printf("3, TWSR = %d\n\r", TWSR);

			TWDR = 112;		
			TWCR |= (1<<TWEN);
			TWCR &= ~(1<<TWSTA);
			TWCR &= ~(1<<TWSTO);
			TWCR |= (1<<TWINT);

			TWI_TSM = 4;
		}		

//		if((TWI_TSM == 4) && (TWCR & (1<<TWINT)) && (TWSR == 0x18))
		if((TWI_TSM == 4) && (TWCR & (1<<TWINT)))
		{
			printf("4, TWSR = %d\n\r", TWSR);
			TWI_TSM = 5;
		}

		
		// TWI Data
		if(TWI_TSM == 5)
		{
			
			printf("5, TWSR = %d\n\r", TWSR);
			TWDR = data_ut;
			TWCR |= (1<<TWEN);
			TWCR &= ~(1<<TWSTA);
			TWCR &= ~(1<<TWSTO);
			TWCR |= (1<<TWINT);

			data_ut++;
			
			TWI_TSM = 6;
		}		

//		if((TWI_TSM == 6) && (TWCR & (1<<TWINT)) && (TWSR == 0x28))
		if((TWI_TSM == 6) && (TWCR & (1<<TWINT)))
		{
			printf("6, TWSR = %d\n\r", TWSR);
			TWI_TSM = 7;
		}

		
		// TWI Stopp
		if(TWI_TSM == 7)
		{
			printf("7, TWSR = %d\n\r", TWSR);
			
			TWCR |= (1<<TWEN);
			TWCR |= (1<<TWSTO);
			TWCR |= (1<<TWINT);

			TWI_TSM = 8;
		}		
		
		if(TWI_TSM == 8)
		{
			printf("8, TWSR = %d\n\r", TWSR);
			TWI_TSM = 1;
		}


		//Blinka lite..
		PORTB |= (1<<LED_G1);
		_delay_ms(100);
		PORTB &= ~(1<<LED_G1);
		_delay_ms(100);
		

	

		// Kick the dog..
		wdt_reset();
		
	}
}



void USART_init( unsigned int ubrr ) 
{
	UBRR0H = (unsigned char)(ubrr>>8);
	UBRR0L = (unsigned char)ubrr;
	UCSR0B = (1 << TXEN0);		// Enable receiver, transmitter & RX interrupt
	UCSR0C = (3 << UCSZ00);	//asynchronous 8 N 1
}

int printCHAR(char character, FILE *stream)
{
while ((UCSR0A & (1 << UDRE0)) == 0) {};
UDR0 = character;
return 0;
} 
Någon som har en idé om vad som kan vara knas?

Tack på förhand, David!
Användarvisningsbild
hanzibal
EF Sponsor
Inlägg: 2499
Blev medlem: 7 september 2010, 20:54:58
Ort: Malmö/Lund

Re: Atmega168 och I2C

Inlägg av hanzibal »

Kan väl inte vara så att du glömt pullups på sda och scl?
Skriv svar