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
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