atmel i2c slave mode
atmel i2c slave mode
Jag har suttit här ett tag och pillat endel kod och läst databladen hundra gånger gällande att använda twi i slave läge.
men jag verkar inte få det att lira.
så jag undrar ifall någon vet någon guide eller bättre förklaring på hur jag ska använda i2c slave läge.
Som master får jag det att funka bekymmers fritt men begriper mig inte på dokumentationen över hur det ska funka i slave läge.
men jag verkar inte få det att lira.
så jag undrar ifall någon vet någon guide eller bättre förklaring på hur jag ska använda i2c slave läge.
Som master får jag det att funka bekymmers fritt men begriper mig inte på dokumentationen över hur det ska funka i slave läge.
Re: atmel i2c slave mode
Titta på appnote AVR311 en bit ner på den här sidan. Den medföljande koden (om du klickar på cd-skivan) hjälpte mig att få igång det.
Re: atmel i2c slave mode
Ja, AVR311 är ett bra tips!
Men läs koden och kommentarerna noga! Jag har fått TWI att snurra med hjälp av denna, men det tog många timmar! Oscilloskop absolut nödvändigt.
Atmelkoden ser i alla fall ut att fungera korrekt.
Det är väl bara att beklaga att det är så jobbigt och tidsödande att tränga in i de här sakerna, men det är väl digitalteknikens eviga förbannelse.
Men läs koden och kommentarerna noga! Jag har fått TWI att snurra med hjälp av denna, men det tog många timmar! Oscilloskop absolut nödvändigt.
Atmelkoden ser i alla fall ut att fungera korrekt.
Det är väl bara att beklaga att det är så jobbigt och tidsödande att tränga in i de här sakerna, men det är väl digitalteknikens eviga förbannelse.
Re: atmel i2c slave mode
Dendär koden motsäger databladet :/
TWSR == 0xA8 Own SLA+R has been received. Så står det att man ska ladda databyte i TWDR och ställa 0xC4/0x84 men i appnoten ser det ut såhär.
Jag blir väldigt förvirrad måste jag säga.
TWSR == 0xA8 Own SLA+R has been received. Så står det att man ska ladda databyte i TWDR och ställa 0xC4/0x84 men i appnoten ser det ut såhär.
Kod: Markera allt
case TWI_STX_ADR_ACK: // Own SLA+R has been received; ACK has been returned
// case TWI_STX_ADR_ACK_M_ARB_LOST: // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
TWI_bufPtr = 0;
Re: atmel i2c slave mode
Du måste ju kolla all kod som körs i det fallet. Vet du inte hur en switch/case-sats fungerar? Notera avsaknaden av break.
Re: atmel i2c slave mode
var typ ett årsedan jag använde en sådan.
men då var det inga konstigheter då.
Nästa break kommer efter data ack som ska göra samma sak. men räkna upp
men då var det inga konstigheter då.
Nästa break kommer efter data ack som ska göra samma sak. men räkna upp
Re: atmel i2c slave mode
Bra, tillräckligt många uppfräschningar av minnet så sitter det till slut 
Fungerar det att köra som slave nu eller?

Fungerar det att köra som slave nu eller?
Re: atmel i2c slave mode
Fick precis ett svar f** va glad jag blev.
Dock så fick jag flera hundra av samma svar när det bara skulle vara ett. så får finputsa på koden någon stanns.
Har skrivit om alltihopa till pulling då det verkar väldigt dummt att köra detta i interrupt när man inte kan köra globala variabler i interrupt i winavr. (volatile funkar men dom funkar ju bara i en fil eller?)
Är helt snurrig i huvudet nu efter att ha suttit hela natten. brukar ju gå och lägga mig vid 04-05 tiden men nu är ju klockan 09:30
Men har man gett sig f** på att man ska lösa ett bekymmer innan man går och lägger sig så har man. Började dra ut på tiden dethär då jag skrivit om koden typ hundra gånger senaste veckan.
Dock så fick jag flera hundra av samma svar när det bara skulle vara ett. så får finputsa på koden någon stanns.
Har skrivit om alltihopa till pulling då det verkar väldigt dummt att köra detta i interrupt när man inte kan köra globala variabler i interrupt i winavr. (volatile funkar men dom funkar ju bara i en fil eller?)
Är helt snurrig i huvudet nu efter att ha suttit hela natten. brukar ju gå och lägga mig vid 04-05 tiden men nu är ju klockan 09:30
Men har man gett sig f** på att man ska lösa ett bekymmer innan man går och lägger sig så har man. Började dra ut på tiden dethär då jag skrivit om koden typ hundra gånger senaste veckan.
Re: atmel i2c slave mode
det funkar om du vill dela mellan filerna.
Titta på volatile och extern...
Titta på volatile och extern...
Re: atmel i2c slave mode
Börjar känna mig lite förvirrad nu igen.
När jag skickar data till datorn får inte vad jag skickat. utan får en 0a nu
Om jag räknar upp CC_data.txi så skickar den ingen data alls till mig.
Jag måste ha gjort någon miss i funktionen som jag inte ser. Någon som kan hitta den åt mig ?
om jag använder CC_data.twi_dataptr så får jag bara en tvåa som svar hela tiden vad jag än stoppar in i den.
EDIT hade visst glömt lägga in den andra funktionen. som hanterar pekaren
När jag skickar data till datorn får inte vad jag skickat. utan får en 0a nu
Om jag räknar upp CC_data.txi så skickar den ingen data alls till mig.
Jag måste ha gjort någon miss i funktionen som jag inte ser. Någon som kan hitta den åt mig ?
om jag använder CC_data.twi_dataptr så får jag bara en tvåa som svar hela tiden vad jag än stoppar in i den.
EDIT hade visst glömt lägga in den andra funktionen. som hanterar pekaren
Kod: Markera allt
struct CC_reg
{
uint16_t storlek; //räknare som används vid inläsning och utskrift av jpeg bild.
uint8_t img_JPG[IMG_MAX_BYTES];//här lagras bilden
uint8_t is_img;//varibel att hålla reda på om det finns en bild i ram eller ej.
uint8_t storlekH; //high byte av storlek
uint8_t storlekL; //low byte av storlek
uint8_t twi_adress;
uint8_t twi_reg;
uint8_t twi_status;
uint8_t twi_data;
uint8_t *twi_dataptr;
char twi_recived_data[1];//[0]=register [1]=data (använder bara register nu)
uint16_t twi_data_size;
uint16_t txi;
uint16_t rxi;
uint8_t test[1];
}CC_data;
void i2c_slave_status_machine(void)
{
twi_bussy();
CC_data.twi_status = TWSR;
switch (CC_data.twi_status)
{
//////////////////////////////////////////////////
//Transmit
case TWI_STX_ADR_ACK:
CC_data.txi = 0;
case TWI_STX_DATA_ACK:
//TWDR = *(CC_data.twi_dataptr + CC_data.txi); //använder jag denna får jag enbart en tvåa som svar :/
TWDR = CC_data.test[CC_data.txi];
//CC_data.txi++; //(om jag använderm ig av uppräkning här får jagi ngen data alls)
TWCR = 0xC4; //11000100 twen = 1, twint = 1, twea = 1
break;
case TWI_STX_DATA_NACK:
if(CC_data.txi == CC_data.twi_data_size)
{
TWCR = 0xC4;
}
break;
/////////////////////////////////////////////////
//Recive
case TWI_SRX_ADR_ACK:
CC_data.rxi = 0;
TWCR = 0xC4;
break;
case TWI_SRX_ADR_DATA_ACK:
case TWI_SRX_ADR_DATA_NACK:
CC_data.twi_recived_data[CC_data.rxi++] = TWDR;
TWCR = 0xC4; //11000100 twen = 1, twint = 1, twea = 1
if (CC_data.rxi == 0)
{
i2c_slave_recive_machine();
}
break;
case TWI_SRX_STOP_RESTART:
case TWI_STX_DATA_ACK_LAST_BYTE:
TWCR = 0xC4;
break;
}
}
void i2c_slave_recive_machine(void)
{
if(CC_data.twi_recived_data[0] == 0)
{
CC_data.test[0] = '1';
CC_data.twi_dataptr = CC_data.test;
CC_data.twi_data_size = 1;
CC_data.twi_recived_data[0] = 255;
}
}
Senast redigerad av eAk 17 augusti 2009, 16:54:14, redigerad totalt 1 gång.
Re: atmel i2c slave mode
Det där med att jobba på nätterna tror jag inte är en bra idé, men det kan vara individueelt.
Jag kan inte sätta mig in i detaljerna i koden ovan, men det förefaller som du vill göra en ISR alias interrupt service rutin. En ISR måste kopplas till ett fysiskt avbrott.
Det skall se ut så här:
TWI_vect skall finnas i en headerfil:
#define TWI_vect _VECTOR(24) /* Two-wire Serial Interface */
_VECTOR(24) i sin tur kopplar till rätt avbrottslinje.
Troligen vinner man ingenting på att skriva en egen ISR, utan det är lika bra att ta den som finns i Atmelkoden TWI_isr.c.
Det som man skriver själv i sitt huvudprogram kan se ut så här
(Det finns nog fler och bättre exempel i Atmelkoden):
Jag kan inte sätta mig in i detaljerna i koden ovan, men det förefaller som du vill göra en ISR alias interrupt service rutin. En ISR måste kopplas till ett fysiskt avbrott.
Det skall se ut så här:
Kod: Markera allt
ISR (TWI_vect)
{
...
}
TWI_vect skall finnas i en headerfil:
#define TWI_vect _VECTOR(24) /* Two-wire Serial Interface */
_VECTOR(24) i sin tur kopplar till rätt avbrottslinje.
Troligen vinner man ingenting på att skriva en egen ISR, utan det är lika bra att ta den som finns i Atmelkoden TWI_isr.c.
Det som man skriver själv i sitt huvudprogram kan se ut så här
(Det finns nog fler och bättre exempel i Atmelkoden):
Kod: Markera allt
/*
* Denna kod är bara ett exempel.
* Det fungerar sannolikt inte utanför sin kontext!
*/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include "TWI_slave.h"
#include "../commons.h" /* Sample TWI transmission commands */
int
main (void)
{
unsigned char messageBuf[10];
unsigned char TWI_slaveAddress;
DDRD = 0b11100011; /* bit 3..0, pin 5..2 */
DDRB = 0x3F; /* bit 3..0, pin 17, 16 ,15, 14 */
DDRC = 0x00; /* bit 3..0, pin 28..23 */
setup_timer0 ();
setup_timer1 (); /* Two PWM signals; generates interrupts. */
setup_timer2 (); /* One PWM signal, syncronized with timer1 */
setup_adc ();
TWI_Slave_Initialise ((TWI_slaveAddress << TWI_ADR_BITS) |
(TRUE << TWI_GEN_BIT));
sei ();
TWI_Start_Transceiver ();
for (;;)
{
if (!TWI_Transceiver_Busy ())
{
if (TWI_statusReg.lastTransOK)
{
if (TWI_statusReg.RxDataInBuf)
{
TWI_Get_Data_From_Transceiver (messageBuf, 6);
if (TWI_statusReg.genAddressCall)
{
;
}
else
{
if (messageBuf[0] == TWI_CMD_MASTER_WRITE)
{
;
}
else if (messageBuf[0] == TWI_CMD_MASTER_READ)
{
cli ();
/*
* Här utväxlas egna data med messageBuf[]
* MessageBuf tas emot och skickas till
* master när avbrottet hanteras.
*/
messageBuf[0] = adcval4;
messageBuf[1] = ticks16;
pos_control = messageBuf[3] & 0x00ff;
pos_control |= (messageBuf[2] << 8) & 0xff00;
messageBuf[5] = e8stimated_pos2;
messageBuf[4] = (e8stimated_pos2 >> 8);
sei ();
TWI_Start_Transceiver_With_Data (messageBuf, 6);
}
}
}
else
asm ("nop");
if (!TWI_Transceiver_Busy ())
TWI_Start_Transceiver ();
}
else
TWI_Act_On_Failure_In_Last_Transmission (TWI_Get_State_Info ());
}
asm ("nop");
}
}
Re: atmel i2c slave mode
Hela tanken är att det är pulling.
så att jag slipper använda interrupt.
main kallar i2c_slave_status_machine();
med jämna mellan rum.
Denhär delen i koden kallar hanterar funktionen för vad som mottagits och vad som ska skickas ut.
Tanken är att en pekare ska sköta det och skicka ut img_JPG då den skiftar i storlek från bild till bild.
så att jag slipper använda interrupt.
main kallar i2c_slave_status_machine();
med jämna mellan rum.
Denhär delen i koden kallar hanterar funktionen för vad som mottagits och vad som ska skickas ut.
Tanken är att en pekare ska sköta det och skicka ut img_JPG då den skiftar i storlek från bild till bild.
Kod: Markera allt
case TWI_SRX_ADR_DATA_ACK:
case TWI_SRX_ADR_DATA_NACK:
CC_data.twi_recived_data[CC_data.rxi++] = TWDR;
TWCR = 0xC4; //11000100 twen = 1, twint = 1, twea = 1
if (CC_data.rxi == 0)
{
i2c_slave_recive_machine();
}
break;
Re: atmel i2c slave mode
Vadå _slipper_ använda interrupt? Om du laddar ner koden till appnoten så finns ju en färdig c-fil där som använder interrupt har jag för mig. Bara att ladda in och lägga till några initieringsrader i din main.