ATTiny USI I2C inledning - en kraftfull, snabb och bekväm kommunikationsgränssnitt för ATTiny projekt! (7 / 8 steg)
Steg 7: ATTiny USI I2C kod genomförandet - USI I2C slav
Så, som en slutanvändare, är du förmodligen mer intresserad av hur gränssnittet biblioteket till din egen kod! Detta är lätt, och här är varför. Jag har gjort bort med de ta emot/Transmissionsbuffert som användes i andra USI I2C implementeringar (främst de som baseras på AVR312 app-note) och istället implementeras den registrera bank protokollet beskrivs i början av denna handledning. Banken lagras som en matris med pekare, inte datavärden, så du måste bifoga lokala variabler i koden till minnesadresser i I2C registrera bank genom att ange pekare till peka på dina variabler. Detta innebär att stambanan koden har inte någonsin att avsöka I2C buffertar eller hantera data ankomster, värdena uppdateras omedelbart när de anländer. Det gör också programmet variabler att vara tillfrågade när som helst av I2C-gränssnittet utan att påverka stambanan koden (än förseningen på grund av avbrott). Det är ett ganska snyggt system. Låt oss återigen ta ett kort exempel.
Till exempel, låt oss säga att vi har en mycket grundläggande programvara PWM generator som driver en LED. Vi vill ha möjlighet att ändra PWM-värde (ett 16 - bitarsvärde, bara för att lära sig om pekare) utan att göra den huvudloop komplicerat. Med magiskt av asynkrona I2C slav, kan vi göra just det!
#include "usi_i2c_slave.h"
Definiera en referens till I2C slav register bank pekaren matris
extern char * USI_Slave_register_buffer [];
int main)
{
Skapa värde för 16-bitars PWM
unsigned int pwm_val = 0;
Tilldela den pwm-värde låg byten till I2C interna adress 0x00
Tilldela pwm värdet övre byte till I2C interna adress 0x01
USI_Slave_register_buffer [0] = (unsigned char *) & pwm_val;
USI_Slave_register_buffer [1] = (unsigned char *)(&pwm_val) + 1;
Initiera I2C slav med slav enhetsadress 0x40
USI_I2C_Init(0x40);
Ställa in pin A0 som utgång för LED (antar vi att oavsett chip vi på har pin A0 tillgängliga)
DDRA | = 0X01;
While(1)
{
PORTA | = 0X01; Aktivera LED
för (unsigned int jag = 0; jag < pwm_val; i ++)
{
PORTA & = ~ (0x01); Inaktivera LED
}
}
}
Och där har du det! Stora slingan hänvisar inte till I2C alls, men på skickar en PWM-värde på 16-bitars plats i I2C interna adress 0x00/0x01, kan vi helt kontrollera PWM LED! För extra stabilitet (se till att endast de pekare värden du använder är tillgängliga och att förhindra herrelösa pekare) föreslår jag att du ändrar #define USI_SLAVE_REGISTER_COUNT vara antalet register pekare du behöver, inte fler, inte färre. När en tillgång (läsa och skriva) görs på ett register index utanför intervallet 0x00 till USI_SLAVE_REGISTER_COUNT - 1, så skrivs ingenting och returneras noll.