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?)
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ę!
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ę!