I'm using such code on PIC18F25K80 compiled with xc8 compiler:
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;
}
and I have strange issue. In kline_kw1281_byte_time_out()
function I have true statement for time_out > 20
but Write1USART(time_out)
prints me lower number than 20. This happens random. The function most of the time works correctly.
this is 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);
}
delay()
which can fail when theruntime_millis
counter wraps. A compiler can include code that tests the overflag and gives you the wrong answer. Better to use a stepping stonedo elapsed = runtime_millis - cTime; while (elapsed < ms);
. Also be careful when reading a value which is altered under interrupt, that is larger than a processor register, lest it changes between the multiple memory reads required. Better to disable the interrupt while you read the counter into another variable. \$\endgroup\$