PIC18F25K80 4 > 20 gibt wahr zurück. Wie ist das möglich?

Ich verwende solchen Code auf PIC18F25K80, der mit dem xc8-Compiler kompiliert wurde:

unsigned long kline_kw1281_byte_time = 0;

void sendKline(void) {
  klineWrite(0x9);
  while (klineBusy());
  kline_kw1281_byte_time = millis();
  while (!klineAvailable()) {
      if (kline_kw1281_byte_time_out()) {
          mStatus = DISCONNECTED;
          while(Busy1USART());
          Write1USART(0x00);
          return;
      }
  }
}


bit kline_kw1281_byte_time_out(void) {
    unsigned long time_out = millis() - kline_kw1281_byte_time;

    if (time_out > 20){
        while(Busy1USART());
        Write1USART(time_out);
        return 1;
    } else
        return 0;
}

und ich habe ein seltsames Problem. In kline_kw1281_byte_time_out()der Funktion habe ich eine wahre Aussage für, drucke time_out > 20aber eine niedrigere Zahl als 20. Dies geschieht zufällig. Write1USART(time_out)Die Funktion arbeitet die meiste Zeit korrekt.

das ist millis() Code:

#include <p18cxxx.h>
#include "timer0.h"

volatile unsigned long runtime_millis;

void initialize_timer0() {
    T0CON = 0b11000011;
    INTCONbits.TMR0IE = 1;
    INTCON2bits.TMR0IP = 1; //set timer0 interrupt priority high
    INTCONbits.TMR0IF = 0; //reset timer0 interrupt flag
}

void timer0(void) {
    runtime_millis++;
    TMR0L = 8;
    INTCONbits.TMR0IF = 0;
}

unsigned long millis(void) {
    return runtime_millis;
}

void delay(unsigned long ms) {
    unsigned long cTime = runtime_millis;
    while (runtime_millis - cTime < ms);
}
Ich kann das von Ihnen angegebene Problem nicht sehen, aber ich kann eines sehen, bei delay()dem es fehlschlagen kann, wenn der runtime_millisZähler umbricht. Ein Compiler kann Code enthalten, der das Overflag testet und Ihnen die falsche Antwort gibt. Verwenden Sie besser ein Sprungbrett do elapsed = runtime_millis - cTime; while (elapsed < ms);. Seien Sie auch vorsichtig, wenn Sie einen Wert lesen, der unter Interrupt geändert wird, der größer als ein Prozessorregister ist, damit er sich nicht zwischen den erforderlichen mehreren Speicherlesevorgängen ändert. Deaktivieren Sie den Interrupt besser, während Sie den Zähler in eine andere Variable einlesen.
der Wert von time_out könnte sich ändern (vielleicht durch Code in einem Interrupt-Thread oder ähnlichem). Versuchen Sie, den Wert von time_out in einer anderen Variablen zu speichern, damit Sie sicher sind, dass der Wert zum Zeitpunkt der Auswertung des 'if'-Tests derselbe ist wie beim Senden des Werts an den UART. Auch wenn der Wert 4 ist, könnte es eine ASCII '4' sein, die 52 ist, wenn es eine ganze Zahl ist. '4' > 20 ist genauso wahr wie 'A' > 20.

Antworten (1)

if (time_out > 20){
    while(Busy1USART());
    Write1USART(time_out);

Dies schreibt time_outals ASCII-Zeichen in das USART-Modul. Wenn Sie „4“ über dem USART sehen, bedeutet dies, dass das ASCII-Zeichen „4“, Realwert 0x34, gesendet wird. Und 0x34, 52 dezimal, ist größer als 20.

Wenn Sie den Dezimalwert als Zeichenfolge in USART drucken möchten, können Sie dies tun:

#define putch Write1USART 

printf("%ul", time_out);

Die printf()Funktion formatiert time_outals unsigned long (daher %ul) und schreibt es Byte für Byte in putch(). putch()sollte daher die Signatur haben:

void putch(unsigned char);

Das #defineim obigen Beispiel stellt sicher, Write1USART()dass für verwendet wird putch().