Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Rasenmaehroboter fuer schwierige und grosse Gaerten im Test

(fifo_init)
(Verbesserungsvorschläge)
 
(Eine dazwischenliegende Version desselben Benutzers wird nicht angezeigt)
Zeile 48: Zeile 48:
 
  #endif  
 
  #endif  
 
-- [[Benutzer:SprinterSB|SprinterSB]] 23:51, 7. Nov 2008 (CET)
 
-- [[Benutzer:SprinterSB|SprinterSB]] 23:51, 7. Nov 2008 (CET)
 +
 +
== Verbesserungsvorschläge ==
 +
 +
Vielen Dank erst ein Mal für diesen Code!
 +
Nachdem ich nun einige Zeit damit verbrachte diese bei mir zu integrieren sind mir ein paar Sachen aufgefallen:
 +
* Bei der Berechnug von OCR1A für das Bittiming sollte eine 1 abgezogen werden, da sonst die Freuenz etwas zu niedrig ist. Einfluss verschärft sich mit höherer Baudrate und kleineren Werten für OCR1A.
 +
OCR1A = F_CPU / SOFTUART_BAUDRATE - 1;
 +
* Nach der Atmel Appnote für effizienten C-Code ist ein predecrement schneller als ein postincrement. Setzt man im InputCapture Interrupt inbits auf 10 und verringert sie, so spart man 10 Bytes. Eine lokale Kopie von inbits ist ebenfalls nicht zwingend nötig. Wenn man den Input-Pin direkt am Anfang des CompareB Interrupts abfragt ist man noch einen kleinen Moment weiter in der Mitte des Bits. Auch kann man die 4 Takte, die der InputCaptureNoiseCanceller braucht noch von ICR1 abziehen um weiter in der Mitte der Bitzeit zu samplen.
 +
// Detects start bit (falling edge)
 +
ISR (TIM1_CAPT_vect)
 +
{
 +
    // Add half bit duration to value from start bit (we lost four bits for noise cancelling)
 +
    uint16_t ocr1b = ICR1 + (F_CPU / SOFTUART_BAUDRATE / 2) - 4;
 +
    if (ocr1b >= (F_CPU / SOFTUART_BAUDRATE - 1))
 +
        ocr1b -= (F_CPU / SOFTUART_BAUDRATE - 1);
 +
    OCR1B = ocr1b;<br>
 +
    // Disable InputCapture interrupt and enable CompareB interrupt to collect bits
 +
    TIFR1 |= (1 << OCF1B);
 +
    TIMSK1 = (TIMSK1 & ~(1 << ICIE1)) | (1 << OCIE1B);
 +
 +
    // Begin with empty frame
 +
    inframe = 0;
 +
    inbits = 10;
 +
}
 +
 +
// Receive and save bits
 +
ISR (TIM1_COMPB_vect)
 +
{
 +
    // Cache the current receive pin value for later checking
 +
    uint8_t rxPin = SOFTUART_RX_PIN & (1 << SOFTUART_RX_BIT);
 +
 +
    uint16_t localInFrame = inframe >> 1;
 +
    if (rxPin)
 +
        localInFrame |= (1 << 9);
 +
 
 +
    if (!--inbits)
 +
    {
 +
        if ((localInFrame & 1) == 0 && localInFrame >= (1 << 9))
 +
            fifo_put(&receiveFifo, localInFrame >> 1);
 +
           
 +
        // re-enable input capture & disable output compare1b
 +
        TIFR1 = (1 << ICF1);
 +
        TIMSK1 = (TIMSK1 & ~(1 << OCIE1B)) | (1 << ICIE1);
 +
    }
 +
    else
 +
        inframe = localInFrame;
 +
}
 +
Auch wenn man das wahrscheinlich aus Rechenzeitgründen nicht machen wird, läuft es bei mir so stabil bei 9600 Baud und 1 MHz (Compiler Optimierung auf Größe, also Standardeinstellung).
 +
--[[Benutzer:FrankB|FrankB]] 08:53, 30. Mai 2012 (CEST)

Aktuelle Version vom 30. Mai 2012, 07:53 Uhr

Full oder Half-Duplex?

Sollte dazugesagt werden, ob das Verfahren full- oder halbduplex arbeiten kann.

--PicNick 14:38, 7. Feb 2006 (CET)


Vom Konzept her hatte ich es als full duplex ausgelegt. Momentan denke ich auch, daß die Timer-Lösung das leistet. Allerdings ist das natürlich auch abhängig davon, was sonst so im System abgeht, insbesondere die Interrupt-Last und respond Zeiten. Falls die hoch werden, ist zu erwarten, daß die Übertragung nicht mehr immer korrekt ist, weil die Zeiten nicht eingehalten werden. Dadurch sampelt man nicht mehr in der Mitte eines Bits bzw. das Signal fängt an zu jittern, man verpasst Zeichen. Das Verpassen sollte durch eine FIFO entschärft werden. Alternativ wäre an eine HW-Flussteuerung zu denken, zumindest in eine Richtung. Eingehende Analysen hab ich nicht gemacht und auch nicht die Mittel dazu. Falls du Vorschläge hast, können die ja eingebaut werden, oder falls du ne Stelle siehst, warum es nicht voll Duplex ist.

--SprinterSB 11:30, 8. Feb 2006 (CET)


Sollte keine Kritik sein. Ich hab zusammen mit einen Forum User mal die entsprechende AVR-Appl-Note f. Soft Uart durchgezogen, mir reicht es :-) . --PicNick 19:44, 8. Feb 2006 (CET)

Senden ohneStart/Stop/Parität ?

TurboFischer schrieb:

Hallo,
ich bin neu hier und hab deinen Beitrag im Wiki über den Software Uart gesehen. Jetzt hätte ich da eine Frage dazu. Ich brauche für mein Projekt nur einen Teil und zwar um Daten zu übertragen, empfangen brauch ich nichts.
Jetzt wollte ich fragen ob es möglich ist Daten ohne Start-, Stop- und Paritätsbit zu senden? Also rein nur die Daten das die in der eingestellten Baudrate an dem definierten PIN ausgesendet werden? Wenn ja wie man das realiesieren könnte bzw. was man ändern müste.
Wäre über deine Hilfe sehr dankbar. Vielen Dank im Voraus.
Mit freundlichen Grüssen
Thomas

Das Paritätsbit wird ohnehin nicht bedient, die Software implementiert 8N1.

Ob Code für Empfänger/Sender erzeugt wird, sollte durch die Defines SUART_RXD resp. SUART_TXD zu steuern sein, weil nur mit gesetzten Defines die Codesequenzen eingeblendet sind.

Um Start/Stop zu vermeiden machst du folgende Änderung in uart_putc:

   // frame = *.7.6.5.4.3.2.1.0  *=Endemarke(1)
   outframe = (1 << 8) | ((uint8_t) c);

Aber ich vermute mal, weder Start noch Stop zu senden ist nicht das, was du willst...

fifo_init

Frage als Neuling: Müsste die FIFO nicht in der funktion uart_init initialisiert werden?

...wo auch immer, irgendwo sollte die initialisiert werden, zB mit

#if defined (SUART_RXD) && defined (_FIFO_H_)
   fifo_init (&infifo, inbuf, INBUF_SIZE);
#endif 

-- SprinterSB 23:51, 7. Nov 2008 (CET)

Verbesserungsvorschläge

Vielen Dank erst ein Mal für diesen Code! Nachdem ich nun einige Zeit damit verbrachte diese bei mir zu integrieren sind mir ein paar Sachen aufgefallen:

  • Bei der Berechnug von OCR1A für das Bittiming sollte eine 1 abgezogen werden, da sonst die Freuenz etwas zu niedrig ist. Einfluss verschärft sich mit höherer Baudrate und kleineren Werten für OCR1A.
OCR1A = F_CPU / SOFTUART_BAUDRATE - 1;
  • Nach der Atmel Appnote für effizienten C-Code ist ein predecrement schneller als ein postincrement. Setzt man im InputCapture Interrupt inbits auf 10 und verringert sie, so spart man 10 Bytes. Eine lokale Kopie von inbits ist ebenfalls nicht zwingend nötig. Wenn man den Input-Pin direkt am Anfang des CompareB Interrupts abfragt ist man noch einen kleinen Moment weiter in der Mitte des Bits. Auch kann man die 4 Takte, die der InputCaptureNoiseCanceller braucht noch von ICR1 abziehen um weiter in der Mitte der Bitzeit zu samplen.
// Detects start bit (falling edge)
ISR (TIM1_CAPT_vect)
{
    // Add half bit duration to value from start bit (we lost four bits for noise cancelling)
    uint16_t ocr1b = ICR1 + (F_CPU / SOFTUART_BAUDRATE / 2) - 4;
    if (ocr1b >= (F_CPU / SOFTUART_BAUDRATE - 1))
        ocr1b -= (F_CPU / SOFTUART_BAUDRATE - 1);
    OCR1B = ocr1b;
// Disable InputCapture interrupt and enable CompareB interrupt to collect bits TIFR1 |= (1 << OCF1B); TIMSK1 = (TIMSK1 & ~(1 << ICIE1)) | (1 << OCIE1B); // Begin with empty frame inframe = 0; inbits = 10; }
// Receive and save bits
ISR (TIM1_COMPB_vect)
{
    // Cache the current receive pin value for later checking
    uint8_t rxPin = SOFTUART_RX_PIN & (1 << SOFTUART_RX_BIT);

    uint16_t localInFrame = inframe >> 1;
    if (rxPin)
        localInFrame |= (1 << 9);
  
    if (!--inbits)
    {
        if ((localInFrame & 1) == 0 && localInFrame >= (1 << 9))
            fifo_put(&receiveFifo, localInFrame >> 1);
            
        // re-enable input capture & disable output compare1b
        TIFR1 = (1 << ICF1);
        TIMSK1 = (TIMSK1 & ~(1 << OCIE1B)) | (1 << ICIE1);
    }
    else
        inframe = localInFrame;
}

Auch wenn man das wahrscheinlich aus Rechenzeitgründen nicht machen wird, läuft es bei mir so stabil bei 9600 Baud und 1 MHz (Compiler Optimierung auf Größe, also Standardeinstellung). --FrankB 08:53, 30. Mai 2012 (CEST)


LiFePO4 Speicher Test