Forum: Compiler & IDEs Ganz kleines UART timing problem (?)


von Marius Schmidt (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

ich arbeite an ein gerät das eine ROM Karte ausliest (512 kb). Das
auslesen funktioniert anscheinend ohne probleme, nur das UART muckt rum
;)

Ich benutze das usb dev board aus dem shop hier, d.h. mein AVR läuft
auf 10 mhz und zur Übertragung benutze ich den USB<->rs232 konverter
FT232BM.

Also Übertragungsgeschwindigkeit habe ich 312500 baud gewählt (das
ergibt sich aus der Mhz-taktung des AVRs) weil...

1 = 10000000 / (a*16) - 1
a = 312500 Baud

Das übertragen funktioniert auch sehr flott, allerdings ist die Datei
nicht 100%ig korrekt (zum größten teil sieht alles ok und richtig aus)
und das geht beim Auslesen von Programmcode natürlich gar nicht das da
fehler drin sind!

Anstatt 512kb (524288 byte) zu lesen, werden 525899 byte gelesen
(513kb)... noch schlimmer wird es wenn ich die Geschwindigkeit runter
schraube, da kommen bei 15625 baud nur noch 277kb beim PC an :(

Hier ist der source code meiner momentanen firmware mit reichlich
kommentaren damit ihr wisst was ich da eigentlich machen will:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdint.h>

//#define UART_BAUD_CALC(UART_BAUD_RATE)
((F_CPU)/((UART_BAUD_RATE)*16L)-1)

#define    N_PROG      0x80
#define    HADR      0x20
#define    LADR      0x10
#define    OUTPUT_ENABLE  0x4

#define    LED_GREEN    (1<<2)
#define    LED_RED      (1<<3)

//#define    BAUDRATE    9600

void uart_send(unsigned char c);

int main(void) {

    //port A als eingang (active high)
  DDRA = 0x00;
  PORTA = 0x00;

  //port B und C sind ausgänge zur Speicherkarte
  //port D wird nur für status LEDs benutzt
  DDRB = 0xFF;
  DDRC = 0xFF;
  DDRD = 0xFF;

  //"power on" LED ein
  PORTD = (~LED_GREEN);

  //UART setup
  //Interrupt bei Daten-Empfang
  //Empfang (RX) und Senden (TX) aktivieren
  UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
  UCSRC = (1<<URSEL)|(3<<UCSZ0); //Asynchron 8N1 (8 bit, 1 stop bit)

  //UBRRH=(uint8_t)(UART_BAUD_CALC(BAUDRATE)>>8);
  //UBRRL=(uint8_t)UART_BAUD_CALC(BAUDRATE);
  UBRRH = 0;
  UBRRL = 1; //1 = 10000000 / (a*16) - 1
             //a = 312500 Baud

  //Interrupts aktivieren
  sei();

  //wie geht man in den sleep mode?
  while(1);


}

//ISR für USART receive
SIGNAL(SIG_USART_RECV) {
uint32_t addr;
uint8_t addh;

  // Command-Byte überprüfen
  if(UDR == 0x10) { //voller ROM dump wurde angefordert
    //LEDs ein schalten
    PORTD = (~LED_GREEN) & (~LED_RED);

    //524288b / 1024 = 512kb auslesen
    for(addr=0;addr<524288;addr++) {
      //erster Teil der addresse (high part der Addresse)
      PORTB = (addr >> 10) & 0xFF;
      addh = (addr >> 18) & 0x3;
      PORTC = addh | N_PROG;

      PORTC = addh | N_PROG | HADR;

      PORTC = addh | N_PROG;

      //zweiter Teil der addresse (low part der Addresse)
      PORTB = addr & 0xFF;
      addh = (addr >> 8) & 0x3;
      PORTC = addh | N_PROG;

      PORTC = addh | N_PROG | LADR;

      PORTC = addh | N_PROG;

      //Ausgabe aktivieren
      PORTC = addh | N_PROG | OUTPUT_ENABLE;


      //Ergebnis von Port A per UART an PC senden
      uart_send(PINA);
    }
    //Grüne LED aus schalten
    PORTD = (~LED_GREEN);

  }

}

//Sendefunktion
void uart_send(unsigned char c) {
    while (!(UCSRA & (1<<UDRE))); // warten bis Senden moeglich
    UDR = c;                      // sende Zeichen
}


Nur zur Info für alle die es vlt interessiert: Bei der Speicherkarte
handelt es sich um ein Mask-ROM mit einen multiplexed address bus.
Diese Karte stammt von einem elektronik spielzeug von Nintendo (Pokemon
Mini heißt das ding und die Produktion ist mitlerweile eingestellt) -
mehr infos gibt es auf unserer website http://pokeme.shizzle.it/
werbung mach ;D

Vielen Dank für eure Hilfe!

Mfg,
Marius

Als Dateianhang noch das Programm was ich auf der PC seite verwendet
habe (VB 6.0), es kann gut sein das dort der Fehler liegt...

von Marius Schmidt (Gast)


Lesenswert?

bevor mir einer sagt ich soll den internen oszilator aus schalten - ich
habe folgende fuse bits gesetzt:

- BOOTSZ1
- BOOTSZ0
- BODLEVEL
- BODEN

Weiß einer was die bedeuten? (ich weiß, rtfm...)

Kann man den FT232BM eigentlich reseten, wenn das Programm welches als
letztes zum FT232BM verbunden hat beim beenden die Verbindung zum chip
nicht beendet hat? Jedes mal wenn ich vergesse die Verbindung zu
beenden muss ich nämlich einmal kurz das USB kabel entfernen und neu
einstöpseln. (meine eigentliche frage ist mir aber momentan
wichtiger... :))

von Marius Schmidt (Gast)


Lesenswert?

es handelt sich um einen ATmega16. jetzt sollte alles geklärt sein ;)

von max.p (Gast)


Lesenswert?

Hallo,
hab mir dein programm nur kurz angesehen, aber warum kommentierst du
die berechnung der Bautrate aus? Und wie kommst du auf so einen
seltsame Baudrate? Es gibt meines wissesn nur gewisse
Standartbaudraten, die bei verschiedenen Taktraten verscheiden hohe
fehlerraten erzeugen.
http://www.mikrocontroller.net/forum/read-4-186948.html#new
versuchs mal mit 19200, das ergibt bei 10 Mhz 0,2% fehler.
mfg
Max

von Marius Schmidt (Gast)


Lesenswert?

a=10000000 / (19200*16) - 1
a=31.55208333

wie soll ich denn diese zahl in das UBRR register schreiben? Ich habe
meine Baud rate extra so ausgewählt das ich für UBRR ein ganz-zahliges
Ergebnis habe damit die baud rate eindeutig definiert ist.

von max.p (Gast)


Lesenswert?

also, du gibst am anfang einfach
#define XTAL 10000000UL
#define USART_BAUD_RATE 9600
#define USART_BAUD_SELECT (XTAL/(USART_BAUD_RATE*16l)-1)
ein, damit wird der richtige wert schon beim compilieren berechnet.

und die werte werden dann mit
UBRR0L = USART_BAUD_SELECT;
UBRR0H = USART_BAUD_SELECT >> 8;
in die register geschrieben.
Wenn du einen anderen Quarz oder eine Andere Baudrate haben willst dann
änderst du die Werte einfach bei den defines.

lass einfach mal die 9600 eingestellt, damit hast du die geringste
fehlerwerte.

mfg
Max

von Marius Schmidt (Gast)


Lesenswert?

Jetzt ist alles ganz schlimm :(

Jedes mal wenn ich meine Speicherkarte verbinde kommen nur noch wirre
zeichen (ich habe nur noch ein Test Programm auf den AVR das einfach
nur ein zeichen sendet), wenn ich die Karte wieder raus nehme und einen
chip reset durchführe ist alles normal und mein test zeichen wird
gesendet.

Kann das mit dem Stromverbrauch zusammen hängen? Ich habe glaube ich
nur 100mA zur Verfügung... aber dann ist das doch irgendwie komisch,
das es gestern fast noch funktioniert hat :(

von A.K. (Gast)


Lesenswert?

>      PORTC = addh | N_PROG | OUTPUT_ENABLE;
>      uart_send(PINA);

Wenn das ein Tiny oder Mega ist, dann hat der einen Synchronizer an den
Inputs dran. Der bewirkt, dass hier der Zustand von PINA ungefähr vom
gleichen Zeitpunkt gelesen wird, zu dem PORTC die letzte Änderung
erfährt. Siehe Datasheet unter I/O-Ports.

Also: Da muss mindestens 1 Befehl zwischen die entsprechenden OUT und
IN Befehle.

von Marius Schmidt (Gast)


Lesenswert?

ich glaube es liegt am interface zwischen AVR und FT232BM.

Ich habe einfach mal ein zeichen * 512kb ausgegeben und man sieht daran
deutlich das da was nicht stimmt, ab und zu kommen immer 4 bytes (immer
0x08 0x00 0x80 0x0F) und ich nehme mal an das da etwas mit dem timing
nicht stimmt und dort die fehlerwahrscheinlichkeit einsetzt... das ist
natürlich nur ein gedanke von mir :/

Am ende hat mein Programm dann anstatt 512kb zeichen ~1kb mehr
gespeichert... es liegt definitiv am USART bzw USB.

Ich melde mich nochmal wenn ich meinen quarz habe, falls das immer noch
nichts bringt werde ich mal einen schaltplan machen, vielleicht stimmt
da ja irgendwas nicht (was eigentlich nicht sein kann, da der speicher
der Karte richtig gelesen wird - das was an kommt ist richtig, bis auf
diese 4 bytes die immer wieder auf tauchen)

von Jörg Wunsch (Gast)


Lesenswert?

Neugierig: wenn du sowieso nur USB willst, warum dann erst noch einen
FT232 und die ganze Ärgerei mit der Baudrate und nicht stattdessen
gleich einen FT245?

von Marius Schmidt (Gast)


Lesenswert?

Weil ich nicht weiß wie man den benutzt und ich habe auch nur noch einen
port frei (...dabei hat der ATmega16 ja schon 32 IO pins) und außerdem
war der FT232 bei dem dev board aus den Shop schon mit dabei

Welche Vorteile hat der FT245 denn gegenüber den FT232 außer das man
sich nicht mit Baudraten rum ärgern muss? Also wenn man an seinen AVR
Komponenten anschließt die mit einen parallel bus angesteuert werden
kann es schon eng werden denke ich.

von Marius Schmidt (Gast)


Lesenswert?

Problem gelöst!

Wer hätte das gedacht? Visual Basic war schuld! Ich habe das Programm
in C++ neu geschrieben und es klappt auf anhieb!

Tut mir leid eure Zeit verschwendet zu haben, das nächste mal bin ich
schlauer. Und vielen dank für die guten Tipps :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.