Witam.
Mam problem z odczytem przez TWI, tzn w programie zamieszczonym ponizej najpierw zapisuje do pamieci podlaczonej przez TWI 2 wartosci, a pozniej gdy chce je odczytac, pierwsza odczytana wartosc jest bledna, natomiast druga dobra. Mysle, ze moze to byc blad w funkcji i2c_readAck, gdyz i2c_readNak jak powiedzialem odczytuje poprawna wartosc. A moze brakuje jakiegos stopu? Zamieszczam listingi. Dodam, ze bledny odczyt wystepuje w przypadku wiekszych liczb, tzn liczb dwucyfrowych, jezeli odczytywana wartosc jest jednocyfrowa, dziala dobrze.
plik mojtwi.h z funkcjami
Mam problem z odczytem przez TWI, tzn w programie zamieszczonym ponizej najpierw zapisuje do pamieci podlaczonej przez TWI 2 wartosci, a pozniej gdy chce je odczytac, pierwsza odczytana wartosc jest bledna, natomiast druga dobra. Mysle, ze moze to byc blad w funkcji i2c_readAck, gdyz i2c_readNak jak powiedzialem odczytuje poprawna wartosc. A moze brakuje jakiegos stopu? Zamieszczam listingi. Dodam, ze bledny odczyt wystepuje w przypadku wiekszych liczb, tzn liczb dwucyfrowych, jezeli odczytywana wartosc jest jednocyfrowa, dziala dobrze.
Cytat:
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <avr\eeprom.h>
#include "globalne.h"
#include "lcd.h"
#include "klawiatura.h"
#include "uart.h"
#include "mojtwi.h"
#define Dev24C02 0xA0
int adres1i, wartoscadres1i, adresodczyti, wartosc2i;
char adres1u[]="";
char wartoscadres1[]="";
char adresodczyt[]="";
char wartosc2[]="";
u08 ret, ret1;
int main (void){
USART_Init(UART_CONST); // inicjalizacja portu szeregowego
LCD_init();
i2c_init();
LCD_PL_chars_init();
KBD_init();
LCD_clear();
LCD_putstr_P(PSTR("Witaj. Uruchomiono program"));
delayms1000();
USART_putstr("Witaj w programie komunikacyjnym\n\r");
USART_putstr("Podaj adres pod ktory chcesz zapisac: ");
USART_getstr(adres1u);
adres1i=atoi(adres1u);
USART_putstr("\n\rPodaj wartosc jaka zapisac: ");
USART_getstr(wartoscadres1);
USART_putstr_P(PSTR("\n\rPodaj 2 wartosc"));
USART_getstr(wartosc2);
wartosc2i=atoi(wartosc2);
wartoscadres1i=atoi(wartoscadres1);
i2c_start(Dev24C02+I2C_WRITE);
i2c_write(adres1i);
i2c_write(wartoscadres1i);
i2c_write(wartosc2i);
i2c_stop();
delayms1000();
USART_putstr("\n\rA teraz odczyt z i2c\n\r");
USART_putstr("Podaj skad odczytac ");
USART_getstr(adresodczyt);
adresodczyti=atoi(adresodczyt);
i2c_start_wait(Dev24C02+I2C_WRITE);
i2c_write(adresodczyti);
i2c_rep_start(Dev24C02+I2C_READ);
ret = i2c_readAck();
ret1=i2c_readNak();
i2c_stop();
delayms1000();
LCD_clear();
LCD_putstr_P(PSTR("odczytano z i2c "));
LCD_putU08(ret);
delayms1000();
USART_putstr("\n\rOdczytano: ");
USART_putint(ret, 10);
USART_putstr("\n\rOdczytano: ");
USART_putint(ret1, 10);
delayms1000();
return 0;
}
plik mojtwi.h z funkcjami
Cytat:
#ifndef _I2CMASTER_H
#define _I2CMASTER_H 1
#ifdef DOXYGEN
#endif
/**@{*/
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
#endif
//definicja kierunku transmisji danych(odczyt)
#define I2C_READ 1
//definicja kierunku transmisji danych(zapis)
#define I2C_WRITE 0
/**@}*/
#endif
#include <inttypes.h>
#include <C:\WinAVR\avr\include\compat\twi.h>
//Definicja czestotliwosci taktowania zegara
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
//Czestotliwosc magistrali I2C
#define SCL_CLOCK 100000L
//Inicjalizacja magistrali I2C
void i2c_init(void)
{
//Czestotliwosc TWI 100 KHz TWPS = 0 => preskaler = 1
TWSR = 0; //brak preskalera
TWBR = ((F_CPU/SCL_CLOCK)-16)/2;
}
/*Wysyla sygnal start na magistrale,
adresuje urzadzenie oraz okresla kierunek transmisji
zwraca 0 jezeli urzadzenie jest dostepne, 1 gdy wystapil blad*/
unsigned char i2c_start(unsigned char address)
{
uint8_t twst;
//START
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// czekaj na zakonczenie transmisji
while(!(TWCR & (1<<TWINT)));
// Sprawdz rejestr statusu
twst = TW_STATUS & 0xF8;
//wystapil blad, zwroc 1
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
// wyslij adres urzadzenia
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
//czekaj na zakonczenie transmisji i odbierz ACK/NAK
while(!(TWCR & (1<<TWINT)));
//sprawdz rejestr statusu
twst = TW_STATUS & 0xF8;
//wystapil blad, zwroc 1
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
//w przeciwnym wypadku operacja powiodla sie zwroc 0
return 0;
}
/*Wysyla sygnal start na magistrale
adres urzadzenia oraz okresla kierunek transmisji
jezeli urzadzenie jest zajete, oczekuje na nie*/
void i2c_start_wait(unsigned char address)
{
uint8_t twst;
while ( 1 )
{
//START
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// czekaj na zakonczenie transmisji
while(!(TWCR & (1<<TWINT)));
//sprawdz rejestr statusu
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
//wyslij adres urzadzenia
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
//czekaj na zakonczenie transmisji
while(!(TWCR & (1<<TWINT)));
//sprawdz rejestr statusu
twst = TW_STATUS & 0xF8;
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
{
//urzadzenie zajete, wyslij stop i przerwij zapis
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
//czekaj na stop i zwolnij szyne
while(TWCR & (1<<TWSTO));
continue;
}
break;
}
}
/*Wysyla powtorzony sygnal start na magistrale
adres urzadzenia i kierunek transmisji
zwraca 0 gdy urzadzenie dostepne, w przeciwnym wypadku 1*/
unsigned char i2c_rep_start(unsigned char address)
{
return i2c_start( address );
}
//Wysyla sygnal stop i zwalnia magistrale
void i2c_stop(void)
{
//STOP
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
//czekaj na wykonanie sygnalu stop i zwolnienie magistrali
while(TWCR & (1<<TWSTO));
}
/*Wysyla 1 bajt do urzadzenia
zwraca 1 gdy blad, w przeciwnym wypadku 0*/
unsigned char i2c_write( unsigned char data )
{
uint8_t twst;
//wyslij dane do uprzednio zaadresowanego urzadzenia
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
//czekaj na zakonczenie transmisji
while(!(TWCR & (1<<TWINT)));
//sprawdz rejestr statusu
twst = TW_STATUS & 0xF8;
//jezeli blad zwroc 1
if( twst != TW_MT_DATA_ACK) return 1;
//gdy operacja zakonczona sukcesem zwroc 0
return 0;
}
/*Czyta 1 bajt z magistrali i oczekuje na nastepne dane
zwraca odczytany bajt*/
unsigned char i2c_readAck(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}
/*Czyta 1 bajt z magistrali i konczy transmisje
zwraca odczytany bajt*/
unsigned char i2c_readNak(void)
{
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
return TWDR;
}