PIC 16F688 ADC average.

Introduction

This little program reads the ADC value of AN7 5 times, stores it in an array, and calculates the average. This perticular examples uses an LM34. This is converted to Celsius.

All the Uart - code is in the uart_header and uart_source files.

The output

Output

The program

// INCLUDE LIBRARIES
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "uart_header.h"

// CONFIGURATION BITS
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA4/OSC2/CLKOUT and RA5/OSC1/CLKIN)
#pragma config WDTE = OFF        // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF      // 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)

#define _XTAL_FREQ 8000000      // Compiler reference

// VARIABLES
unsigned char adc_raw;
float mV, tempC, tempF, sum;
unsigned char str[8];
volatile unsigned char num = 0;
unsigned short adc_values[4];
unsigned short adc_average;

// FUNCTIONS
// Function initialize the ADC moduel
void adc_init(void) {
    ADCON0bits.ADFM     = 1;        // Right justify
    ADCON0bits.VCFG     = 0;        // VDD as reference
    ADCON0bits.CHS      = 0b111;    // Analog channel AN7
    ADCON0bits.ADON     = 1;        // ADC enable
    ADCON1bits.ADCS     = 0b101;    // ADC conversion set bit
}

// Function read the ADC values
void adc_read(void) {
    ADCON0bits.GO       = 1;        // Start ADC
    __delay_us(10);
    while (ADCON0bits.nDONE);       // Wait for ADC to finish
}

// Function to calculate the average of 5 readings
void get_average() {
    for (int i=0;i<5;i++) {
        adc_read();                     // Call func adc_read())
        adc_raw = (ADRESH<<8)+ADRESL;   // Move ADRESH 8 shift left, and add ADRESL
        adc_values[i] = adc_raw;        // Put value in table/array
        adc_average += adc_values[i];   // Adding next value to variable
    }

    itoa(str, adc_average, 10);
    uart_send_str("Sum: ");
    uart_send_str(str);
    sum = adc_average / 5;              // Calculate the average
    itoa(str, sum, 10);
    uart_send_str(" - Average: ");
    uart_send_str(str);
    uart_send_str(" - ");

    tempF = (sum * 4900) / 1024;        // Convert ADC
    tempF = tempF / 10;                 //  to Fahrenheit
    itoa(str, tempF, 10);

    uart_send_str(str);
    uart_send_str(" F\t");

    tempC = (tempF - 32) / 1.8;         // Convert F to C.
    itoa(str, tempC, 10);

    uart_send_str(str);
    uart_send_str(" C\t");

uart_send_str("\r\n");
adc_average = 0;
}

// The interrupt function
void __interrupt() ISR(void) {
    num++;
    if (num == 18) {
        get_average();
        num = 0;
    }
    TMR0 = 39;
    INTCONbits.T0IF = 0;
}

// Main program
void main(void) {
    CMCON0      = 0x07;             // Turn comparato off
    TRISC       = 0b111000;         // RX -TX - AN7 as input
    PORTC       = 0b000000;         // Set all pins LOW

    ANSEL       = 0b10000000;       // AN7 set as input

    OPTION_REG  = 0b00000111;
    TMR0        = 39;
    INTCON      = 0b10100000;

    uart_init();
    adc_init();

    uart_send_str("Start...\r\n");

    while (1) {
        // Do nothing, it's all taken care of in the interrupt / timer0
    }
    return;
}

Uart_header

#ifndef UART_INIT_HEADER_H
#define UART_INIT_HEADER_H

#ifdef  __cplusplus
extern "C" {
#endif

#include <xc.h>
void uart_init();
void uart_tx(char out);
char uart_rx();
void uart_send_str(const char *);

#ifdef  __cplusplus
}
#endif

#endif  /* UART_INIT_HEADER_H */

Uart_source

#include "uart_header.h"

// Function to initialize the uart port
void uart_init() {
    TXSTAbits.BRGH  = 0; // high baud selection bit, 1=high, 0=low
    TXSTAbits.SYNC  = 0; // USART mode selection bit, 1=sync mode, 0=async mode
    TXSTAbits.TX9   = 0; // 9-bit selection bit, 1=9-bit transmission, 0=8-bit trans
    RCSTAbits.CREN  = 1; // continous receive enable bit, 1=Enable continous receive.
    /* 4Mhz -> 9600
     * 4000000 / 16 = 250000
     * 250000 / 9600 = 26.0416
     * 26.0416 - 1 = 25
     * 8MHz -> 9600
     * 8000000 / 64 = 125000
     * 125000 / 9600 = 13.0208
     * 13.0208 - 1 = 12
     */

    SPBRG = 12; // 9600-n-8-1    
    PIE1bits.RCIE   = 1; // USART Receive iterrupt enable bit, 1=enable, 0=disable
    RCSTAbits.SPEN  = 1; // serial port enable bit, 1=serial port enable, 0=disable
    TXSTAbits.TXEN  = 1; // transmit enable bit, 1=Transmit enable, 0=disable  
    return;
}

// Functio to send one char
void uart_tx(char out) {
    while (TXIF == 0);
    TXREG = out;
}

// Function to recieve one char
char uart_rx() {
    while (RCIF == 0);
    if (RCSTAbits.OERR) {
        CREN = 0;
        NOP();
        CREN = 1;
    }
    return (RCREG);
}

// Function to send a string of single chars
void uart_send_str(const char *out) {
    while (*out!='\0') {
        uart_tx(*out);
        out++;
    }
}

The output looks like this: ADC average

blogroll

social