As you could see in the video I of my 7-segment driver with serial input, the left most digit was flickering heavily. I decided to spend some time to improve the code. I did several variations of the program and finally settled on the following one.
In this new version I eliminated Timer0 and changed the timing of actions in the main loop. The flickering didn’t disappear completely but it became much much better.
Here is the new application.
unsigned char digits[] = {
0b01000000, // 0
0b01111001, // 1
0b00100100, // 2
0b00110000, // 3
0b00011001, // 4
0b00010010, // 5
0b00000010, // 6
0b01111000, // 7
0b00000000, // 8
0b00011000 // 9
};
/****************************************
*
****************************************/
void interrupt ISR()
{
if (PIR1bits.RCIF == 1) {
if (FERR == 0)
adcvalue = RCREG;
if (OERR == 1) {
overrun = 1;
}
PIR1bits.RCIF = 0;
}
}
/****************************************
*
****************************************/
void show_overrun_error()
{
LATC0 = 0;
LATC1 = 1;
LATC2 = 1;
LATC3 = 1;
LATC4 = 1;
LATC5 = 1;
LATA4 = 1;
}
/****************************************
*
****************************************/
void show_number(unsigned char number)
{
LATC0 = ((number & 0x1) > 0) ? 1 : 0;
LATC1 = ((number & 0x2) > 0) ? 1 : 0;
LATC2 = ((number & 0x4) > 0) ? 1 : 0;
LATC3 = ((number & 0x8) > 0) ? 1 : 0;
LATC4 = ((number & 0x10) > 0) ? 1 : 0;
LATC5 = ((number & 0x20) > 0) ? 1 : 0;
LATA4 = ((number & 0x40) > 0) ? 1 : 0;
}
/****************************************
*
****************************************/
void calculate_digits()
{
static unsigned int value = 0;
int remainder;
if (value == adcvalue)
return;
if (adcvalue > 999)
adcvalue = 999;
digit1index = adcvalue / 100;
remainder = adcvalue % 100;
digit2index = remainder / 10;
digit3index = remainder % 10;
value = adcvalue;
}
/****************************************
*
****************************************/
void main()
{
OSCCON = 0xF0; // set internal osc to 32Mhz
OPTION_REG = 0x08; // Prescaler not assigned to timer 0
TRISC0 = 0;
TRISC1 = 0;
TRISC2 = 0;
TRISC3 = 0;
TRISC4 = 0;
TRISC5 = 0;
TRISA4 = 0;
TRISA5 = 0;
TRISA2 = 0;
TRISA0 = 0;
TRISA1 = 1;
// configure the RX pin on A1
RXDTSEL = 1;
// configure EUSART BAUD rate: Fosc / 64(n+1)
BRG16 = 0;
BRGH = 0;
// configure the EUSART receiver
CREN = 1;
SYNC = 0;
SPEN = 1;
// The analog bit must be cleared for RX to function
ANSELAbits.ANSA1 = 0;
state = 0;
adcvalue = 0;
// enabling EUSART rx interrupt
PIE1bits.RCIE = 1;
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;
while(1) {
switch (state) {
case 0 * INTERVAL:
LATA0 = 0;
LATA2 = 1;
LATA5 = 0;
if (overrun == 1)
show_overrun_error();
else
show_number(digits[digit2index]);
break;
case 1 * INTERVAL:
LATA0 = 1;
LATA2 = 0;
LATA5 = 0;
if (overrun == 1)
show_overrun_error();
else
show_number(digits[digit3index]);
break;
case 2 * INTERVAL:
LATA5 = 1;
LATA2 = 0;
LATA0 = 0;
if (overrun == 1)
show_overrun_error();
else
show_number(digits[digit1index]);
break;
case 3 * INTERVAL:
calculate_digits();
break;
}
if (state >= 3 * INTERVAL)
state = 0;
else
state++;
};
}
I found something strange while working on this code. My main development computer is a MAC mini but it does not recognise my fake PICKIT3. Therefore I normally develop on a virtual Windows machine that runs under VirtualBox on my MAC. This time I decided to run the IDE on the MAC and run only the IPE (the programmer) on the Windows. When I compiled the code above on the MAC and downloaded it with Windows, the application behaved very strangely. It would suddenly crash, or come to a halt at random points in time. Other variations of this program caused a read overflow very quickly. It was very strange and nothing I did fixed the problem. So I went back to my normal environment and ran exactly the same code on the Windows machine and it just worked.
I will be very glad if anyone could explain why this happens. I did compare all the compiler settings, especially the optimisation settings, between the two computers and they are identical.