Zbernica i2c: Rozdiel medzi revíziami
Z SensorWiki
Riadok 14: | Riadok 14: | ||
<source lang="c"> | <source lang="c"> | ||
+ | #include <avr/interrupt.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <avr/io.h> | ||
+ | #include <util/delay.h> | ||
+ | #include <util/twi.h> | ||
+ | #include <stdio.h> | ||
− | + | //#include "lcd.h" | |
+ | #include "Uart_ch.h" | ||
− | + | unsigned char RD_EEprom(unsigned char adr_RAM); | |
− | + | void WR_EEprom(unsigned char adr_IC,unsigned char adr_pocitadlo); | |
− | + | void obsluha_Stav_Aut_I2C(void); | |
− | |||
− | |||
− | |||
− | |||
− | + | #define ADR_IC_WR 0xA0 // EEPROM Adresa IC+WR | |
− | + | #define ADR_IC_RD 0xA1 // EEPROM Adresa IC+RD | |
− | |||
− | |||
− | + | ||
− | } | + | volatile unsigned char buffer_I2C[10]; // buffer pre obsluhu I2C |
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | FILE mystdout_Uart = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE); | ||
+ | |||
+ | |||
+ | void WR_EEprom(unsigned char adr_IC,unsigned char adr_pocitadlo) | ||
+ | { // nastavenie globalnych premennych | ||
+ | |||
+ | buffer_I2C[0]=adr_IC; // Adr obvodu + wr | ||
+ | buffer_I2C[1]=adr_pocitadlo; // Nastavenie Adresneho citaca 24LC04 , Adresa (z ktorej citam)/(do ktorej zapisujem) | ||
+ | // buffer_I2C[1]=<obsah>; // zapisovane data, byte,-ty | ||
+ | |||
+ | TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); // send start condition | ||
+ | // a odovzdanie riadenia "preruseniu od I2C" | ||
+ | obsluha_Stav_Aut_I2C(); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | unsigned char RD_EEprom(unsigned char adr_RAM) | ||
+ | { | ||
+ | // nastavenie globalnych premennych | ||
+ | |||
+ | buffer_I2C[0]=ADR_IC_RD; // Adr obvodu + rd | ||
+ | buffer_I2C[1]=adr_RAM; // Sem vrati obsah z nastavenej adresy 24LC04 | ||
+ | |||
+ | TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); // send start condition | ||
+ | // a odovzdanie riadenia "preruseniu od I2C" | ||
+ | obsluha_Stav_Aut_I2C(); | ||
+ | return(buffer_I2C[1]); | ||
+ | |||
+ | } | ||
+ | |||
+ | // tato funkcia vyuziva globalne premenne | ||
+ | // buffer_I2C[x] | ||
+ | // Wr_data - tato premenna nadobuda vyznam az pri komunikacii s konkretnou premennou | ||
+ | // vid. "instrukcny subor" I2C periferie | ||
+ | |||
+ | // implementovany instrukcny subor pre seriovu EEPROM max 256 byte | ||
+ | // S|adr_IO+wr|<AC>|P -- nastavenie adresneho citaca pamate EEPROM | ||
+ | // {nie je implementova} S|adr_IO+wr|<AC>|data|P -- zapisanie dat na nastavenu adresu pamate EEPROM | ||
+ | // S|adr_IO+rd|data|P -- precitanie jedneho bytu z aktualne nastavenej adresy pamate EEPROM | ||
+ | // obsah adresneho citaca sa inkrementne | ||
+ | |||
+ | void obsluha_Stav_Aut_I2C(void) | ||
+ | { unsigned char pom_St_Aut=0; | ||
+ | |||
+ | |||
+ | nav:while ((TWCR & _BV(TWINT)) == 0); /* wait for transmission */ | ||
+ | |||
+ | { pom_St_Aut=TWSR & 0xf8; // precitaj stav | ||
+ | printf(" %02x",pom_St_Aut); | ||
+ | switch(pom_St_Aut) | ||
+ | { case TW_START:// = 0x08 // odvysielany start | ||
+ | case TW_REP_START:// = 0x10 // odvysielany repeated start | ||
+ | TWDR = buffer_I2C[0];// Adr+wr/rd, adresa IO | ||
+ | TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */ | ||
+ | break; | ||
+ | |||
+ | case TW_MT_SLA_ACK: // 0x18 Data byte has been tramsmitted and ACK received | ||
+ | TWDR = buffer_I2C[1]; // tu konkretne, nastavenie Adreseho citaca pamate. | ||
+ | TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */ | ||
+ | break; | ||
+ | |||
+ | case TW_MT_DATA_ACK: // 0x28 Data byte has been tramsmitted and ACK received | ||
+ | TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */ | ||
+ | return; // tento riadok v preruseni vypadne | ||
+ | break; | ||
+ | |||
+ | case TW_MR_SLA_ACK: // 0x40 // Data byte has been tramsmitted and NACK received | ||
+ | TWCR = _BV(TWINT) | _BV(TWEN) ; // clear interrupt to start transmission | ||
+ | break; | ||
+ | |||
+ | case TW_MR_DATA_NACK: // 0x58 // Data byte has been tramsmitted and ACK received | ||
+ | buffer_I2C[1]= TWDR; // Vycitaj jeden byte z 24LC04. Adresny citac sa posunie | ||
+ | TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); // send stop condition | ||
+ | return; // tento riadok v preruseni vypadne | ||
+ | break; | ||
+ | |||
+ | default: | ||
+ | TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */ | ||
+ | return; // tento riadok v preruseni vypadne | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | goto nav; // toto v preruseni vypadne | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | int main(void) | ||
+ | { unsigned char znak; | ||
+ | |||
+ | unsigned int i=0; | ||
+ | unsigned char poc_adresa_EEPROM=0; | ||
+ | |||
+ | |||
+ | |||
+ | inituart(); // inicializacia UARTU // inicializacia v 4-bitovom rezime | ||
+ | |||
+ | |||
+ | // sei(); // Enable ALL interrupts | ||
+ | |||
+ | // ini I2C | ||
+ | { | ||
+ | |||
+ | TWCR = _BV(TWEN); /* send start condition */ | ||
+ | TWBR = 72; // fi2c= fosc/(16 +2(preddelic=00=> 1)(<TWBR>)) = 100kHz | ||
+ | TWSR=1; | ||
+ | } | ||
+ | |||
+ | |||
+ | // TODO: to USART | ||
+ | /* ************************************************************ */ | ||
+ | |||
+ | stdout = &mystdout_Uart; | ||
+ | |||
+ | |||
+ | printf("Nastavenie adresy EEPROM = %02x \n\r",poc_adresa_EEPROM); | ||
+ | WR_EEprom(ADR_IC_WR,poc_adresa_EEPROM); | ||
+ | |||
+ | |||
+ | printf("\n\r\rVypis EEPROM: \n\r"); | ||
+ | |||
+ | // vypisme prvych 10 znakov | ||
+ | while (i<10) //256)// kapacita pamate 256 znakov, bytov, | ||
+ | { | ||
+ | znak = RD_EEprom(ADR_IC_RD); // obsah adresneho citaca EEPROM sa automaticky inkrementuje | ||
+ | if(znak==0xff)i=256; // vymazane pametove miesto | ||
+ | { | ||
+ | printf(" %02d %02x %c\r",i++,znak,znak); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | for(;;); // a cakam napr. na "RESET" | ||
+ | |||
+ | } | ||
</source> | </source> | ||
[[Category:DVPS]] | [[Category:DVPS]] |
Verzia zo dňa a času 11:13, 6. december 2012
K. Zbernica i2c: EEPROM
Prečítajte obsah predloženej pamäti EEPROM a zobrazte na PC.
Literatúra:
- M24C02 Datasheet
- Mitchell Kahn: Programming the i2c interface. Dr. Dobb's Journal, June 1992.
- Example using the two-wire interface (TWI). AVRlibc demo projects.
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include <util/twi.h>
#include <stdio.h>
//#include "lcd.h"
#include "Uart_ch.h"
unsigned char RD_EEprom(unsigned char adr_RAM);
void WR_EEprom(unsigned char adr_IC,unsigned char adr_pocitadlo);
void obsluha_Stav_Aut_I2C(void);
#define ADR_IC_WR 0xA0 // EEPROM Adresa IC+WR
#define ADR_IC_RD 0xA1 // EEPROM Adresa IC+RD
volatile unsigned char buffer_I2C[10]; // buffer pre obsluhu I2C
FILE mystdout_Uart = FDEV_SETUP_STREAM(sendchar, NULL, _FDEV_SETUP_WRITE);
void WR_EEprom(unsigned char adr_IC,unsigned char adr_pocitadlo)
{ // nastavenie globalnych premennych
buffer_I2C[0]=adr_IC; // Adr obvodu + wr
buffer_I2C[1]=adr_pocitadlo; // Nastavenie Adresneho citaca 24LC04 , Adresa (z ktorej citam)/(do ktorej zapisujem)
// buffer_I2C[1]=<obsah>; // zapisovane data, byte,-ty
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); // send start condition
// a odovzdanie riadenia "preruseniu od I2C"
obsluha_Stav_Aut_I2C();
}
unsigned char RD_EEprom(unsigned char adr_RAM)
{
// nastavenie globalnych premennych
buffer_I2C[0]=ADR_IC_RD; // Adr obvodu + rd
buffer_I2C[1]=adr_RAM; // Sem vrati obsah z nastavenej adresy 24LC04
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); // send start condition
// a odovzdanie riadenia "preruseniu od I2C"
obsluha_Stav_Aut_I2C();
return(buffer_I2C[1]);
}
// tato funkcia vyuziva globalne premenne
// buffer_I2C[x]
// Wr_data - tato premenna nadobuda vyznam az pri komunikacii s konkretnou premennou
// vid. "instrukcny subor" I2C periferie
// implementovany instrukcny subor pre seriovu EEPROM max 256 byte
// S|adr_IO+wr|<AC>|P -- nastavenie adresneho citaca pamate EEPROM
// {nie je implementova} S|adr_IO+wr|<AC>|data|P -- zapisanie dat na nastavenu adresu pamate EEPROM
// S|adr_IO+rd|data|P -- precitanie jedneho bytu z aktualne nastavenej adresy pamate EEPROM
// obsah adresneho citaca sa inkrementne
void obsluha_Stav_Aut_I2C(void)
{ unsigned char pom_St_Aut=0;
nav:while ((TWCR & _BV(TWINT)) == 0); /* wait for transmission */
{ pom_St_Aut=TWSR & 0xf8; // precitaj stav
printf(" %02x",pom_St_Aut);
switch(pom_St_Aut)
{ case TW_START:// = 0x08 // odvysielany start
case TW_REP_START:// = 0x10 // odvysielany repeated start
TWDR = buffer_I2C[0];// Adr+wr/rd, adresa IO
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
break;
case TW_MT_SLA_ACK: // 0x18 Data byte has been tramsmitted and ACK received
TWDR = buffer_I2C[1]; // tu konkretne, nastavenie Adreseho citaca pamate.
TWCR = _BV(TWINT) | _BV(TWEN); /* clear interrupt to start transmission */
break;
case TW_MT_DATA_ACK: // 0x28 Data byte has been tramsmitted and ACK received
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */
return; // tento riadok v preruseni vypadne
break;
case TW_MR_SLA_ACK: // 0x40 // Data byte has been tramsmitted and NACK received
TWCR = _BV(TWINT) | _BV(TWEN) ; // clear interrupt to start transmission
break;
case TW_MR_DATA_NACK: // 0x58 // Data byte has been tramsmitted and ACK received
buffer_I2C[1]= TWDR; // Vycitaj jeden byte z 24LC04. Adresny citac sa posunie
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); // send stop condition
return; // tento riadok v preruseni vypadne
break;
default:
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); /* send stop condition */
return; // tento riadok v preruseni vypadne
break;
}
}
goto nav; // toto v preruseni vypadne
}
int main(void)
{ unsigned char znak;
unsigned int i=0;
unsigned char poc_adresa_EEPROM=0;
inituart(); // inicializacia UARTU // inicializacia v 4-bitovom rezime
// sei(); // Enable ALL interrupts
// ini I2C
{
TWCR = _BV(TWEN); /* send start condition */
TWBR = 72; // fi2c= fosc/(16 +2(preddelic=00=> 1)(<TWBR>)) = 100kHz
TWSR=1;
}
// TODO: to USART
/* ************************************************************ */
stdout = &mystdout_Uart;
printf("Nastavenie adresy EEPROM = %02x \n\r",poc_adresa_EEPROM);
WR_EEprom(ADR_IC_WR,poc_adresa_EEPROM);
printf("\n\r\rVypis EEPROM: \n\r");
// vypisme prvych 10 znakov
while (i<10) //256)// kapacita pamate 256 znakov, bytov,
{
znak = RD_EEprom(ADR_IC_RD); // obsah adresneho citaca EEPROM sa automaticky inkrementuje
if(znak==0xff)i=256; // vymazane pametove miesto
{
printf(" %02d %02x %c\r",i++,znak,znak);
}
}
for(;;); // a cakam napr. na "RESET"
}