Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Atmega RS485 błędy/przekłamania

percol 08 Jul 2010 23:52 6345 31
SterControl
  • #1
    percol
    Level 12  
    Szanowni Koledzy,

    Buduję kontroler sterujący urządzeniami zewnętrznymi. Na chybcika skleciłem układ-programator AVR przez łącze LPT.
    Program napisany i skompilowany w WinAVR-20100110 (Win2k).
    Wszystko działa poprawnie (Linux Slackware 10 + avrdude) jeśli idzie o programowanie flesha.
    Od strony elektronicznej też jest wszystko w porządku (jak manual przykazał;).
    Krótki opis:
    AMEGA88PA (DIP28)
    MAX487 (wariant 485, nie ma się do czego przyczepić)
    rezonator 12 MHz (wiem, wiem 11,0592 byłby lepszy - pierwotnie miał być na USB)
    pojemności 10 pF (takie miałem pod ręką - wystarczają, rezonator się wzbudza)
    5V łapane z joy'a
    PD2 ATMEGI przełącza MAX'a w tryb Rx/Tx

    Teraz program.
    Po wielu przeróbkach (uproszczeniach) nadal nie działa. Jego funkcja - prymitywne echo (wywaliłem kontrolę ramki LRC dla przejrzystości kodu + uproszczenia działania, mimo to otrzymuję te same błędy).
    Tzn. ATMEGA czyta ciąg znaków dopóki nie napotka 'n' wtedy zwraca swoją odpowiedź: pierwszy bajt 0x00, potem długość otrzymanego stringu (włącznie z 'r' i 'n') + to co otrzymała i przechodzi na nasłuch.
    Wybaczcie mi taką sieczkę ale zrezygnowałem z funkcji podejrzewając że może błędy pojawiają się na stosie... (przepełnienie? przez częste wywoływanie funkcji? a może inny powód?)


    
    #define F_CPU 12000000UL
    #include <avr/io.h>
    #include <util/delay.h>
    #include <string.h>
    
    #define FOSC 12000000 // Clock Speed
    #define BAUD 9600
    #define MYUBRR FOSC/16/BAUD-1
    #define MAXBUFSIZE 40	// Watch out, no more than 127!
    
    int main(void){
    volatile unsigned char len,tmp,lrc;
    unsigned char buf[MAXBUFSIZE];
    unsigned long longer;
    
    longer=MYUBRR;
    UBRR0H=(unsigned char)(longer>>8);
    UBRR0L=(unsigned char)longer;
    UCSR0C=(3<<UCSZ00);
    DDRD|=_BV(2);
    
    while(1){
    	PORTD&=~_BV(2);	// Tx off, Rx on
    	UCSR0B=(1<<RXEN0);
    	len=0;
    	tmp=0;
    	memset(buf,0x00,sizeof(buf));
    	while(tmp!='n'){	// Dance to the end of line...
    		while(!(UCSR0A&(1<<RXC0)));
    		tmp=UCSR0A;
    		if((UCSR0A&(1<<FE0))|(UCSR0A&(1<<DOR0))|(UCSR0A&(1<<UPE0))){
    			while(UCSR0A&(1<<RXC0)) tmp=UDR0; break; }
    		tmp=UDR0;
    		if(len<MAXBUFSIZE){	// We can dance but not too long!
    			buf[len]=tmp; len++; }
    		}
    	while(UCSR0A&(1<<RXC0)) tmp=UDR0;
    
    	PORTD|=_BV(2);	// Tx on, Rx off
    	UCSR0B=(1<<TXEN0);
    
    	while(!(UCSR0A&(1<<UDRE0)));
    	UDR0=0x00;
    
    	while(!(UCSR0A&(1<<UDRE0)));
    	UDR0=len;
    
    	lrc=0;
    	while(lrc<=len){
    		while(!(UCSR0A&(1<<UDRE0)));
    		UDR0=buf[lrc]; lrc++; }
    
    	while(!(UCSR0A&(1<<TXC0)));
    	UCSR0A|=(1<<TXC0);
    	}
    return 0;
    }
    
    


    A teraz co się krzaczy:
    Wysyłam string np. ":abc'r''n'" = 6 znaków, bezpośrednio po włączeniu ATMEGI pierwszy pakiet jaki od niej dostaję jest poprawny, tj. "0x00 0x06 ... ".
    Ponowne wysłanie tego samego stringu powoduje, że zwraca mi: "0x00 0x08 ... ", a więc długość (jaka mu się wydaje?) jest dłuższa o 2 bajty!
    Oczywiście tak być nie może - później, w wersji rozwojowej, nie będę mógł obliczyć poprawnie LRC!
    Wspomnę tylko, że program, który miał wysyłać co 100ms bajt zinkrementowany (czyli 0x00, 0x01, 0x02 ... 0x255, 0x00, 0x01, 0x02 ... ) działał w pełni poprawnie, więc nie jest to błąd przesyłu danych. Testowałem też cytowany program dla innych prędkości (1200, 2400 i chyba nawet 300 bodów) i ciągle występował ten sam błąd!
    Musi to być związane z softem, bo sprzętowo wszystko wygląda ślicznie (oscyloskop) + nie ma przekłamań w danych zwracanych tylko ta długość jest chybiona...

    Znalazłem coś takiego na elektrodzie:
    Link
    ale tam facet źle ustawiał UCSR0C (odpowiednik w ATMEGA16), w ATMEGA88PA tego się nie robi. Poza tym dostawał sieczkę, a u mnie wszystko jest cacy i się zgadza, prócz tej nieszczęsnej długości...

    Może jeszcze dodam, że FUSY są poprawnie ustawione (inaczej by nie działało).

    A.. dla jasności: ATMEGA odsyła błędną długość w drugim i każdym następnym cyklu, póki się jej nie zresetuje - potem historia się powtarza. A przecież na początku każdego obiegu głównej pętli while(1) zmienna len jest zerowana. Komp nic więcej nie przesyła poza ramką! Czyżby zostawały jakieś śmieci w buforze wejściowym ATMEGI? [hardware]

    Ewentualnie to musi być jakaś totalna bzdura, błąd w programie którego nie widzę... A męczę się z tym dobrych kilka tygodni (ostatnie 2 leżakowało;-)

    Nie gniewajcie się, że piszę jak dla tumana ale chce dobrze opisać układ i problem.
    W elektronice siedzę od lat, choć bardziej analogowej. Programuję w C głównie pod Linuxem ale i Win się nie brzydzę... ;-)
    To mój pierwszy uC którym się bawię stąd pewnie takie głupie błędy. Przewaliłem trochę literatury o AVR, manual ATMEGI znam prawie cały, a z takim problemem sobie nie radzę... nie mam pomysłu w czym może być rzecz.

    Z góry dziękuję za KAŻDĄ sugestię!
  • SterControl
  • #2
    markosik20
    Level 33  
    Złe podejście.

    Zrób to na przerwaniach. W przerwaniu odbieraj znaki do bufora i sprawdzaj czy przyszło to co trzeba. Jak przyszło to ustaw flagę po czym w main załaduj do bufora nadawczego co trzeba i wyślij (też w przerwaniu).
  • SterControl
  • #3
    gaskoin
    Level 38  
    skróci i uprości to znacznie kod
  • #4
    percol
    Level 12  
    @Markosik20

    Dziękuję za zainteresowanie! :-D

    Nie zrozumieliśmy się.
    Nie chcę transmitować znaków w czasie rzeczywistym.
    Druga sprawa - w RS485 masz wiele nadajników, jeden master reszta slave - nie można sobie tak śmiecić na linii (po znaku), to nie buforowany RS232!
    Inna sprawa, że docelowo przesył będzie w trybie ASCII (później rozszerzę soft o tryb RTU) protokołu MODBUS, tj.: znak ':' a dalej bajty podzielone na: "HighByte1 LowByte1 HighByte2 LowByte2 ... HighByteN LowByteN" (opcjonalnie LRC/CRC16) i kończące: '\r' '\n', ot i cała ramka. Wtedy uC ma czytać ramkę aż do otrzymania znaku '\n', a potem sprawdza czy to do niego zaadresowany jest ten pakiet informacji i ewentualnie co ma wykonać. Stąd te "nieoptymalne" naleciałości z czytaniem w pierwszym kroku a potem odesłaniem informacji zwrotnej. ;-)

    Zaprezentowałem jedynie programik testowy (to co ostatnio siedzi we flashu i z czym mam problemy), którego zadaniem miało być sprawdzenie czy wszystko działa poprawnie na linii ATMEGA <--> RS485 <--> PC (czyli czy odbiera co potrzeba, wykonuje co każą = podaje liczbę odczytanych bajtów + to co otrzymał (do porównania), i słucha dalej w oczekiwaniu na nową komendę, którą odbierze policzy i wypluje ;-) ).
    Zaprogramowałem większość funkcji, które mają być w docelowym układzie ale wywala sie już na samej długości otrzymanego pakietu, więc okroiłem programik, zrezygnowałem z funkcji itd. i ostatnią wersję (najprostszą - echo) zaprezentowałem tutaj.
    Ten program mam na ATMEDZE, i z nim jest kłopot (zmienna len w drugim i dalszych obrotach w pętli przechowuje złą wartość lub procesor ma złudzenie, że otrzymuje 2 bajty więcej, dlaczego?) - nic poza tym.

    Nie chodzi mi o optymalny kod itp., chcę tylko by ATMEGA miała poprawne dane w pamięci!
    Jeśli uC liczy dwa razy identyczny string, za pierwszym razem poprawnie a potem już nie, to MUSI być tego przyczyna.
    Pytanie jaka?

    Dodam tylko, ża uC nie będzie się przepracowywał (ustawi tylko (nie częściej niż raz na sekundę) stan High lub Low na wybranym pinie i finito), toteż stosowanie przerwań chyba nie ma bardzo sensu... Jakieś zalety?


    Oto prostszy kod (bardziej czytelny a robi to samo):

    
    
    #define F_CPU 1000000UL
    #include <avr/io.h>
    #include <util/delay.h>                
    
    #define FOSC 1843200 // Clock Speed
    #define BAUD 9600
    #define MYUBRR FOSC/16/BAUD-1
    #define MAXBUFSIZE 16
    
    void USART_Init( unsigned int ubrr){
    /*Set baud rate */
    UBRR0H = (unsigned char)(ubrr>>8);
    UBRR0L = (unsigned char)ubrr;
    /*Enable receiver and transmitter */
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    /* Set frame format: 8data, 1stop bit */
    UCSR0C = (0<<USBS0)|(3<<UCSZ00);
    }
    
    void USART_Transmit( unsigned char data ){
    /* Wait for empty transmit buffer */
    while ( !( UCSR0A & (1<<UDRE0)) );
    /* Put data into buffer, sends the data */
    UDR0 = data;
    }
    
    
    unsigned char USART_Receive( void ){
    /* Wait for data to be received */
    while ( !(UCSR0A & (1<<RXC0)) );
    /* Get and return received data from buffer */
    return UDR0;
    }
    
    void USART_Flush( void ){
    unsigned char dummy;
    while ( UCSR0A & (1<<RXC0) ) dummy = UDR0;
    }
    
    
    int main(void){
    unsigned char buf[MAXBUFSIZE], i;
    unsigned char nr_u=1;
    DDRD|=_BV(2);
    
    USART_Init(MYUBRR);
    PORTD&=~_BV(2);	// Tx off, Rx on
    while(1){
    	unsigned char tmp, err, len;
    	len=0;
    	err=0;
    	tmp=0;
    	memset(buf, 0, MAXBUFSIZE);
    	buf[len]=USART_Receive();
    	if(buf[len]!=':'){	// It's not ASCII frame!
    		continue; }
    	len++;
    	while(tmp!='\n'){	// Dance to the end of line...
    		tmp=USART_Receive();
    		if(len<MAXBUFSIZE){	// We can dance but not too long!
    			buf[len]=tmp; len++; }else{ err=1; }	// err=1; 'frame is too long!'
    		}
    	if(err!=0){	// Buffer overflow! Ramka niekompletna - olewamy ja...
    		continue; }
    	PORTD^=_BV(2);	// Tx on, Rx off
    	tmp=0;
    	USART_Transmit(tmp); // Wyslij 0x00 <- historyczny poczatek ramki (dla oscyloskopu, obecnie jest to niewazne)
    	USART_Transmit(len); // Wyslij dlugosc odczytanej wiadomosci (tu jest blad!!! Albo len ma zla wartosc albo...?)
    	while(tmp<len){
    		USART_Transmit(buf[tmp++]); }
    	PORTD^=_BV(2);	// Tx off, Rx on
    	}
    return 0;
    }
    
    


    Dodam tylko, że migam tak tym pinem PORTD(2) gdyż MAX487 działa w half-duplex (wymaga przełączania Rx/Tx).
  • #5
    markosik20
    Level 33  
    percol wrote:
    Nie chodzi mi o optymalny kod itp., chcę tylko by ATMEGA miała poprawne dane w pamięci!


    Ale Twoje rozwiązanie transmisji jest najgorsze z możliwych...dlatego masz z nim problemy.

    ISR(USART_RXC_vect)
    {
    
    	buf_odbioru[poz_znaku_odbioru]=UDR;
    
    
    	if(	buf_odbioru[poz_znaku_odbioru]==0x0A &&
    		buf_odbioru[poz_znaku_odbioru-1]==0x0D )
    	{
    		flagi_UARTA.dane_przyszly=1;
    		//Opoznienie_odpowiedzi_UARTA=20;
    	}
    	if(poz_znaku_odbioru<ROZM_BUFORA_RX-2)
    	{
    	 poz_znaku_odbioru++;
    	 Czas_UARTA = 2;
    	}
    	else flagi_UARTA.bufor_RX_pelny=1;
    
    
    ISR(USART_TXC_vect)
    {
    
        if(ilosc_bajtow_do_wyslania)
    		{
    			UDR=buf_nadania[poz_znaku_nadania];
    			if(poz_znaku_nadania<ROZM_BUFORA_TX-1)poz_znaku_nadania++;
    			ilosc_bajtow_do_wyslania--;
    		}
        else
    	{
    		RS485_ODBIOR;
    		ZerowanieBuforaNadania();
    
    	}
    
    }
    
    while(1)
    {
        if(flagi_UARTA.dane_przyszly && Weryfikuje_Dane())
       {
              Wyslij_Odpowiedz();
       }
    
    
    
    }
  • #6
    arturt134
    Level 27  
    Spróbuj po przełączeniu na odbiór zaczekać chwilę (z wyłączonym odbiornikiem), np. czas trwania 2 bajtów.

    Jeżeli na linii RS485 może wystąpić sytuacja, że żaden nadajnik nie jest aktywny, to sprawdź w dokumentacji MAX-a co wtedy wygeneruje odbiornik RS485. Czy przy "pływającej" magistrali ma stan nieaktywny na wyjściu (czyli wysoki), czy też przypadkowy. Jeżeli ten drugi, to podciągnij D+ do VCC, a D- do GND dużymi rezystorami, np. 100k.
  • #7
    tmf
    Moderator of Microcontroller designs
    Tak jak pisze markosik20 zrób to na przerwaniach. Kod, który pokazałeś jest dosyć zakręcony. Co do magistrali to pamiętasz o terminatorze?
    arturt134 - stan spoczynkowy na magistrali nie wymusza się tak dużymi rezystorami. 100k? Skąd wziąłeś tą wartość. To powinno wyglądać tak: Vcc-680om-B-120om-A-680om-GND. Spoczynkowo różnica B-A>200mV.
  • #8
    arturt134
    Level 27  
    tmf:
    Z życia. Jak dasz tak małe rezystory, to i owszem działać będzie, ale niestety pobór prądu jest duży.... Przy urządzeniach sieciowych nie ma problemu, przy bateryjnych nie przejdzie. terminator 120R też zwiększa pobór prądu, a moim zdaniem potrzebny będzie tylko przy bardzo dużych prędkościach (do 38400 bodów / 1000m kabla nie używałem terminatorów i było OK, żadnych przekłamań, odbić, nadmiernego promieniowania).
    Reasumując, proponuję poeksperymentować.
  • #9
    tmf
    Moderator of Microcontroller designs
    RS485 jest magistralą, gdzie dane są przesyłane prądowo więc pobór prądu musi być sporawy. Nie ma sensu go zmniejszać, bo wtedy traci się zalety RS485. Zresztą nie jest to też możliwe, standardowy transceiver RS485 ma impedancję wejścia rzędu 12kom, rezystorami 100 k nie spolaryzujesz go, bo nie wymusisz wystarczającego prądu polaryzacji wejścia. Z kolei rezystor 120om jest zależny od impedancji falowej linii. Tu nie ma miejsca na eksperymenty, bo RS485 jest dokładnie opisany, wystarczy zajrzeć do źródeł a nie kombinować. Jeśli przy zasilaniu bateryjnym komuś zaleź na ograniczeniu poboru prądu to stosuje się aktywne terminatory, którymi można sterować.
  • #10
    arturt134
    Level 27  
    Quote:
    RS485 jest magistralą, gdzie dane są przesyłane prądowo

    Nie bardzo rozumiem dlaczego tak uważasz... Wydaje mi się, że sygnałem jest napięcie różnicowe...


    Quote:
    Zresztą nie jest to też możliwe, standardowy transceiver RS485 ma impedancję wejścia rzędu 12kom, rezystorami 100 k nie spolaryzujesz go, bo nie wymusisz wystarczającego prądu polaryzacji wejścia.


    Rezystancja wejściowa to minimum 12k. Przy 5V napięcie różnicowe wynosi 283mV. Przy 3,3V jest to 187mV. Differential threshold voltage to ±0,2V. Układ działa zarówno przy 5 jak i przy 3,3V (chociaż przy 3,3 jest to działanie "na styk"). Zmniejszając te rezystory do 47k uzyskamy 373mV dla 3,3V. To już bezpieczny poziom.

    Quote:
    Tu nie ma miejsca na eksperymenty, bo RS485 jest dokładnie opisany, wystarczy zajrzeć do źródeł a nie kombinować.

    Źródło: dokumentacja do MAX3485 oraz własne doświadczenie.

    Pozdrawiam.
  • #11
    tmf
    Moderator of Microcontroller designs
    Co do nadawania prądowego to mój błąd, myślałem o czymś innym i taki skrót paskudny mi wyszedł. Co do reszty to, dla transceivera ważny jest także prąd polaryzacji wejścia, z DS do 75176:
    IIH High-level input current VI = 2.4 V 20 mikroA
    IIL Low-level input current VI = 0.4 V –400 mikroA.

    Dla rezystora polaryzującego 100kom i zasilania 5V, prąd polaryzacji będzie mniejszy od 50mikroA (właściwie to mniejszy niż 5V/(2*100k), to 10x za mało do wymuszenia stanu. A mówimy tylko o jednym transceiverze, w rzeczywistym układzie trzeba te prądy przemnożyć przez ilość transceiverów i dodatkowo uwzględnić pojemność magistrali. Bo się okaże, że stan co prawda wymusimy ale po zbyt długim czasie.
  • #12
    arturt134
    Level 27  
    Myślę, że nasz dyskusja jest bezprzedmiotowa. Ja układy z takimi rezystorami robiłem i działały. Co prawda maksymalnie miałem ich na magistrali chyba z 8 sztuk, ale chodziły bezbłędnie. Bez rezystorów ustalających stan linii miałem pływającą magistralę i fałszywe dane.
  • #13
    tmf
    Moderator of Microcontroller designs
    Rozumiem, że np. inżynierowie z Texas Instruments się nie znają:
    http://focus.ti.com/lit/an/slyt324/slyt324.pdf
    A że ci chodziło to albo przypadek, albo miałeś transceivery z true failsafe operation albo nie miałeś sytuacji w której wszystkie nadajniki są zablokowane.
  • #14
    arturt134
    Level 27  
    O ile pamiętam, to bez rezystorów miałem śmieci. Z rezystorami było OK. Wnioski wyciągnij sam.
    Nie pamiętam jakie to były układy, nie pamiętam nawet czy były zasilane z 5V czy z 3,3. Trochę za dawno to było.
  • #15
    percol
    Level 12  
    Dziękuję uprzejmie za zainteresowanie i sugestie. :-D

    O RS485 mogę napisać tyle, że działa poprawnie.
    Bez oporników (terminatorów - linia wymaga dwóch!) rzeczywiście był niezły śmietnik (kiedyś oglądałem pod oscyloskopem). Dałem trochę większe (220 omów) niż przewiduje standard, gdyż transceiver RS232/RS485 wymagał takich (w specyfikacji - nie chciałem go przeciążyć).

    Nie sądzę by problem tkwił w samym przesyle (echo), bo między nadawaniem a odbiorem mija spory odstęp (dawałem też opóźnienie rzędu 1..60 us - testowałem różne zwłoki i nie pomogło).
    Poza tym MAX487 wymaga przełączania z Rx na Tx i vice versa (pytanie czy będąc w trybie Tx może coś buforować w części Rx w międzyczasie?). Gdyby tak było to byłby to wielki feler układu (mała szansa).
    Dodam jeszcze, że jako Master wysyłam ramki nie częściej niż jedna na sekundę (ręcznie), więc problem śmieci/wtórnego echa nie powinien zaistnieć. Zauważcie, że początek pakietu jest OK, wygląda jakby na końcu drugiej ramki i każdej następnej coś jeszcze wchodziło, albo zmienna 'len' się np. nie zeruje, czy to możliwe?

    Najprawdopodobniej jest to wina po stronie uC, bo niby jakim cudem pakiet zwrotny ma IDENTYCZNĄ TREŚĆ jak pakiet NADAWCZY? Przynajmniej pierwszych 6 bajtów (wszystkie te które nadałem) się idealnie zgadzają, pytanie skąd biorą się te dwa dodatkowe bajty (jeśli w ogóle takie są!) w drugim i kolejnych cyklach?

    Może robię błąd, że nie odsyłam tych dwóch nadmiarowych bajtów (nie znam ich treści, więc nie ma pewności czy to jakieś śmieci z USARTu czy uC przekłamuje zmienną 'len', a może jest jakiś inny powód?).

    Myślę, że odczyt tych dwóch bajtów może wiele wnieść do tematu - 0x00 oznacza, że najpewniej zmienna 'len' trzyma niewłaściwą informację o pakiecie.
    Inna zawartość niż 0x00 oznacza, że zapewne coś nadeszło albo "się wygenerowało" (np. w trakcie przełączania?).

    Zobaczę i dam znać.

    P.S.:
    Chciałem tego uniknąć ale zrobię komunikację na przerwaniach (i tak muszę użyć Timera0 (więc sei() i przerwania) do sygnalizacji timeout'u na linii).
    Nie zmienia to faktu, że podane źródła w tej wersji POWINNY DZIAŁAĆ!
    Przecież zerżnąłem je wprost z manuala! ;-)))

    A... zastanawiam się czy może przypadkiem nie bruździ dodatkowe urządzenie w sieci RS485?
    Do testów wyłączyłem wszystkie odbiorniki na linii, prócz tego jednego. Urządzenie to ma co prawda inny adres (powinno więc siedzieć cicho) ale kto je tam wie? ;-)
    Chwilowo nie mam jak tego odłączyć (taka konstrukcja sieci) ani za bardzo jak ""zbajpasować"" (gniazda, wtyczki i te sprawy).
    Pokombinuję jeszcze, może coś szybko wymyślę...

    Na sugestie Kolegi dotyczącą ilości odbiorników w sieci - dziś jest 6 jutro może być 6+x - nie jestem w stanie tego przewidzieć, toteż nie uda mi się dobrać optymalnych oporników wymuszających polaryzujących.
    Szczęśliwie sieć nie jest rozległa - max. 50 metrów, więc mimo sporych zakłóceń "da się żyć" (terminatory wystarczają, w razie potrzeby mogę je zmniejszyć do 120 omów).

    Dodano po 58 [minuty]:

    Oto co wypluwa program:

    
    
    root@gpib2:/tmp/Ametek# ./Skaner.exe -b 9600 -d 8 -s 1 -c 1 -p 0 -x "abc"
    0x00 0x06 0x00 0x00 0x3a 0x61 0x62 0x63 0x0d 0x0a 0x00
    
    root@gpib2:/tmp/Ametek# ./Skaner.exe -b 9600 -d 8 -s 1 -c 1 -p 0 -x "abc"
    0x00 0x08 0x00 0x00 0x3a 0x61 0x62 0x63 0x0d 0x0a 0x00
    
    root@gpib2:/tmp/Ametek# ./Skaner.exe -b 9600 -d 8 -s 1 -c 1 -p 0 -x "abc"
    0x00 0x08 0x00 0x00 0x3a 0x61 0x62 0x63 0x0d 0x0a 0x00
    
    root@gpib2:/tmp/Ametek# ./Skaner.exe -b 9600 -d 8 -s 1 -c 1 -p 0 -x "abc"
    0x00 0x08 0x00 0x00 0x3a 0x61 0x62 0x63 0x0d 0x0a 0x00
    
    


    Ramka wysyłana (Master) za każdym razem: "0x3a 0x61 0x62 0x63 0x0d 0x0a" (w ASCII: ":abc\r\n").

    Program nieco zmieniony - ramka powrotna od ATMEGi:
    1 bajt - odsyłam 0x00 (początek ramki zwrotnej, nieważne)
    2 bajt - długość (tutaj początkowo poprawnie 0x06 potem błędnie 0x08)
    3 bajt - 0x00 (zeruję jakąś zmienną i wysyłam w pakiecie - dla testu, corrupt register? nie! w sumie nieistotne)
    4 bajt - 0x00 (oddzielający część kontrolną od informacyjnej)
    5 bajt i kolejne - echo z tego co otrzymał USART + jeden bajt naddatku (tj. buf[len] = zupełnie jak w/w kodzie)

    Ostatni bajt wskazuje (0x00), że nie wchodzą żadne śmieci, a faktyczna długość ramki (liczba zwracanych bajtów) jest poprawna w każdym z przypadków! Mimo, że ATMEGA odsyła mi wartość 'len' o 2 zwiększoną - bardzo dziwne...
    Wygląda na to, że w uC 'len' pamięta prawdziwą długość pakietu ale z niewiadomych przyczyn (USART?) w drugim obrocie odsyła wartość zawyżoną!

    Sam już nie wiem co o tym wszystkim sądzić.
    Jesli mam otrzymywać nieprawdziwe dane to fatalnie. Tym bardziej, że urządzenie ma pracować jako część aparatury pomiarowo-badawczej ...

    Testowałem też na innych ramkach - efekt ten sam, zawsze zawyża o 2 wartość w 'len'! (np.: ":a\r\n" czy ":abcdef\r\n" albo "::abc\r\n")

    Dodano po 44 [minuty]:

    Udało się zbajpasować w/w nadmiarowe urządzenie na linii RS485.

    Tak więc na "sterylnej linii" (tylko transceiver RS485/RS232 i moja ATMEGA + terminatory) błędna wartość 'len' jest nadal zwracana... (co oczywiste w świetle tego o czym wcześniej pisałem, ale trzeba było sprawdzić by żaden purysta nie mógł się przyczepić)

    Konkluzja:
    Z nieznanych powodów USART wysyła po drucie (jako drugi bajt - więc ewentualne złe/spóźnione dekodowanie pierwszego bajtu odpada) niewłaściwą wartość. Wszystkie inne bajty są w porządku! Dlaczego?

    Przecież ta sama procedura za pierwszym razem wysyła to co potrzeba, a dopiero w następnym cyklu wartość jest powiększona o 2, tylko w którym miejscu?
    W kodzie tego nie ma - może winna jest optymalizacja?
  • #16
    arturt134
    Level 27  
    Może spróbuj przenieść zmienne z funkcji main do programu głównego (czyli poza funkcję).
    Możesz też spróbować wyłączyć optymalizację.
  • #17
    percol
    Level 12  
    @arturt134

    Robiłem to co mi sugerujesz - bezowocnie.
    Ale spostrzegłem ciekawą rzecz: wysyłając pakiet czynię to co parę sekund (ręcznie), przypadkowo dałem chwilkę czasu (5..10 min.) spokoju ATMEDZE (musiałem coś tam innego zrobić), po tym czasie znowu wysłalem pakiet i o dziwo ramka wyglądała jak po resecie uC! Ale następne znowu były oszukane.
    Teraz podejrzewam kondensatory kwarcu (oryginalnie dałem 10pF w/g datasheet powinny być wystarczające, chociaż najczęściej ludzie stosują 22pF), może to one generują jakąś niestabilność?

    Zmodyfikowałem testowo kod, tak by uC wysyłal mi każdy bit zmiennej 'len' w oddzielnym bajcie. Zmienna 'len' jest globalna, podobnie bufor Rx/Tx (static, volatile, register dla 'len' - żadna z tych kombinacji nie działa! buf jest static).
    Wychodzi na to, że uC ma błędną wartość w 'len', mało tego - faktycznie odsyła 'len-4' bajtów (czyli pamięta w 'len' o 2 bajty za dużo, a odsyła o 4 bajty za mało niż w tym zafałszowanym 'len'!), niezła komedia...
    To wygląda jakby albo gubił prawidłową wartość 'len' np. na stosie (ale jak już zmieniłem, że jest to zmienna typu static albo register - nie ma prawa, bo nie odkłada na stos!) albo może procek niestabilnie pracuje?

    Optymalizacje wyłączylem - efekt ten sam.
    Testowałem opcje: bez optymalizacji i z optymalizacja rozmiaru - dalej ten sam problem.
    Przejrzałem manual do avr-libc pod kątem optymalizacji, zarządzania pamięcią itp. + FAQ - też nic nie znalazłem... :-(
    Pozostają już chyba tylko te kondensatory przy kwarcu...
    Podmienię i dam znać - warto rozwikłać ten problem i podać przyczynę by kolejne pokolenia elektroników "nie umierały znowu za Niceę"... ;-)
  • #18
    szelus
    Level 34  
    Jeszcze raz wrzuć dokładnie ten program, którego teraz używasz. W tym drugim, który podałeś, jest np. taki błąd, że nie czekasz z przełączeniem kierunku RS-a do zakończenia transmisji. W związku z tym obetnie ostatnie wysyłane bajty.

    DE i /RE masz połączone razem?
  • #19
    percol
    Level 12  
    Bardzo to wszystko dziwne:
    Program ma odesłać "[:][bit0][bit1]...[bit7][len][\r][\n]"
    Gdy [len]=6 wtedy ramka powinna mieć postać: "[:][0x00][0x01][0x01][0x00]...[0x00][0x06][\r][\n]" czyli: ":011000006\r\n". Stąd binarnie: b110 = 6 wszystko OK.
    Łącznie 12 bajtów (1 znak startu + 8 znaków bitów + 1 znak 'len' + 2 znaki kończące ramkę).

    A otrzymuję: 10 bajtów (brak pierwszego i ostatniego) oraz niepoprawną wartość 'len' (także BITOWĄ!). Oto odpowiedz:
    "[0x00][0x00][0x00][0x01][0x00]...[0x00][0x08][\r]" czyli "00010008\r".
    Stąd binarnie b1000 = 8 (a więc transmisja OK, sama wartość w uC ZŁA!!!). Długość ramki 10 bajtów - zła (choć ZAWSZE programowo wymuszam przesłanie 12 bajtów!).

    Coś jest nie tak z tym uC?
    Nadmienię tylko, że zmieniłem szybkość transmisji na 1200 bodów (dla 12MHz zegara błąd preskalera (UBRR0) wynosi wtedy 0%, dla wyższych transmisji był 0,2% - więc okazało się, że to nie była przyczyną).

    Ręce opadają...

    Ma ktoś pomysł co jeszcze może być ewentualnym źródłem błędów?

    Źródła których dotyczą ostatnie dwa wpisy:
    
    
    #define F_CPU 12000000UL
    #include <avr/io.h>
    #include <util/delay.h>
    #include <string.h>
    
    #define FOSC 12000000 // Clock Speed
    #define BAUD 1200
    #define MYUBRR FOSC/16/BAUD-1
    #define MAXBUFSIZE 40	// Watch out, no more than 127!
    
    volatile register unsigned char len asm("r3"); // rejestr 3 zafiksowany jako 'len'
    static unsigned char buf[MAXBUFSIZE+10]; // siedzi zawsze w RAMie
    
    void Rx_to_buf(void){
    unsigned char tmp;
    tmp=0;
    len=0;
    while(tmp!='\n'){
    	while(!(UCSR0A&(1<<RXC0))); // kreci sie wkolo poki nie nadejdzie bajt
    	if(UCSR0A&0x1C){ // Test FE0, DOR0, UPE0 czy nie ma bledu transmisji.
    		tmp=UDR0; len=0; continue; }
    	tmp=UDR0;
    	if(len<MAXBUFSIZE){ // gdy jest miejsce w buf wpisujemy otrzymany bajt
    		buf[len++]=tmp; }
    	}
    return;
    }
    
    void Tx_to_buf(void){
    unsigned char tmp;
    tmp=0;
    while(tmp<=len){
    	while(!(UCSR0A&(1<<UDRE0))); // czekamy az UDR0 bedzie wolny
    	UDR0=buf[tmp++]; // wpisujemy znak do wyslania
    	}
    while(!(UCSR0A&(1<<TXC0))); // czekamy na zakonczenie transmisji
    return;
    }
    
    int main(void){
    unsigned long longer;
    
    DDRC|=_BV(5); // kontrolny LED, gdy dojdzie pakiet to ja wlacza lub wylacza 
    PORTC|=_BV(5); // LED podpieta pod PC5
    longer=MYUBRR;
    UBRR0H=(unsigned char)(longer>>8); // ustawiamy Baud_rate
    UBRR0L=(unsigned char)longer; // j/w
    UCSR0C=(3<<UCSZ00); // bajt typu 8N1
    DDRD|=_BV(2); // tu podlaczamy sterowanie MAX487 (nadawanie/odbior)
    while(1){
    	PORTD&=~_BV(2);	// Tx off, Rx on
    	UCSR0B=(1<<RXEN0); // wlaczamy odbior w ATMEDZE
    	_delay_ms(20);
    	memset(buf,0x00,sizeof(buf));
    	Rx_to_buf();
    	PORTD|=_BV(2);	// Tx on, Rx off
    	UCSR0B=(1<<TXEN0); // wlaczamy nadawanie w ATMEDZE
    	_delay_ms(20);
    //	buf[0] pozostaje niezmieniony, czyli ':'
    	buf[1]=len&0x01;
    	buf[2]=(len>>1)&0x01;
    	buf[3]=(len>>2)&0x01;
    	buf[4]=(len>>3)&0x01;
    	buf[5]=(len>>4)&0x01;
    	buf[6]=(len>>5)&0x01;
    	buf[7]=(len>>6)&0x01;
    	buf[8]=(len>>7)&0x01;
    	buf[9]=len;
    	buf[10]='\r';
    	buf[11]='\n';
    	len=12; // UWAGA, dlugosc pakietu zwrotnego ustawiona NA SZTYWNO!
    	Tx_to_buf();
    	PORTC^=_BV(5); // dioda LED zmienia stan (swieci lub nie;)
    	_delay_ms(20);
    	}
    return 0;
    }
    
    
  • #20
    szelus
    Level 34  
    A to, przepraszam, to co?
    
    volatile register unsigned char len asm("r3"); 
    

    Jak masz problemy, to nie dodawaj sobie dodatkowych przez potencjalny konflikt z funkcjami bibliotecznymi (memset, _delay_ms?).
    Ostatniego znaku prawdopodobnie nie odbierasz, bo pewnie za szybko przełączasz na odbiór - powinieneś sprawdzać status TX. Dla 1200 bodów wysłanie 1 bajtu zajmuje prawie 10ms.
  • #22
    percol
    Level 12  
    @szelus

    Oczywiście DE i RE są połączone razem (zworka).
    Inaczej nie miałbym transmisji zwrotnej albo trzeba by podłączyć do dwóch różnych pinów ATMEGI.

    Zwłoki po przełączeniu się z nadawania na odbiór (20ms) i odwrotnie wydają się być i tak przydługie - jakby były przeznaczone dla starej elektroniki analogowej... ;-)

    Testowałem też różne odstępy między znakami (delay po 1..60us) i to samo.

    Zresztą, jak wytłumaczyć że mikrokontrolerowi wydaje się, że pakiet o stałej długości (np. 6 bajtów) za pierwszym razem ma długość poprawną (w pamięci), a za drugim i każdym następnym już nie?

    Przeprowadzone testy wskazują, że coś jest nie halo z ATMEGą. Pytanie dlaczego?
    To nowy mikrokontroler, kupiony niecały miesiąc temu, fleszowany może kilkadziesiąt razy (różną wersją tego programu) bez zbędnych bajerów, tylko kilka elementów (kwarc 12MHz, opronik 680, LED, MAX487, 2x220nF i 2x24pF). Avrdude sprawdzał poprawność zapisanego programu - zgadza się. Kompiluję w/w źródła WinAVR (chyba najnowszy: 20100110), fleszuję pod Linuxem z wygody (jest w pobliżu testowej sieci RS485 tak jak ATMEGA). Programator przez LPT, niestety taki system nie daje możliwości debugowania.

    Schematu nie będę rysował bo to nie ma sensu. MAX487 podpięty jak należy (dowodem transmisja w dwie strony), przełączanie Rx/Tx działa. Dioda LED się zapala (policzona na 7 mA, więc nie przeciąża ATMEGI). Kwarc 12MHz + dwa kondensatorki ceramiczne 24 pF (powinny być w zakresie 10..27pF ludzie najczęściej dają 22pF których akurat nie mam - testowałem na 10pF i teraz na 24pF - efekt ten sam).
    Fuse bytes:
    Low - 0xFF
    High - 0xDF
    Extended - 0x01
    Kontroler: ATMEGA88PA-PU (obudowa PDIP28).
    Zasilanie podłączone pod Vcc i pod AVcc (jak radzi producent) + kondensatory foliowe 220nF przy Vcc i przy AVcc.
    Niczego więcej nie ma = nie ma gdzie się przyczepić.
    No może tylko do tego, że programator LPT jest cały czas podpięty do uC ale nieaktywny (aktywuję/dezaktywuję ATMEGĘ stanem na nóżce RESET wysyłając na LPT odpowiednią wartość - wygodny sposób startu podmienionego softu), w razie potrzeby przefleszowuję układ i już.
    Przy czym nóżki do których podpięte są linie z portu LPT nie są w ogóle wykorzystywane w normalnym działaniu programu (więc nie generują przypadkowych błędów/szumów/przerwań itd.).
    Zasilanie czerpię z portu joysticka komputera który steruje LPTem (odpowiada też za fleszowanie). Uwaga, zasilania nie stabilizuję - korzystam z gotowego +5V komputera (+5.1V spokojnie mieści się w tolerancji Vcc ATMEGI).
    Co jeszcze chcecie wiedzieć?

    Dodano po 17 [minuty]:

    szelus wrote:
    A to, przepraszam, to co?
    
    volatile register unsigned char len asm("r3"); 
    

    Jak masz problemy, to nie dodawaj sobie dodatkowych przez potencjalny konflikt z funkcjami bibliotecznymi (memset, _delay_ms?).
    Ostatniego znaku prawdopodobnie nie odbierasz, bo pewnie za szybko przełączasz na odbiór - powinieneś sprawdzać status TX. Dla 1200 bodów wysłanie 1 bajtu zajmuje prawie 10ms.



    Tonący brzytwy się chwyta... OK wiem, że to trochę bez sensu ale testowałem z volatile i bez (chciałem wymusić na kompilatorze by nie optymalizował zmiennej len), i nadal ten sam problem...
    A może chodzi Ci o ten rejestr r3? Rzeczywiście nie wiem do czego służy i co go wykorzystuje (to był strzał z mej strony - na podstawie manuala do avr-libc, tam dali taki przykład w FAQ). Jeśli może być konflikt z funkcjami delay() czy memset() to który mogę bezpiecznie użyć?

    Jak mogę "za szybko" się przełączać jak jest zwłoka 20 milisekund!? To ok. 2 bajty.
    A jaka elektronika nie zdąży się przełączyć w 20ms?
    Chyba że nie zdążył całkowicie wysłać znaku aktualnie wysyłanego, ewentualnie znaku z bufora wejściowego modułu Tx?
    Ale przecież sprawdzam TXC0 (Tx Complete Bit) i dopiero wychodzę z funkcji Tx_to_buf() (swoją drogą bez sensu nazwa, powinno być buf_to_Tx ;-) ).
    Na mój gust powinno być w porządku.

    Jeśli uważasz inaczej napisz co powinienem zmienić.

    Dodano po 23 [minuty]:

    tmf wrote:
    UCSR0C=(3<<UCSZ00); z pewnością nie wybiera ramki 8N1.


    Jak to nie?

    UCSR0C przyjmuje według tego wartość b00000110 = 6
    A więc idąc od najstarszego bitu "Mode: Asynchronous USART" (00) + "Parity Mode: Disabled" (00) + "Stop Bit(s): 1-bit" (0) + "Character Size: 8-bit" (11) + "Clock Polarity: Falling XCKn Edge" (0) = razem b00_00_0_11_0.
    UCSZ02 w UCSR0B ma zawsze 0 podczas działania programu, więc ustawiam 8 bitów w ramce bajtu.

    Źródło: manual ATMEGA88PA strona 196-199.
  • #23
    szelus
    Level 34  
    percol wrote:

    Oczywiście DE i RE są połączone razem (zworka).
    Inaczej nie miałbym transmisji zwrotnej [...]

    Mógłbyś podsłuchiwać własną transmisję...
    Quote:

    Zwłoki po przełączeniu się z nadawania na odbiór (20ms) i odwrotnie wydają się być i tak przydługie - jakby były przeznaczone dla starej elektroniki analogowej... ;-)

    Przy 1200, 1 bit to prawie milisekunda. Pamiętaj, ze transmisja jest w praktyce podwójnie buforowana. Ale fakt, przeoczyłem że czekasz na TXC, zatem to nie ma znaczenia.
    Quote:

    Testowałem też różne odstępy między znakami (delay po 1..60us) i to samo.

    Jakie znaczenie miałoby mieć opóźnienie tego rzędu przy zegarze transmisji 1200Hz?
    Quote:

    A może chodzi Ci o ten rejestr r3? Rzeczywiście nie wiem do czego służy i co go wykorzystuje (to był strzał z mej strony - na podstawie manuala do avr-libc, tam dali taki przykład w FAQ). Jeśli może być konflikt z funkcjami delay() czy memset() to który mogę bezpiecznie użyć?

    Dawno temu korzystałem z tej funkcjonalności, ale już nie pamiętam dokładnie. Można ew. upewnić się oglądając kod wygenerowany, ale na twoim miejscu odpuściłbym sobie takie kombinowanie w ogóle. Zwykła zmienna globalna jest ok.


    tmf wrote:

    UCSR0C=(3<<UCSZ00); z pewnością nie wybiera ramki 8N1.

    To istotnie byłoby wyjaśnienie, ale jakoś mi się też wydaje, ze owszem wybiera 8N1. Co przeoczyłem?
  • #24
    percol
    Level 12  
    @szelus

    "Mógłbyś podsłuchiwać własną transmisję... "

    Mogę, tyle że oscyloskopem bez pamięci, który w dodatku śmieci na linii... :-(
    Jak dla mnie nadawał się tylko do testowania ogólnego stanu linii (przydźwięk i czy coś leci, jak to wygląda - stabilnie czy nie, i tylko przy ciągłym wysyłaniu tego samego znaku przez ATMEGĘ, np. 0xFF, 0xAA, 0x55 i 0x00 czy też 0xF0 albo 0x0F).

    "Jakie znaczenie miałoby mieć opóźnienie tego rzędu przy zegarze transmisji 1200Hz?"

    Przy tym transferze znikome, ale wcześniej dla 9600 i wyższych prędkości (testowałem jeszcze dla 19200, 38400, 57600 i 115200) mogło już mieć (RS od strony kompa powinien chyba zauważyć stan IDLE na linii).


    "Zwykła zmienna globalna jest ok."

    Też tak myślę ale skoro uC mnie nie słucha? ;-)


    Zastanawiam się nad przecięciem pępowiny (LPT), tylko czy to ma sens? Wszystko jest lutowane na sztywno (bez złączy, bo miała to być płytka doświadczalna/programator).
    Myślę nad tym czy te długie przewody (taśma ok. 0.5 m) do LPTa nie wprowadzają czegoś do układu (nawet jeśli nóżki ATMEGI są nieużywane), bo w sumie otoczenie może generować trochę zakłóceń (ale bez przesady - 3 zwykłe silniki trójfazowe mniejsze niż 0.5kW, 2 większe transformatory 4kW, trochę elektroniki, ale wszystko z dala, co najwyżej szczątkowo przez fazę... A może jacyś sąsiedzi mają swój wkład? Chociaż zasilanie idzie z kompa, stabilizowane, a na fazie nie ma żadnych szpilek...).

    Żeby nie było, ten układ testowałem też wczoraj gdy wszystkie inne urządzenia w bliższej i dalszej okolicy były wyłączone (była awaria sieci wysokiego napięcia - ale nawet parę godzin po niej WSZYŚCIUSIEŃKO w okolicy było wyłączone) i dalej te same błędy zmiennej 'len'.
    Dla mnie to wyklucza zewnętrzne zakłócenia.
    Musi być inny powód, że mikrokontroler niestabilnie pracuje... (?)

    Problem rodzi się w jakimś miejscu po wywołaniu Rx_to_buf() albo w jej wnętrzu. Funkcja ta poprawnie odczytuje dane które wysyłam z PC. Problem w tym, że źle je przetwarza w drugim obrocie i kolejnych. Dlaczego?

    Dorzucam też Makefile, może w nim jest ustawiona jakaś idiotyczna flaga?

    
    # Hey Emacs, this is a -*- makefile -*-
    #----------------------------------------------------------------------------
    # WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
    #
    # Released to the Public Domain
    #
    # Additional material for this makefile was written by:
    # Peter Fleury
    # Tim Henigan
    # Colin O'Flynn
    # Reiner Patommel
    # Markus Pfaff
    # Sander Pool
    # Frederik Rouleau
    # Carlos Lamas
    #
    #----------------------------------------------------------------------------
    # On command line:
    #
    # make all = Make software.
    #
    # make clean = Clean out built project files.
    #
    # make coff = Convert ELF to AVR COFF.
    #
    # make extcoff = Convert ELF to AVR Extended COFF.
    #
    # make program = Download the hex file to the device, using avrdude.
    #                Please customize the avrdude settings below first!
    #
    # make debug = Start either simulavr or avarice as specified for debugging, 
    #              with avr-gdb or avr-insight as the front end for debugging.
    #
    # make filename.s = Just compile filename.c into the assembler code only.
    #
    # make filename.i = Create a preprocessed source file for use in submitting
    #                   bug reports to the GCC project.
    #
    # To rebuild project do "make clean" then "make all".
    #----------------------------------------------------------------------------
    
    
    # MCU name
    MCU = atmega88pa
    
    
    # Processor frequency.
    #     This will define a symbol, F_CPU, in all source code files equal to the 
    #     processor frequency. You can then use this symbol in your source code to 
    #     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
    #     automatically to create a 32-bit value in your source code.
    #     Typical values are:
    #         F_CPU =  1000000
    #         F_CPU =  1843200
    #         F_CPU =  2000000
    #         F_CPU =  3686400
    #         F_CPU =  4000000
    #         F_CPU =  7372800
    #         F_CPU =  8000000
    #         F_CPU = 11059200
    #         F_CPU = 14745600
    #         F_CPU = 16000000
    #         F_CPU = 18432000
    #         F_CPU = 20000000
    F_CPU = 12000000
    
    
    # Output format. (can be srec, ihex, binary)
    FORMAT = ihex
    
    
    # Target file name (without extension).
    TARGET = test3
    
    
    # Object files directory
    #     To put object files in current directory, use a dot (.), do NOT make
    #     this an empty or blank macro!
    OBJDIR = .
    
    
    # List C source files here. (C dependencies are automatically generated.)
    SRC = $(TARGET).c
    
    
    # List C++ source files here. (C dependencies are automatically generated.)
    CPPSRC = 
    
    
    # List Assembler source files here.
    #     Make them always end in a capital .S.  Files ending in a lowercase .s
    #     will not be considered source files but generated files (assembler
    #     output from the compiler), and will be deleted upon "make clean"!
    #     Even though the DOS/Win* filesystem matches both .s and .S the same,
    #     it will preserve the spelling of the filenames, and gcc itself does
    #     care about how the name is spelled on its command-line.
    ASRC =
    
    
    # Optimization level, can be [0, 1, 2, 3, s]. 
    #     0 = turn off optimization. s = optimize for size.
    #     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
    OPT = s
    
    
    # Debugging format.
    #     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
    #     AVR Studio 4.10 requires dwarf-2.
    #     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
    DEBUG = dwarf-2
    
    
    # List any extra directories to look for include files here.
    #     Each directory must be seperated by a space.
    #     Use forward slashes for directory separators.
    #     For a directory that has spaces, enclose it in quotes.
    EXTRAINCDIRS = 
    
    
    # Compiler flag to set the C Standard level.
    #     c89   = "ANSI" C
    #     gnu89 = c89 plus GCC extensions
    #     c99   = ISO C99 standard (not yet fully implemented)
    #     gnu99 = c99 plus GCC extensions
    CSTANDARD = -std=gnu99
    
    
    # Place -D or -U options here for C sources
    CDEFS = -DF_CPU=$(F_CPU)UL
    
    
    # Place -D or -U options here for ASM sources
    ADEFS = -DF_CPU=$(F_CPU)
    
    
    # Place -D or -U options here for C++ sources
    CPPDEFS = -DF_CPU=$(F_CPU)UL
    #CPPDEFS += -D__STDC_LIMIT_MACROS
    #CPPDEFS += -D__STDC_CONSTANT_MACROS
    
    
    
    #---------------- Compiler Options C ----------------
    #  -g*:          generate debugging information
    #  -O*:          optimization level
    #  -f...:        tuning, see GCC manual and avr-libc documentation
    #  -Wall...:     warning level
    #  -Wa,...:      tell GCC to pass this to the assembler.
    #    -adhlns...: create assembler listing
    CFLAGS = -g$(DEBUG)
    CFLAGS += $(CDEFS)
    CFLAGS += -O$(OPT)
    CFLAGS += -funsigned-char
    CFLAGS += -funsigned-bitfields
    CFLAGS += -fpack-struct
    CFLAGS += -fshort-enums
    CFLAGS += -Wall
    CFLAGS += -Wstrict-prototypes
    #CFLAGS += -mshort-calls
    #CFLAGS += -fno-unit-at-a-time
    #CFLAGS += -Wundef
    #CFLAGS += -Wunreachable-code
    #CFLAGS += -Wsign-compare
    CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
    CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
    CFLAGS += $(CSTANDARD)
    
    
    #---------------- Compiler Options C++ ----------------
    #  -g*:          generate debugging information
    #  -O*:          optimization level
    #  -f...:        tuning, see GCC manual and avr-libc documentation
    #  -Wall...:     warning level
    #  -Wa,...:      tell GCC to pass this to the assembler.
    #    -adhlns...: create assembler listing
    CPPFLAGS = -g$(DEBUG)
    CPPFLAGS += $(CPPDEFS)
    CPPFLAGS += -O$(OPT)
    CPPFLAGS += -funsigned-char
    CPPFLAGS += -funsigned-bitfields
    CPPFLAGS += -fpack-struct
    CPPFLAGS += -fshort-enums
    CPPFLAGS += -fno-exceptions
    CPPFLAGS += -Wall
    CPPFLAGS += -Wundef
    #CPPFLAGS += -mshort-calls
    #CPPFLAGS += -fno-unit-at-a-time
    #CPPFLAGS += -Wstrict-prototypes
    #CPPFLAGS += -Wunreachable-code
    #CPPFLAGS += -Wsign-compare
    CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
    CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
    #CPPFLAGS += $(CSTANDARD)
    
    
    #---------------- Assembler Options ----------------
    #  -Wa,...:   tell GCC to pass this to the assembler.
    #  -adhlns:   create listing
    #  -gstabs:   have the assembler create line number information; note that
    #             for use in COFF files, additional information about filenames
    #             and function names needs to be present in the assembler source
    #             files -- see avr-libc docs [FIXME: not yet described there]
    #  -listing-cont-lines: Sets the maximum number of continuation lines of hex 
    #       dump that will be displayed for a given single line of source input.
    ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
    
    
    #---------------- Library Options ----------------
    # Minimalistic printf version
    PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
    
    # Floating point printf version (requires MATH_LIB = -lm below)
    PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
    
    # If this is left blank, then it will use the Standard printf version.
    PRINTF_LIB = 
    #PRINTF_LIB = $(PRINTF_LIB_MIN)
    #PRINTF_LIB = $(PRINTF_LIB_FLOAT)
    
    
    # Minimalistic scanf version
    SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
    
    # Floating point + %[ scanf version (requires MATH_LIB = -lm below)
    SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
    
    # If this is left blank, then it will use the Standard scanf version.
    SCANF_LIB = 
    #SCANF_LIB = $(SCANF_LIB_MIN)
    #SCANF_LIB = $(SCANF_LIB_FLOAT)
    
    
    MATH_LIB = -lm
    
    
    # List any extra directories to look for libraries here.
    #     Each directory must be seperated by a space.
    #     Use forward slashes for directory separators.
    #     For a directory that has spaces, enclose it in quotes.
    EXTRALIBDIRS = 
    
    
    
    #---------------- External Memory Options ----------------
    
    # 64 KB of external RAM, starting after internal RAM (ATmega128!),
    # used for variables (.data/.bss) and heap (malloc()).
    #EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
    
    # 64 KB of external RAM, starting after internal RAM (ATmega128!),
    # only used for heap (malloc()).
    #EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
    
    EXTMEMOPTS =
    
    
    
    #---------------- Linker Options ----------------
    #  -Wl,...:     tell GCC to pass this to linker.
    #    -Map:      create map file
    #    --cref:    add cross reference to  map file
    LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
    LDFLAGS += $(EXTMEMOPTS)
    LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
    LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
    #LDFLAGS += -T linker_script.x
    
    
    
    #---------------- Programming Options (avrdude) ----------------
    
    # Programming hardware
    # Type: avrdude -c ?
    # to get a full listing.
    #
    AVRDUDE_PROGRAMMER = bsd
    
    # com1 = serial port. Use lpt1 to connect to parallel port.
    AVRDUDE_PORT = lpt1
    
    AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
    #AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
    
    
    # Uncomment the following if you want avrdude's erase cycle counter.
    # Note that this counter needs to be initialized first using -Yn,
    # see avrdude manual.
    #AVRDUDE_ERASE_COUNTER = -y
    
    # Uncomment the following if you do /not/ wish a verification to be
    # performed after programming the device.
    #AVRDUDE_NO_VERIFY = -V
    
    # Increase verbosity level.  Please use this when submitting bug
    # reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 
    # to submit bug reports.
    #AVRDUDE_VERBOSE = -v -v
    
    AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
    AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
    AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
    AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
    
    
    
    #---------------- Debugging Options ----------------
    
    # For simulavr only - target MCU frequency.
    DEBUG_MFREQ = $(F_CPU)
    
    # Set the DEBUG_UI to either gdb or insight.
    # DEBUG_UI = gdb
    DEBUG_UI = insight
    
    # Set the debugging back-end to either avarice, simulavr.
    DEBUG_BACKEND = avarice
    #DEBUG_BACKEND = simulavr
    
    # GDB Init Filename.
    GDBINIT_FILE = __avr_gdbinit
    
    # When using avarice settings for the JTAG
    JTAG_DEV = /dev/com1
    
    # Debugging port used to communicate between GDB / avarice / simulavr.
    DEBUG_PORT = 4242
    
    # Debugging host used to communicate between GDB / avarice / simulavr, normally
    #     just set to localhost unless doing some sort of crazy debugging when 
    #     avarice is running on a different computer.
    DEBUG_HOST = localhost
    
    
    
    #============================================================================
    
    
    # Define programs and commands.
    SHELL = sh
    CC = avr-gcc
    OBJCOPY = avr-objcopy
    OBJDUMP = avr-objdump
    SIZE = avr-size
    AR = avr-ar rcs
    NM = avr-nm
    AVRDUDE = avrdude
    REMOVE = rm -f
    REMOVEDIR = rm -rf
    COPY = cp
    WINSHELL = cmd
    
    
    # Define Messages
    # English
    MSG_ERRORS_NONE = Errors: none
    MSG_BEGIN = -------- begin --------
    MSG_END = --------  end  --------
    MSG_SIZE_BEFORE = Size before: 
    MSG_SIZE_AFTER = Size after:
    MSG_COFF = Converting to AVR COFF:
    MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
    MSG_FLASH = Creating load file for Flash:
    MSG_EEPROM = Creating load file for EEPROM:
    MSG_EXTENDED_LISTING = Creating Extended Listing:
    MSG_SYMBOL_TABLE = Creating Symbol Table:
    MSG_LINKING = Linking:
    MSG_COMPILING = Compiling C:
    MSG_COMPILING_CPP = Compiling C++:
    MSG_ASSEMBLING = Assembling:
    MSG_CLEANING = Cleaning project:
    MSG_CREATING_LIBRARY = Creating library:
    
    
    
    
    # Define all object files.
    OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) 
    
    # Define all listing files.
    LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) 
    
    
    # Compiler flags to generate dependency files.
    GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
    
    
    # Combine all necessary flags and optional flags.
    # Add target processor to flags.
    ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
    ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
    ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
    
    
    
    
    
    # Default target.
    all: begin gccversion sizebefore build sizeafter end
    
    # Change the build target to build a HEX file or a library.
    build: elf hex eep lss sym
    #build: lib
    
    
    elf: $(TARGET).elf
    hex: $(TARGET).hex
    eep: $(TARGET).eep
    lss: $(TARGET).lss
    sym: $(TARGET).sym
    LIBNAME=lib$(TARGET).a
    lib: $(LIBNAME)
    
    
    
    # Eye candy.
    # AVR Studio 3.x does not check make's exit code but relies on
    # the following magic strings to be generated by the compile job.
    begin:
    	@echo
    	@echo $(MSG_BEGIN)
    
    end:
    	@echo $(MSG_END)
    	@echo
    
    
    # Display size of file.
    HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
    ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
    
    sizebefore:
    	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
    	2>/dev/null; echo; fi
    
    sizeafter:
    	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
    	2>/dev/null; echo; fi
    
    
    
    # Display compiler version information.
    gccversion : 
    	@$(CC) --version
    
    
    
    # Program the device.  
    program: $(TARGET).hex $(TARGET).eep
    	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
    
    
    # Generate avr-gdb config/init file which does the following:
    #     define the reset signal, load the target file, connect to target, and set 
    #     a breakpoint at main().
    gdb-config: 
    	@$(REMOVE) $(GDBINIT_FILE)
    	@echo define reset >> $(GDBINIT_FILE)
    	@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
    	@echo end >> $(GDBINIT_FILE)
    	@echo file $(TARGET).elf >> $(GDBINIT_FILE)
    	@echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
    ifeq ($(DEBUG_BACKEND),simulavr)
    	@echo load  >> $(GDBINIT_FILE)
    endif
    	@echo break main >> $(GDBINIT_FILE)
    
    debug: gdb-config $(TARGET).elf
    ifeq ($(DEBUG_BACKEND), avarice)
    	@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
    	@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
    	$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
    	@$(WINSHELL) /c pause
    
    else
    	@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
    	$(DEBUG_MFREQ) --port $(DEBUG_PORT)
    endif
    	@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
    
    
    
    
    # Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
    COFFCONVERT = $(OBJCOPY) --debugging
    COFFCONVERT += --change-section-address .data-0x800000
    COFFCONVERT += --change-section-address .bss-0x800000
    COFFCONVERT += --change-section-address .noinit-0x800000
    COFFCONVERT += --change-section-address .eeprom-0x810000
    
    
    
    coff: $(TARGET).elf
    	@echo
    	@echo $(MSG_COFF) $(TARGET).cof
    	$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
    
    
    extcoff: $(TARGET).elf
    	@echo
    	@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
    	$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
    
    
    
    # Create final output files (.hex, .eep) from ELF output file.
    %.hex: %.elf
    	@echo
    	@echo $(MSG_FLASH) $@
    	$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock $< $@
    
    %.eep: %.elf
    	@echo
    	@echo $(MSG_EEPROM) $@
    	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
    	--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
    
    # Create extended listing file from ELF output file.
    %.lss: %.elf
    	@echo
    	@echo $(MSG_EXTENDED_LISTING) $@
    	$(OBJDUMP) -h -S -z $< > $@
    
    # Create a symbol table from ELF output file.
    %.sym: %.elf
    	@echo
    	@echo $(MSG_SYMBOL_TABLE) $@
    	$(NM) -n $< > $@
    
    
    
    # Create library from object files.
    .SECONDARY : $(TARGET).a
    .PRECIOUS : $(OBJ)
    %.a: $(OBJ)
    	@echo
    	@echo $(MSG_CREATING_LIBRARY) $@
    	$(AR) $@ $(OBJ)
    
    
    # Link: create ELF output file from object files.
    .SECONDARY : $(TARGET).elf
    .PRECIOUS : $(OBJ)
    %.elf: $(OBJ)
    	@echo
    	@echo $(MSG_LINKING) $@
    	$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
    
    
    # Compile: create object files from C source files.
    $(OBJDIR)/%.o : %.c
    	@echo
    	@echo $(MSG_COMPILING) $<
    	$(CC) -c $(ALL_CFLAGS) $< -o $@ 
    
    
    # Compile: create object files from C++ source files.
    $(OBJDIR)/%.o : %.cpp
    	@echo
    	@echo $(MSG_COMPILING_CPP) $<
    	$(CC) -c $(ALL_CPPFLAGS) $< -o $@ 
    
    
    # Compile: create assembler files from C source files.
    %.s : %.c
    	$(CC) -S $(ALL_CFLAGS) $< -o $@
    
    
    # Compile: create assembler files from C++ source files.
    %.s : %.cpp
    	$(CC) -S $(ALL_CPPFLAGS) $< -o $@
    
    
    # Assemble: create object files from assembler source files.
    $(OBJDIR)/%.o : %.S
    	@echo
    	@echo $(MSG_ASSEMBLING) $<
    	$(CC) -c $(ALL_ASFLAGS) $< -o $@
    
    
    # Create preprocessed source for use in sending a bug report.
    %.i : %.c
    	$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 
    
    
    # Target: clean project.
    clean: begin clean_list end
    
    clean_list :
    	@echo
    	@echo $(MSG_CLEANING)
    	$(REMOVE) $(TARGET).hex
    	$(REMOVE) $(TARGET).eep
    	$(REMOVE) $(TARGET).cof
    	$(REMOVE) $(TARGET).elf
    	$(REMOVE) $(TARGET).map
    	$(REMOVE) $(TARGET).sym
    	$(REMOVE) $(TARGET).lss
    	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
    	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
    	$(REMOVE) $(SRC:.c=.s)
    	$(REMOVE) $(SRC:.c=.d)
    	$(REMOVE) $(SRC:.c=.i)
    	$(REMOVEDIR) .dep
    
    
    # Create object files directory
    $(shell mkdir $(OBJDIR) 2>/dev/null)
    
    
    # Include the dependency files.
    -include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
    
    
    # Listing of phony targets.
    .PHONY : all begin finish end sizebefore sizeafter gccversion \
    build elf hex eep lss sym coff extcoff \
    clean clean_list program debug gdb-config
    
    
    


    Dodano po 9 [minuty]:

    Kusi mnie by spróbować ten sam program na innym mikrokontrolerze ATMEGA328PA (sztuka nówka, miał być do innych celów), różni się tylko rozmiarem pamięci RAM/FLASH/EEPROM.
    Może program nie działa, bo uC jest uszkodzony?
    Kto wie, może akurat trafił się egzemplarz na milion?

    Dodano po 1 [minuty]:

    Innym słabym punktem zawsze może być kwarc (podatny na uszkodzenia mechaniczne, może wtedy niestabilna praca?).
  • #25
    szelus
    Level 34  
    Jeszcze jedno pytanie - czym wysyłasz i odbierasz dane do/z atmegi?
    Zrób tak:
    1. Nie kombinuj za dużo.
    2. Zmień w obecnym programie, aby odsyłał dokładnie to, co odebrał. Opóźnienia na razie zostaw. Zmienne rejestrowe odpuść sobie.
    3. Wyślij ramkę, która ma wszystkie bajty różne.
    4. Wyślij drugą ramkę, która ma bajty jeszcze inne.
    5 Podaj, co wysłałeś i co odebrałeś.
  • #26
    percol
    Level 12  
    @szelus

    OK, zmiany w programie:

    
    
    unsigned char len;
    
    //...
    
    //W pętli while(1){
    //...
    	UCSR0B=(1<<TXEN0);
    	_delay_ms(20);
    	Tx_to_buf();
    	PORTC^=_BV(5);
    	_delay_ms(20);
    //}
    
    



    Rezultat:

    
    
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "zxy"
    0x7a 0x78 0x79 0x0d 0x0a 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "efg"
    0x65 0x66 0x67 0x0d 0x0a 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "123"
    0x31 0x32 0x33 0x0d 0x0a 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "0987"
    0x30 0x39 0x38 0x37 0x0d 0x0a 0x00
    
    


    Wygląda dobrze.
    Ale... jeśli będziemy liczyć sumy kontrolne muszę mieć poprawną długość otrzymanego pakietu, inaczej zostanie on odrzucony (powinien).

    A... przestałem wysyłać na początku znak ':' (elastyczność w tworzeniu ramki).

    Dodano po 5 [minuty]:

    A teraz wprowadziłem na końcu 'len' i popatrz tylko:

    
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x05 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "0123456"
    0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x0d 0x0a 0x0b 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x07 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x07 0x00
    


    Dodano po 4 [minuty]:

    A dodałem tylko dwie linie:

    
    buf[len]=len;
    len++;
    Tx_to_buf();
    


    Zważ, że zwraca dobry string, długość pakietu też właściwa = to co nadane +1 bajt na zmienną len, tylko ta wartość zmiennej 'len' - kluczowej.

    Dodano po 11 [minuty]:

    Zaaranżowałem szybko nowy układ PC <-> RS485:
    ATMEGA jest teraz podłączona do dedykowanego transceivera, podłączonego do tego samego kompa, którym ją programuję.
    Teraz ma warunki super-, hiper- ... krótki przewód linii, ekskluzywny dostęp ...

    Te testy które podałem wcześniej były przeprowadzone na tym właśnie układzie.
    To nie problem w transmisji.
    IMO, albo kompilator bruździ albo coś jest walnięte z elektroniki (włącznie z uC).

    Dodano po 12 [minuty]:

    Przeoczyłem jeszcze pytanie: "czym wysyłasz..."

    Własny program napisany kiedyś do obsługi RS232 <-> kernel 2.6.x Slackware-10 <-> port COM3 zintegrowany z płytą główną starego, testowego kompa P-233 MMX <-> transceiver Omega 285M (tak jest teraz, a poprzednio ADAM 4520, oba skonfigurowane poprawnie - na obu chodzi lub chodziło kilka urządzeń komercyjnych obsługiwanych przez mój soft w zasadzie bez problemów) <-...-> MAX487 <-> Atmega88PA

    W poprzednim układzie używałem terminatorów (rozległa sieć - konieczność), teraz z nich zrezygnowałem, bo Atmega jest 10 cm od transceivera, wręcz face2face.

    Dodano po 8 [minuty]:

    Oczywiście odsyłam znak więcej niż potrzeba (końcowe 0x00) całkiem świadomie (wbudowane w procedurę Tx_to_buf() od zawsze i w poprzednich wersjach programu), to pomaga w detekcji czy wszystko zostało wysłane, co było w kolejce itd.

    W ostatnich testach, jak widać, wszystko było OK.
  • #27
    arturt134
    Level 27  
    A może WinAVR ma jakiś problem? Ja kiedyś zainstalowałem sobie wersję o której piszesz (20100110), jak tylko się pojawiła i dwa dni później ją wywaliłem. Coś nie chciało mi działać. Co prawda pewnie do tej pory już wszystko poprawili, ale na wszelki wypadek może spróbujesz zainstalować wersję starszą (ja mam na kompie w pracy 20090313 - śmiga OK).
    W końcu tonący brzytwy się chwyta...
  • #28
    percol
    Level 12  
    Zainstalowałem WinAVR-20090313, który jak się okazuje nie ma ATMEGA88PA, więc wziąłem plik nagłówkowy <iom88pa.h> z WinAVR-20100110 i zmieniłem nazwę na <iom88p.h> oraz zawartość (wszędzie gdzie było 88pa zmieniłem na 88p).
    Skompilowało się pięknie (skopiowałem starego Makefile, gdzie zmieniłem tylko typ uC na atmega88p).
    Hex miał trochę inny rozmiar niż otrzymany z nowszej wersji ale cóż ...

    Oto co otrzymałem po przefleszowaniu:


    
    
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x05 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x07 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x07 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x07 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x07 0x00
    
    


    Czyli nadal ten sam błąd. :-(

    Dodano po 4 [minuty]:

    A teraz (po resecie uC) różne pakiety:

    
    
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x05 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "efg"
    0x65 0x66 0x67 0x0d 0x0a 0x07 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "xyz"
    0x78 0x79 0x7a 0x0d 0x0a 0x07 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "123456"
    0x31 0x32 0x33 0x34 0x35 0x36 0x0d 0x0a 0x0a 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "1234"
    0x31 0x32 0x33 0x34 0x0d 0x0a 0x08 0x00
    root@gpib:~/Atmegi/writer/Ametek# ./Skaner.exe -b 1200 -d 8 -s 1 -c 3 -p 0 -x "abc"
    0x61 0x62 0x63 0x0d 0x0a 0x07 0x00
    
    


    Znowu oszukuje ...
  • #29
    szelus
    Level 34  
    Wrzuć (najlepiej jako załącznik) plik .lss po kompilacji razem z obecną wersją kodu w C.
  • #30
    percol
    Level 12  
    Proszę, kod dla obu wersji + pliki nagłówkowe podmienione w starej wersji WinAVR (oryginalny: iom88p_old.h oraz iom88p.h z wersji 20100110 jako iom88pa.h).

    W zasadzie można olać starą wersję - też nie działa i ściągnąć tylko test3-WinAVR20100110.rar - tam są wszystkie pliki generowane przez WinAVR przy kompilacji.