Bus Pirate v3 PIC 24 analog to digital converter example

From DP

(Redirected from BPv3 ADC demo)
Jump to: navigation , search

BPADCDEMO.jpg

Contents

Overview

The Bus Pirate uses the PIC24FJ64GA002 microcontroller, and can be used as a development board. In this demo we'll use the ADC pin to control the MODE LED. If the voltage on the ADC pin drops below 3 volts the LED will turn off.

The code is broken up and explained section by section below. You can Download the full project from our SVN download the full MPLAB 8 project from our SVN].

Basic Configuration

#include <p24fxxxx.h>

Include the C30 compiler definitions for PIC24F microcontrollers

_CONFIG1(    JTAGEN_OFF &     //JTAG port is disabled
            GCP_OFF &         //GSP Memory Code Protection OFF
            GWRP_OFF &         //GCC Flash Write Protection OFF
            COE_OFF &         //
            FWDTEN_OFF &     //Watchdog Timer OFF
            ICS_PGx1)         //debug over PGD1 and PGC1

Configuration bits control the default settings used when the PIC first starts. Things like the clock source need to be configured or code will never run. CONFIG1 register sets up the MCU to the following specs:

  • JTAG is turned off
  • Watchdog Timer is off
  • Debugging is handled by the PGD1 and PGC1 pins


CONFIG2(    FNOSC_FRCPLL &     //Internal FRC with PLL
            OSCIOFNC_ON &    //RA3 is clk out (fosc/2)
            POSCMOD_NONE &     //Primary oscillator disabled
            I2C1SEL_PRI)    //Use default SCL1/SDA1 pins

The CONFIG2 register handles the oscillator selections, we set it up so that the MCU uses the internal FRC oscillator and PLL to drive the processor clock at ...

  • Internal Fast RC oscillator is used as clock base
  • Processor clock (32 MHz), divided by 2 (16 MHz)
#define VREG33_DIR TRISAbits.TRISA0
#define VREG33_EN LATAbits.LATA0
#define MODE_LED_DIR TRISAbits.TRISA1
#define MODE_LED LATAbits.LATA1
  1. defines let us replace confusing hardware names with easy to remember nicknames. Instead of typing LATAbits.LATA0 to work with the pin that switches the voltage regulators on and off, we can use something easy like VREG33_EN.

The variables that end with _DIR are in fact the TRIS bits that set the pin for output(0) or input(1).

#pragma code

This instructs the compiler that the next section is source code. This is not strictly needed.

Additional Setup

int main(void)
{
 
    CLKDIVbits.RCDIV0 = 0;    //clock divider to 0
    AD1PCFG = 0xFFFF;         // Default all pins to digital
    OSCCONbits.SOSCEN = 0;    //Disables the secondary oscilator

Code in the main() function will execute first. In the first line we set the clock divider to 0 by setting the RCDIV0 bit of the CLKDIV register to 0. Next all the pins are configured to be digital, by setting all the bits in the AD1PCFG register to 1s. Finally we disable the secondary oscillator by clearing the SOSCEN bit in the OSCCON register.

[name of register]bits.[name of bit]

C30 bit variables are accessed with this syntax. Names match the registers in the datasheet.

    MODE_LED_DIR = 0;       //sets the Mode LED pin RA1 as output
    MODE_LED = 0;           //turns LED off
    VREG33_DIR =0;          //sets the VREG pin RA0 as output
    VREG33_EN = 1;          //turns on the voltage regulator

The MODE LED pin direction (RA1) is set to output, and then connected to ground (0).

We want to enable the voltage regulators so we can use them in the demo. The voltage regulator enable pins are connected to PIC pin A0 (VREG33), and they turn on when more than 2volts is applied. We set the VREG pin for output, and then set it high (1). The PIC then outputs 3.3volts to the regulator enable pins, turning them on.

ADC configuration

///////////////ADC config//////////////////////////////////
    AD1PCFGbits.PCFG12=0;          //configure RB12 as analog
    AD1CON1bits.SSRC  = 0b111;     // SSRC<3:0> = 111 implies internal
                                   // counter ends sampling and starts
                                   // converting.
    AD1CON3 = 0x1F02;              // Sample time = 31Tad,
                                   // Tad = 2 Tcy
    AD1CHS =12;                    //ADC channel select 12
    AD1CON1bits.ADON =1;           // turn ADC on

Analog to digital converters measure voltage. The ADC/voltage probe pin of the Bus Pirate can measure between 0 and 6volts. We need to assign the ADC to measure from the correct pin (RB12/AN12) and enable it. These settings are explained ad nauseum in the datasheet, we won't dwell on them too much here.

  • Configure the probe pin as an analog input. If you change the demo to measure from a different pin you'll need to set that pin to analog too.
  • Configure for automatic method analog to digital conversions
  • Set the length of time to sample voltage before taking a reading
  • Select the ADC channel to sample from, the probe is attached to pin RB12/ ADC channel 12. If you want to measure from a different pin, substitute the ADC channel connected to that pin here
  • Start the ADC module to get conversions going

Use voltage to control the MODE LED

///FOREVER LOOP///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
    while(1)
    {
        //this just gives us a little delay between measurements
        i =0xFFFFF;                 //sets i to 1048575
        while (i--);                //delay function
 
        //start a measurement with the ADC
        AD1CON1bits.DONE=0;         //resets DONE bit
        AD1CON1bits.SAMP=1;         //start sample
 
        while(AD1CON1bits.DONE==0); //wait for conversion to finish
 
        //get the measurement and use it to control the LED
        voltage = ADC1BUF0;         //get the voltage measurement
        if (voltage > 0x1D1) MODE_LED = 1; //enable LED if measurement is > 3volts
        else MODE_LED = 0;           //disable LED if less than 3volts
   }
}

The processor runs this while() loop continuously.

First two lines in the loop provide a delay of ~1s between measurements. This isn't strictly needed.

After the delay, the DONE bit is cleared in the AD1CON register. This is a flag that will be reset to 1 when the measurement is complete. The measurement is kicked off by writing 1 to the sample bit.

The ADC module will let us know when the conversion is finished by setting the DONE bit to 1. while(AD1CON1bits.DONE==0); continuously checks the DONE bit until it turns to 1.

When the conversion is complete we move the ADC measurement from the ADC1BUF register into our voltage integer variable. The measurement isn't an actual voltage reading like 3.3volts, instead it's returned as a fraction of the PIC power supply. The ADC takes 10bit measurements, so the value is a fraction of 1024. To further complicate things, the ADC probe has two resistors that divide the input voltage in half.

A measurement like 465 (0x1D1 in hexadecimal) can be converted to a voltage as follows:

  1. 465/1024 = 0.45 (fraction of the PIC's 3.3volt power supply)
  2. 0.45 * 3.3volts = 1.5volts (actually read at the ADC pin)
  • 1.5volts * 2 = 3volts (multiply by two due to voltage divider on probe)

To check if voltage is greater than 3volts, we compate it to 0x1D1. If it is higher then 3volts we turn on the MODE LED, if not we turn it off.

To test it out simply jumper together the ADC and 3V3 pins of the IO header. Once connected the MODE LED will light up. Remove the jumper and the LED turns off.

Need help?

Don't fret, just give us a shout in the forum.


C30 source code

#include <p24fxxxx.h>
 
_CONFIG1(    JTAGEN_OFF &     //JTAG port is disabled
            GCP_OFF &         //GSP Memory Code Protection OFF
            GWRP_OFF &        //GCC Flash Write Protection OFF
            COE_OFF &         //
            FWDTEN_OFF &      //Watchdog Timer OFF
            ICS_PGx1)         //debug over PGD1 and PGC1
 
_CONFIG2(    FNOSC_FRCPLL &   //Internal FRC with PLL
            OSCIOFNC_ON &     //RA3 is clk out (fosc/2)
            POSCMOD_NONE &    //Primary oscillator disabled
            I2C1SEL_PRI)      //Use default SCL1/SDA1 pins
 
#define VREG33_DIR TRISAbits.TRISA0
#define VREG33_EN LATAbits.LATA0
#define MODE_LED_DIR TRISAbits.TRISA1
#define MODE_LED LATAbits.LATA1
 
 
#pragma code
 
int main(void)
{
 
    CLKDIVbits.RCDIV0=0;     //clock divider to 0
    AD1PCFG = 0xFFFF;        // Default all pins to digital
    OSCCONbits.SOSCEN=0;     //Disables the secondary oscilator
 
    MODE_LED_DIR = 0;        //sets the Mode LED pin RA1 as output
    MODE_LED = 0;            //turns LED off
    VREG33_DIR =0;           //sets teh VREG pin RA0 as output
    VREG33_EN = 1;           //turns on the voltage regulator
 
    unsigned long int i,voltage;      
//////////////////////////////////////////////////////////////
///////////////ADC config//////////////////////////////////
    AD1PCFGbits.PCFG12=0;          //configure RB12 as analog
    AD1CON1bits.SSRC  = 0b111;     // SSRC<3:0> = 111 implies internal
                                   // counter ends sampling and starts
                                   // converting.
    AD1CON3 = 0x1F02;              // Sample time = 31Tad,
                                   // Tad = 2 Tcy
    AD1CHS =12;                    //ADC channel select 12
    AD1CON1bits.ADON =1;           // turn ADC on
///FOREVER LOOP///////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
    while(1)
    {
        //this just gives us a little delay between measurements
        i =0xFFFFF;                 //sets i to 1048575
        while (i--);                //delay function
 
        //start a measurement with the ADC
        AD1CON1bits.DONE=0;         //resets DONE bit
        AD1CON1bits.SAMP=1;         //start sample
 
        while(AD1CON1bits.DONE==0); //wait for conversion to finish
 
        //get the measurement and use it to control the LED
        voltage = ADC1BUF0;         //get the voltage measurement
        if (voltage > 0x1D1) MODE_LED = 1; //enable LED if measurement is > 3volts
        else MODE_LED = 0;           //disable LED if less than 3volts
   }
}

Compiling and Uploading the firmware

For instructions on how to compile and upload the firmware to your Bus Pirate check out our first demo.