PIC 16F688 ADC
This is a little ADC demo, based on the PIC 16F688. I'm using 8-bit analog converter, that's 255, not the 1023 a 10-bit has.
// INCLUDE LIBRARIES
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
// CONFIGURATION BITS
#pragma config FOSC = HS // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown Out Detect (BOR enabled)
#pragma config IESO = ON // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)
// DEFINITIONS
#define _XTAL_FREQ 4000000
// GLOBAL VARIABLES
/*
unsigned int adc_raw;
unsigned int mV;
unsigned int result;
*/
short raw_adc, mV, V, Vtenth, result;
short x, y, z;
// FUNCTION PROTOTYPES
void osc_tune(void);
void init_adc(void);
void read_adc(void);
void uart_init(void);
void putch(unsigned char byte);
// FUNCTIONS
// Oscillator tuning
void osc_tune(void) {
OSCCONbits.IRCF0 = 0b110; // Internal Osc Freq Select bit => 4MHz
OSCCONbits.HTS = 1; // Status bit, high freq => Stable
OSCCONbits.OSTS = 1; // Osc startup time out => dev run from external
OSCCONbits.LTS = 1; // Low freq bit => stable
OSCCONbits.SCS = 0; // External osc used for system clock
}
// Initialize the ADC module
void init_adc(void) {
ADCON0bits.ADFM = 1; // Right justified
ADCON0bits.VCFG = 0; // Voltage ref => VDD
ADCON0bits.CHS = 0b111; // Analog channel => AN7
ADCON0bits.ADON = 1; // ADC enable bit
ADCON1bits.ADCS = 0b000; // A/D Conversion clock bit
}
// Read the ADC port
void read_adc(void) {
ADCON0bits.GO = 1; // A/D Conversion is in progress
__delay_us(10);
while (ADCON0bits.nDONE); // Wait for AD to complete
}
// Configuring the ESUART port
void uart_init(void){
/*
4MHz
* 16000000 / 9600 = 1666.6666
* 1666.6666 / 64 = 26.0416
* 26.0416 - 1 = 25.0416
* 25.0416 = 25
*/
TXSTAbits.BRGH = 1; // Setting BRGH to use LOW speed
TXSTAbits.SYNC = 0; // Setting async mode
TXSTAbits.TX9 = 0; // Setting 8-bit transmission
RCSTAbits.CREN = 1; // Enable continious receive
SPBRG = 25; // Setting the SPBRG register to use 16MHz with BRGH 0
PIE1bits.RCIE = 1; // USART receive interrupt enable
RCSTAbits.SPEN = 1; // Enable serial port
TXSTAbits.TXEN = 1; // Enable transmit
}
// Adding New line and Carrier return
void putch(unsigned char byte){ // Adding Carrier Return and Line feed
while(!TXSTAbits.TRMT);
TXREG = byte;
if ('\n'==byte){
while (!TXSTAbits.TRMT);
TXREG = '\r';
}
return;
}
// MAIN PROGRAM
void main(void) {
ANSEL = 0b00000000; // Disable all analog inputs
ANSELbits.ANS7 = 1; // Enabling analog input on AN3
TRISA = 0b00000000; // Set TRISA to output
TRISC = 0b00000000; // Set TRISC to output
TRISCbits.TRISC3 = 1; // Enable input on RC3/AN7
CMCON0 = 0x07; // Disable comparators
osc_tune();
init_adc();
uart_init();
__delay_ms(2000);
printf("\n\nADC test\n");
while (1) {
read_adc(); // Read the ADC value
x = ADRESH; // A/D High
y = ADRESL; // A/D Low
raw_adc = (x << 6) | (y >> 2); // Combine ADRESH & ADRESL to ADC
mV = (4900/255) * raw_adc; // Calculate the millivolt
V = mV /1000; // Calculate the volt
Vtenth = mV % 1000; // Calculate the remainder
printf("ADC: %d\tmV: %d\tV: %d.%d\n", raw_adc, mV, V, Vtenth); // Print everything
__delay_ms(1000); // Wait a sec
}
}