Tuesday, April 6, 2010

PIC16C72/PIC16F72 based DC voltmeter

PIC16C72/PIC16F72 based DC voltmeter

// Program : Calculates the input voltage of ADC and display the result in a
// 4-digit multiplexed 7-segment display
// Device : PIC16C72/PIC16F72
// Clock : 4MHz

#define digit1 PORTB.F0
#define digit2 PORTB.F1
#define digit3 PORTB.F2
#define digit4 PORTB.F3
#define decimal PORTC.F7

void delay() { // Function for 5mS delay
delay_ms(5);
}

unsigned char display(unsigned char no) { // Function for returning mask values
unsigned char pattern;
unsigned char segment[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66,
0x6D, 0x7D, 0x07, 0x7F, 0x6F};
pattern = segment[no]; // Patterns to be returned
return (pattern);
}

/* Main program starts here */

void main() { unsigned char units, tens, hundreds, thousands;
unsigned long adc_val;

TRISA = 0xFF; // PORTA as input
TRISB = 0x00; // PORTB as output
TRISC = 0x00; // PORTC as output
ADCON0 = 0x41; // Configuring ADC
ADCON1 = 0x00;
Start: // Endless loop
delay();
ADCON0.F2 = 1; // Start conversion
Wait: // Loops until conversion stops
delay();
if (ADCON0.F2 == 1) goto wait; // Checks conversion status
adc_val = ADRES; // Reads ADC register
adc_val = (adc_val*5000)>>8; // Converts adc value to volts
adc_val = adc_val/10; // Omits LSD

/* Converts adc_val to four individual digits */

thousands = adc_val / 1000; // digit_thousands
adc_val = adc_val % 1000;
hundreds = adc_val / 100; // digit_hundreds
adc_val = adc_val % 100;
tens = adc_val / 10; // digit_tens
units = adc_val % 10; // digit_units

/* Formats the digits to desired configuration */

if (units > 5) {
tens = tens + 1; // Add carry to ten's place
units = 0; // Clear Unit's place
}
if (tens > 9) {
hundreds = hundreds + 1; // Add carry to hundred's place
tens = 0; // Clear tens's place
}
if (hundreds > 9) {
thousands = thousands + 1; // Add carry to thousand's place
hundreds = 0; // Clear hundred's place
}

/* Loads mask values to digits */

PORTC = display(thousands); // Send to PORTC
digit1 = 0; // Enable digit 1
delay(); // Add delay
digit1 = 1; // Disable digit 1

PORTC = display(hundreds); // Send to PORTC
digit2 = 0; // Enable digit 2
decimal = 1; // Enable decimal point
delay(); // Add delay
digit2 = 1; // Disable digit 2
decimal = 0; // Disable decimal point

PORTC = display(tens); // Send to PORTC
digit3 = 0; // Enable digit 3
delay(); // Add delay
digit3 = 1; // Disable digit 3

PORTC = display(units); // Send to PORTC
digit4 = 0; // Enable digit 4
delay(); // Add delay
digit4 = 1; // Disable digit 4

goto Start // Repeat forever
}