logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Atmega168][AT24C64] Znak konca strony ??

chrupex 24 Wrz 2010 09:31 1356 7
REKLAMA
  • #1 8544571
    chrupex
    Poziom 11  
    Witojcie dobrzy ludzie!

    Mam pewien problemik. Otoz napisalem pewien programik na atmege, ktory zapisuje na zew eepromie jakis kawalek strony internetowej, a nastepnie odczytuje to. Oto wycinek programu:

    
    int main(void)
    {
    
    	char *tekst = PSTR("<html><!-- <img src=\"star.png\" width=\"15\" height=\"15\" alt=\"\"> --><head><META NAME=\"konwerter\" CONTENT=\"Ogonki97 1.3\"><META HTTP-EQUIV=\"content-type\" CONTENT=\"text/html; CHARSET=windows-1250\"><title>COStAM</title><link rel=\"shortcut icon\" href=\"favicon.ico\"><style type=\"text/css\"></style>");
    
    	...
    
    	uint16_t adreso = 0;
    	TWBR = 32;
    	TWSR = 0;
    	TWCR = (1 << TWINT) | (1 << TWEN);
    	
    	...
    
    	while(1)
    	{
    		
    		while((znak = pgm_read_byte(tekst++))){
    			kod_bledu = eeprom_write(EEPROM1, adreso++, &znak);
    			if(kod_bledu != 1) {send_txt("\n Eeprom 1 Blad zapisu!!"); send_data(kod_bledu);break;}
    		}
    
    		_delay_ms(500);
    		adreso = 0;
    		
    		for(int i=0; i<1000; i++){
    			kod_bledu = eeprom_read(EEPROM1,adreso+i, &znak);
    			if(kod_bledu != 1) {send_txt("\n Eeprom 1 Blad odczytu!!"); send_data(kod_bledu);}
    			else {send_data(znak);}
    		}
    		
    		
    		while(1){
    			PORTB = 0x00;
    			_delay_ms(1000);
    			PORTB = 0x01;
    			_delay_ms(1000);
    		}
    		
    	}
    }
    


    Funkcja eeprom_write zapisuje pojedynczo, nie stronami. Wszystko pieknie dziala, zero bledow, lecz w momencie kiedy odczytuje na terminalu dostaje wszystko tak jak zapisano, tylko, ze po 30 znaku zamiast moich literek wystepuje wartosc 0x04 a nastepnie 0x01.

    I wszedzie tak jest, zawsze na 31 i 32 pozycji. Poniewaz eeprom ma 32 bajtowe strony to mysle sobie moze to jakies znaki konca strony w eepromie, ktore sa nadawane automatycznie. Ale niestety nie moge nigdzie o tym znalezc informacji w datasheet.

    Aha... i nie jest to wina odczytu, bo jak zaczne odczytywanie nie od zera, ale np od 5 to te znaki pojawiaja sie na 26 i 27 pozycji.

    Orientujecie sie o co moze chodzic?

    Pozdrawiam!

    Proszę poprawić pisownię!
    Robak
  • REKLAMA
  • #2 8545228
    Andrzej__S
    Poziom 28  
    chrupex napisał:

    ...moze to jakies znaki konca strony w eepromie, ktore sa nadawane automatycznie...

    Nie ma czegoś takiego.

    chrupex napisał:

    
       TWCR = (1 << TWINT) | (1 << TWEN);
    


    Do czego ma służyć ta instrukcja? Magistralę włącza się dopiero podczas transmisji.

    Nie przedstawiłeś kodu funkcji eeprom _write() i eeprom_read(), a to one są najprawdopodobniej przyczyną problemów.
  • REKLAMA
  • #3 8546256
    chrupex
    Poziom 11  
    TWCR = (1 << TWINT) | (1 << TWEN); 

    To jest jakas pozostalosc po starszych wersjach programu, ktora faktycznie mozna wyrzucic, aczkolwiek tez nie sadze, zeby byla ona przyczyna tego problemu.

    Tutaj przedstawiam funkcje eeprom_write() oraz eeprom_read():
    unsigned char i2c_start (void)
    {
       TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
       while (!(TWCR & (1<<TWINT)));
       return TWSR; 
    }
    
    void i2c_stop (void)
    {
       TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);   
    }
    
    unsigned char i2c_send (unsigned char send)
    {
       
       TWDR = send;
       TWCR = (1<<TWINT) | (1<<TWEN);
       while (!(TWCR & (1<<TWINT)));
       return TWSR; 
    }
    
    unsigned char i2c_read (unsigned char ack)
    {
       TWCR = (1<<TWINT) | (ack<<TWEA) | (1<<TWEN);
       while (!(TWCR & (1<<TWINT)));
       return TWDR; 
    } 
    
    int eeprom_write(char deviceID, uint16_t adres, char *znak)
    {
    	
    	if ((i2c_start() & 0xF8) != 0x08) return 0;
    	
    	deviceID |= 0xA0;
    	if ((i2c_send(deviceID) & 0xF8) != 0x18) return 1;
    	
    	if ((i2c_send((adres>>8)) & 0xF8) != 0x28) return 2;
    	
    	if ((i2c_send(adres) & 0xF8) != 0x28) return 3;
    	
    	while(*znak!=0){
    		if ((i2c_send(*znak) & 0xF8) != 0x28) return 3;
    		znak++;}
    
    	i2c_stop();
    	_delay_ms(10);
    	return 1;
    	
    }
    
    int eeprom_read(char deviceID, uint16_t adres, char *znak)
    {
    	if ((i2c_start() & 0xF8) != 0x08) return 0;
    
    	deviceID |= 0xA0;
    	if ((i2c_send(deviceID) & 0xF8) != 0x18) return 2;
    	
    
    	if ((i2c_send((adres>>8)) & 0xF8) != 0x28) return 3;
    	
    
    	if ((i2c_send(adres) & 0xF8) != 0x28) return 4;
    	
    
    	if ((i2c_start() & 0xF8) != 0x10) return 5;
    	
    	deviceID |= 0xA1;
    	i2c_send(deviceID);
    	
    	*znak = i2c_read(0);
    	
    	i2c_stop();
    	_delay_ms(10);
    	return 1;
    	
    }
  • REKLAMA
  • #4 8546529
    Andrzej__S
    Poziom 28  
    Wstępnie zauważyłem coś takiego:
    
    int eeprom_write(char deviceID, uint16_t adres, char *znak) 
    { 
        
       if ((i2c_start() & 0xF8) != 0x08) return 0; 
        
       deviceID |= 0xA0; 
       if ((i2c_send(deviceID) & 0xF8) != 0x18) return 1; // to jest sytuacja nieprawidłowa
                                                          // np. brak bitu potwierdzenia - funkcja zwraca 1
        
       .....
    
       i2c_stop(); 
       _delay_ms(10); 
       return 1; // to jest sytuacja prawidłowa, czyli transmisja przebiegła prawidłowo
                 // funkcja także zwraca 1
        
    }
    


    Być może to nie jest przyczyna zamieszania, ale tak chyba być nie powinno.

    Dodano po 11 [minuty]:

    Druga sprawa:
    
    int eeprom_write(char deviceID, uint16_t adres, char *znak) 
    { 
       .......
        
       while(*znak!=0){ 
          if ((i2c_send(*znak) & 0xF8) != 0x28) return 3; 
          znak++;}
    // Zastanowiłeś się, co robi ta konstrukcja? Przecież do funkcji podajesz wskaźnik do pojedynczego znaku,
    // a nie do ciągu. Dlaczego inkrementujesz wskaźnik? Przecież ta funkcja miała niby zapisywać pojedynczy bajt.
    
       .......
        
    }
    
  • #5 8546681
    chrupex
    Poziom 11  
    Odnosnie wstepnej uwagi, masz racje nie powinno tam tak byc. Dziekuje za spostrzezenie. Aczkolwiek, tak jak piszesz, nie jest to przyczyna bledu.

    Co do drugiej uwagi wspomniana konstrukcja w funkcji eeprom_write() jest takowa, z mysla o tym, zebym mogl jej uzywac do zapisywania ciagow. Dzieki temu moge napisac
    
    eeprom_write(EEPROM1, adres, "tekst do wpisania < 32 liter");
    


    i od razu mam zapisany caly ciag, tylko trzeba uwazac, zeby nie przekroczyl 32 znakow (jednej eepromowej strony)
  • REKLAMA
  • Pomocny post
    #6 8546820
    Andrzej__S
    Poziom 28  
    chrupex napisał:

    Co do drugiej uwagi wspomniana konstrukcja w funkcji eeprom_write() jest takowa, z mysla o tym, zebym mogl jej uzywac do zapisywania ciagow. Dzieki temu moge napisac
    
    eeprom_write(EEPROM1, adres, "tekst do wpisania < 32 liter");
    


    Obawiam się, że to będzie działać prawidłowo tylko wtedy, gdy adres będzie podzielny przez 32.

    Poza tym, funkcję eeprom_write wywołujesz tak:
    
          while((znak = pgm_read_byte(tekst++))){ 
             kod_bledu = eeprom_write(EEPROM1, adreso++, &znak);
          .......
    

    Domyślam się, że zmienna znak jest zadeklarowana jako pojedynczy znak (char). Skąd wiesz, co będzie zawierała komórka pamięci o adresie większym o 1? Przecież to będą przypadkowe dane. Jeśli stworzyłeś funkcję, która ma zapisywać ciąg znaków, to później musisz przekazać do niej wskaźnik do ciągu (ograniczonego znakiem 0x00), a nie do pojedynczego znaku, bo w innym przypadku ta konstrukcja, którą przedstawiłem w poprzednim poście, nie zadziała prawidłowo.
  • #7 8546850
    chrupex
    Poziom 11  
    Dobra problem rozwiazany. Faktycznie tak jak pisales problem byl w tej konstrukcji
    while(*znak!=0){
    		if ((i2c_send(*znak) & 0xF8) != 0x28) return 5;
    		znak++;}
    


    A dokladniej w tym, ze przekazywalem jeden znak.

    Co prawda dalej nie wiem skad ten dziwne wartosci wystepujace co 30 znak, ale najwazniejsze, ze problem rozwiazany.

    No nic... dzieki wielkie za pomoc!
    Pozdrawiam!
  • #8 8546906
    Andrzej__S
    Poziom 28  
    chrupex napisał:

    Co prawda dalej nie wiem skad ten dziwne wartosci wystepujace co 30 znak...


    Po prostu podczas zapisu 30-go znaku:
    
       while(*znak!=0){ 
          if ((i2c_send(*znak) & 0xF8) != 0x28) return 3; 
          znak++;} // inkrementujesz wskaźnik 'znak' o 1 i komórka o tym adresie
                   // nie zawiera 0, tylko wartość jakiejś innej zmiennej, która
                   // jest tam umieszczona, więc zapis (wysyłanie danych do pamięci)
                   // nie kończy się: 'while(*znak!=0)'
    
REKLAMA