Saturday, May 30, 2020

PIC16F887 reads the ADC using Interrupt

The ADC module could trigger an interrupt flag when the reading is completed. Using the interrupt makes the running tasks more effective since it doesn't need to wait for reading completion in the main program loop.

To use the ADC interrupt, we must enable the,
  • Global interrupt control bit (GIE)of the INTCON register
  •  ADC interrupt enable bit (ADIE) of the PIE1 register,
and clear the ADC complete reading interrupt flag (ADIF) of the PIR1 register. 

To read the ADC using interrupt method,
  1. set 'GO' of the ADCON0 to '1'
  2. test the ADIF flag 
  3. if ADIF = 1, we can get the ADC result
  4. clear ADIF
Programming the interrupt of ADC reading

Programming the interrupt of ADC reading

Programming the interrupt of ADC reading

In this example, I use ADC interrupt to return a completed ADC reading result. Timer 0 is used for initiating the ADC reading for every one second. Both ADC and timer use interrupt ISR.

Programming the interrupt of ADC reading
Analog voltage input fed to AN12. A multiplexed SSD display the ADC reading
result in decimal.

C source code's here:

#include<xc.h>
// PIC16F887 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = XT
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config IESO = ON
#pragma config FCMEN = ON
#pragma config LVP = ON
// CONFIG2
#pragma config BOR4V = BOR40V
#pragma config WRT = OFF
/*_XTAL_FREQ use for __delay*/
#define _XTAL_FREQ 4000000

void driveDisplays(unsigned int result){
 unsigned char ssd[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
 0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
 //Digit 1 1000's
 PORTD=0x00;
 PORTC=ssd[result/1000];
 if(result>=1000)PORTD=0x01;
 __delay_ms(10);
 //Digit 2 100's
 PORTD=0x00;
 PORTC=ssd[(result%1000)/100];
 if(result>=100)
     PORTD=0x02;
 __delay_ms(10);
 //Digit 3 10's
 PORTD=0x00;
 PORTC=ssd[(result%100)/10];
 if(result>=10)
     PORTD=0x04;
 __delay_ms(10);
 //Digit 4 1's
 PORTD=0x00;
 PORTC=ssd[result%10];
 PORTD=0x08;
 __delay_ms(10);
}
unsigned int readADC(void){
    GO=1;
    while(GO);
    __delay_ms(10);
    return (ADRESH<<8)+ADRESL;
}
void portSetup(void){
    /*Analog and digital Port
     Configuration*/
    PORTB=0x00;
    PORTC=0x00;
    PORTD=0x00;
    TRISB=0x01;
    TRISC=0x00;
    TRISD=0x00;
}
void adcSetup(void){
    /*Result is right justify*/
    ADFM=1;
    /*By default is analog,
     but again set it to analog*/
    ANS12=1;
    /*Select FRC Clock of ADC module*/
    ADCON0bits.ADCS=0x03;
    /*Turn on ADC Module*/
    ADON=1;
    /*Select AN12 RB0*/
    ADCON0bits.CHS=0b1100;
    
}
void interruptSetup(void){
    /*Select FOSC*/
    T0CS=0;
    /*Select timer 0 Prescaler*/
    PSA=0;
    /*Enable Timer 0 Overflow
     interrupt*/
    T0IE=1;
    /*Turn on Global interrupt
     Control*/
    GIE=1;
    /*Enable Peripheral Interrupt*/
    PEIE=1;
    /*Enable ADC complete reading
     interrupt*/
    ADIE=1;
    /*Clear ADC interrupt Flag*/
    ADIF=0;
    /*Clear interrupt flag*/
    T0IF=0;
    /*Clear timer 0 register*/
    TMR0=0;
}
unsigned int adcResult;
unsigned char oneSecondTick=0;
void main(void){
    portSetup();
    adcSetup();
    interruptSetup();    
    while(1){
        driveDisplays(adcResult);
    }
}
void interrupt _ISR(void){
    /*If timer 0 Overflow*/
    if(T0IF){
        oneSecondTick+=1;
        T0IF=0;
    }
    /*If it's one second*/
    if(oneSecondTick>=15){
        oneSecondTick=0;
        GO=1; 
    }
    /*If ADC reading completed*/   
      if(ADIF){
        adcResult=(ADRESH<<8)+ADRESL;
        ADIF=0;
    }
}

Programming the interrupt of ADC reading
The ADC reading acquires 921 digital value result in decimal. 

Back to main tutorials page.




No comments:

Post a Comment

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (56) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (47) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (71) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (3) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (31) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)