Author Topic: PIC32 ADC help  (Read 7399 times)

0 Members and 1 Guest are viewing this topic.

Offline mapexmbirchTopic starter

  • Contributor
  • Posts: 20
PIC32 ADC help
« on: March 07, 2017, 03:16:29 pm »
Hello

I have a PIC32MZ1024EFG064 and I am trying to get the ADC to work.

When Timer 1 interrupts, the ADC should convert the input. The voltage in is 1.65V, which will be a number over 5, which should light an LED on port F.
However, I am setting a pin high before the ADC status bit.  So the pin should go down after the data is ready to be read.  But it never goes down. 

I can do the same for either conversion bits - GSWTRG or RQCNVRT in ADCCON3. And the pin goes down, meaning there is a clock going to the ADC, which clears the conversion bit.

Here is my code:

Code: [Select]
#include "p32mz1024efg064.h"

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/attribs.h>

#include <stdint.h> /* For uint32_t definition */
#include <stdbool.h> /* For true/false definition */
#include <xc.h>

// PIC32MZ1024EFG064 Configuration Bit Settings

// 'C' source line config statements

// DEVCFG3
// USERID = No Setting
#pragma config FMIIEN = ON             // Ethernet RMII/MII Enable (MII Enabled)
#pragma config FETHIO = ON              // Ethernet I/O Pin Select (Default Ethernet I/O)
#pragma config PGL1WAY = ON            // Permission Group Lock One Way Configuration (Allow only one reconfiguration)
#pragma config PMDL1WAY = ON            // Peripheral Module Disable Configuration (Allow only one reconfiguration)
#pragma config IOL1WAY = ON             // Peripheral Pin Select Configuration (Allow only one reconfiguration)
#pragma config FUSBIDIO = OFF           // USB USBID Selection (Controlled by the USB Module)

// DEVCFG2
#pragma config FPLLIDIV = DIV_1         // System PLL Input Divider (1x Divider)
#pragma config FPLLRNG = RANGE_5_10_MHZ // System PLL Input Range (8-16 MHz Input)
#pragma config FPLLICLK = PLL_FRC      // System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLMULT = MUL_8         // System PLL Multiplier (PLL Multiply by 8)
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (2x Divider)
#pragma config UPLLFSEL = FREQ_12MHZ    // USB PLL Input Frequency Selection (USB PLL input is 12 MHz)

// DEVCFG1
#pragma config FNOSC = SPLL          // Oscillator Selection Bits (Primary Osc (HS,EC))
#pragma config DMTINTV = WIN_127_128    // DMT Count Window Interval (Window/Interval value is 127/128 counter value)
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disable SOSC)
#pragma config IESO = OFF                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = OFF             // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Clock Switch Enabled, FSCM Enabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
#pragma config WDTSPGM = STOP           // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
#pragma config WINDIS = NORMAL          // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled)
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window size is 25%)
#pragma config DMTCNT = DMT31           // Deadman Timer Count Selection (2^31 (2147483648))
#pragma config FDMTEN = OFF             // Deadman Timer Enable (Deadman Timer is disabled)

// DEVCFG0
#pragma config DEBUG = OFF              // Background Debugger Enable (Debugger is disabled)
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx1        // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config TRCEN = ON               // Trace Enable (Trace features in the CPU are enabled)
#pragma config BOOTISA = MIPS32         // Boot ISA Selection (Boot code and Exception code is MIPS32)
#pragma config FECCCON = OFF_UNLOCKED   // Dynamic Flash ECC Configuration (ECC and Dynamic ECC are disabled (ECCCON bits are writable))
#pragma config FSLEEP = OFF             // Flash Sleep Mode (Flash is powered down when the device is in Sleep mode)
#pragma config DBGPER = PG_ALL          // Debug Mode CPU Access Permission (Allow CPU access to all permission regions)
#pragma config SMCLR = MCLR_NORM        // Soft Master Clear Enable bit (MCLR pin generates a normal system Reset)
#pragma config SOSCGAIN = GAIN_2X       // Secondary Oscillator Gain Control bits (2x gain setting)
#pragma config SOSCBOOST = OFF          // Secondary Oscillator Boost Kick Start Enable bit (Normal start of the oscillator)
#pragma config POSCGAIN = GAIN_2X       // Primary Oscillator Gain Control bits (2x gain setting)
#pragma config POSCBOOST = ON           // Primary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config EJTAGBEN = NORMAL        // EJTAG Boot (Normal EJTAG functionality)

// DEVCP0
#pragma config CP = OFF         

unsigned int i = 0;
unsigned int a = 0;

using namespace std;

void __ISR_AT_VECTOR(_TIMER_1_VECTOR, IPL1SOFT) T1Interrupt(void) {
    IFS0bits.T1IF = 0;

    ADCCON3bits.SAMP=0;                     //stop sampling
    ADCCON3bits.GSWTRG = 1;              //trigger conversion
    //ADCCON3bits.RQCNVRT = 1;          //Begin sampling
   
    LATB = 0x2000;
    while(!ADCDSTAT1bits.ARDY2);
    //while(!ADCCON2bits.EOSRDY);       //Wait until complete

    ADCCON3bits.SAMP=1;
    LATB = 0;
   
    a = ADCDATA2;
    if(a>=5) LATF=0x8;
}

int main(void) {
//Osc config
    PB2DIV = 0x8003; //Clock div for UART clock, Div = 4, CLK = 8MHz
    PB3DIV = 0x8000; //Timer clock
   
//Outputs/inputs
    TRISF = 0;
    TRISB = 0x2;  //RB2 ADC input
    CNPUBbits.CNPUB2 = 0;    //Pull up disabled
    ANSELBbits.ANSB2 = 1;    //Analog input

//Interrupts: TM1 (ADC) TM2 (NPC) UART1
    asm("ei");
    INTCONbits.MVEC = 1;
   
    IPC1bits.T1IP = 1;
    IEC0bits.T1IE = 1;
    IFS0bits.T1IF = 1;
   
    IPC2bits.T2IP = 2;
    IEC0bits.T2IE = 1;
    IFS0bits.T2IF = 0;
   
    IEC3bits.U1EIE  = 1;
    IEC3bits.U1RXIE = 1;
    IEC3bits.U1TXIE = 1;
    IPC28bits.U1TXIP = 5;
    IPC28bits.U1RXIP = 4;
    IPC28bits.U1EIP  = 3;
       
//config ADC
    /*
    ADCCON3bits.ADINSEL = 2;    //AN2 selected
    //ADCCON3bits.DIGEN2 = 1;     //(Maybe not needed)
    ADCCON3bits.ADCSEL = 3;     //FRC clock
   
    ADC2TIMEbits.SELRES = 3;    //12bits
    ADC2TIMEbits.ADCDIV = 1;    //2*Tq=TAD2
    ADC2TIMEbits.SAMC = 2;      //4TAD sample time
    ADCANCONbits.ANEN2 = 1;     //Enable ADC2
    ADCTRG1bits.TRGSRC2 = 1;    //Software trigger
    //ADCFSTATbits.ADC2EN = 1;   
    ADCTRGMODEbits.STRGEN2 = 1; //
    ADCCSS1bits.CSS2 = 1;
   
    ADCCON1bits.FSPBCLKEN = 1;  //Use Prephial clock
    ADCCON1bits.FSSCLKEN = 1;   //Use system clock
    ADCCON1bits.STRGSRC = 1;    //Global software trigger
    ADCCON1bits.SELRES = 3;     //12bits
    //ADCCON1bits.TRBMST = 2;   //ADC2 is master (not needed, just incase)
    ADCCON1bits.ON     = 1;
    */
//Timer 1
    T1CON = 0x8040; //Timer on, Prescaler 256
    PR1 = 1562; //(2*256*(1562+1))/32M = 25ms  (32M*T/2*256)-1=PR1

//Timer 2
    PR2 = 1000; //
    T2CON = 0x8040; //Timer on

    while (1) {
   
    }
}


Any help would be greatly appreciated!
 

Offline Lunasix

  • Regular Contributor
  • *
  • Posts: 142
  • Country: fr
Re: PIC32 ADC help
« Reply #1 on: March 07, 2017, 06:51:40 pm »
I think that the following line is needed.
ADCCON3bits.DIGEN2 = 1;
I don't see any other obvious problem, but ADC on PIC32MZ is much more complicated than on PIC32MX.
I use a PIC32MZ for signal processing, and it works fine. I first tried (for debug) to start ADC with software command, and I remember that it didn't worked, don't know why. As I needed fast convert and without jitter, ADCs are now started on timer signal and data are stored trough DMA channels. And it's ok, all automatic !
 

Offline mapexmbirchTopic starter

  • Contributor
  • Posts: 20
Re: PIC32 ADC help
« Reply #2 on: March 07, 2017, 07:18:59 pm »
I'll try triggering it with the Timer 1, instead of the software trigger and see how that goes.  I don't want to use DMA though, so hopefully it will work with TM1 triggering.

Cheers!
 

Offline mapexmbirchTopic starter

  • Contributor
  • Posts: 20
Re: PIC32 ADC help
« Reply #3 on: March 07, 2017, 09:30:12 pm »
I was looking at the PIC32 ADC section 22 datasheet (not the one for the PIC32MZ as a whole).  It gave some example code which uses the software trigger, which I will try out tomorrow.  It's on page 66 and 67.
 

Offline Lunasix

  • Regular Contributor
  • *
  • Posts: 142
  • Country: fr
Re: PIC32 ADC help
« Reply #4 on: March 08, 2017, 02:08:56 pm »
I didn't remember that on another project, I'm using adc with software trigger.

In the init, I don't see what would be missing, except :

ADCCON3bits.CONCLKDIV = 1;
ADCCON3bits.DIGEN2 = 1;

Order of instructions, maybe.


And to trigger conversion, I only use
ADCCON3bits.GSWTRG = 1;

So, with some effort, should work !
 

Offline mapexmbirchTopic starter

  • Contributor
  • Posts: 20
Re: PIC32 ADC help
« Reply #5 on: March 08, 2017, 07:28:45 pm »
Yeah I got it to work with the code in the datasheet.  However, when I put the acquisition code in the timer 1 ISR and use the software trigger.  It doesn't work, it seems to not wake up.

When you use timer 1 as the trigger, where do you wait for the conversion to complete and read the data from the register? From the timer 1 ISR or in the main?

Here is my timer 1 ISR:
Code: [Select]
void __ISR_AT_VECTOR(_TIMER_1_VECTOR, IPL1SOFT) T1Interrupt(void) {
    IFS0bits.T1IF = 0;
   
    ADCCON3bits.GSWTRG = 1;           //Start conversion
    while (ADCDSTAT1bits.ARDY2 == 0);   //Wait
    a = ADCDATA2;                        //Read data
    if(a>=5)LATF=0x8;         //Light the LED if ADC value greater that 5
}


This code works fine:
Code: [Select]
#include "p32mz1024efg064.h"

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/attribs.h>

#include <stdint.h> /* For uint32_t definition */
#include <stdbool.h> /* For true/false definition */
#include <xc.h>

// PIC32MZ1024EFG064 Configuration Bit Settings

// 'C' source line config statements

// DEVCFG3
// USERID = No Setting
#pragma config FMIIEN = ON             // Ethernet RMII/MII Enable (MII Enabled)
#pragma config FETHIO = ON              // Ethernet I/O Pin Select (Default Ethernet I/O)
#pragma config PGL1WAY = ON            // Permission Group Lock One Way Configuration (Allow only one reconfiguration)
#pragma config PMDL1WAY = ON            // Peripheral Module Disable Configuration (Allow only one reconfiguration)
#pragma config IOL1WAY = ON             // Peripheral Pin Select Configuration (Allow only one reconfiguration)
#pragma config FUSBIDIO = OFF           // USB USBID Selection (Controlled by the USB Module)

// DEVCFG2
#pragma config FPLLIDIV = DIV_1         // System PLL Input Divider (1x Divider)
#pragma config FPLLRNG = RANGE_5_10_MHZ // System PLL Input Range (8-16 MHz Input)
#pragma config FPLLICLK = PLL_FRC      // System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLMULT = MUL_8         // System PLL Multiplier (PLL Multiply by 8)
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (2x Divider)
#pragma config UPLLFSEL = FREQ_12MHZ    // USB PLL Input Frequency Selection (USB PLL input is 12 MHz)

// DEVCFG1
#pragma config FNOSC = SPLL          // Oscillator Selection Bits (Primary Osc (HS,EC))
#pragma config DMTINTV = WIN_127_128    // DMT Count Window Interval (Window/Interval value is 127/128 counter value)
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disable SOSC)
#pragma config IESO = OFF                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = OFF             // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Clock Switch Enabled, FSCM Enabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
#pragma config WDTSPGM = STOP           // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
#pragma config WINDIS = NORMAL          // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled)
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window size is 25%)
#pragma config DMTCNT = DMT31           // Deadman Timer Count Selection (2^31 (2147483648))
#pragma config FDMTEN = OFF             // Deadman Timer Enable (Deadman Timer is disabled)

// DEVCFG0
#pragma config DEBUG = OFF              // Background Debugger Enable (Debugger is disabled)
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx1        // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config TRCEN = ON               // Trace Enable (Trace features in the CPU are enabled)
#pragma config BOOTISA = MIPS32         // Boot ISA Selection (Boot code and Exception code is MIPS32)
#pragma config FECCCON = OFF_UNLOCKED   // Dynamic Flash ECC Configuration (ECC and Dynamic ECC are disabled (ECCCON bits are writable))
#pragma config FSLEEP = OFF             // Flash Sleep Mode (Flash is powered down when the device is in Sleep mode)
#pragma config DBGPER = PG_ALL          // Debug Mode CPU Access Permission (Allow CPU access to all permission regions)
#pragma config SMCLR = MCLR_NORM        // Soft Master Clear Enable bit (MCLR pin generates a normal system Reset)
#pragma config SOSCGAIN = GAIN_2X       // Secondary Oscillator Gain Control bits (2x gain setting)
#pragma config SOSCBOOST = OFF          // Secondary Oscillator Boost Kick Start Enable bit (Normal start of the oscillator)
#pragma config POSCGAIN = GAIN_2X       // Primary Oscillator Gain Control bits (2x gain setting)
#pragma config POSCBOOST = ON           // Primary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config EJTAGBEN = NORMAL        // EJTAG Boot (Normal EJTAG functionality)

// DEVCP0
#pragma config CP = OFF         

unsigned int i = 0;
unsigned int a = 0;

using namespace std;
int main(void) {
    TRISF = 0;
    TRISB = 0x104;  //RB2 ADC input
    //CNPUBbits.CNPUB2 = 0;
    ANSELBbits.ANSB2 = 1;
    ANSELBbits.ANSB8 = 1;
   
    PB2DIV = 0x8003; //Clock div for UART clock, Div = 4, CLK = 8MHz
    PB3DIV = 0x8000; //Timer clock
/* Configure ADCCON1 */
    ADCCON1 = 0; // No ADCCON1 features are enabled including: Stop-in-Idle, turbo,
// CVD mode, Fractional mode and scan trigger source.
/* Configure ADCCON2 */
    ADCCON2 = 0; // Since, we are using only the Class 1 inputs, no setting is
// required for ADCDIV
/* Initialize warm up time register */
    ADCANCON = 0;
    ADCANCONbits.WKUPCLKCNT = 5; // Wakeup exponent = 32 * TADx
/* Clock setting */
    ADCCON3 = 0;
    ADCCON3bits.ADCSEL = 3; // Select input clock source
    ADCCON3bits.CONCLKDIV = 1; // Control clock frequency is half of input clock
    ADCCON3bits.VREFSEL = 0; // Select AVdd and AVss as reference source
/* Select ADC sample time and conversion clock */
    ADC2TIMEbits.ADCDIV = 1; // ADC2 clock frequency is half of control clock = TAD2
    ADC2TIMEbits.SAMC = 10; // ADC2 sampling time = 5 * TAD2
    ADC2TIMEbits.SELRES = 3; // ADC2 resolution is 12 bits
/* Select analog input for ADC modules, no presync trigger, not sync sampling */
    ADCTRGMODEbits.SH2ALT = 0; // ADC2 = AN2
/* Select ADC input mode */
    ADCIMCON1bits.SIGN2 = 0; // unsigned data format
    ADCIMCON1bits.DIFF2 = 0; // Single ended mode
/* Configure ADCGIRQENx */
    ADCGIRQEN1 = 0; // No interrupts are used
    ADCGIRQEN2 = 0;
/* Configure ADCCSSx */
    ADCCSS1 = 0; // No scanning is used
    ADCCSS2 = 0;

/* Set up the trigger sources */
    ADCTRGSNSbits.LVL2 = 0; // Edge trigger

    ADCTRG1bits.TRGSRC2 = 1; // Set AN2 to trigger from software.
/* Early interrupt */
    ADCEIEN1 = 0; // No early interrupt
    ADCEIEN2 = 0;
/* Turn the ADC on */
    ADCCON1bits.ON = 1;
   
/* Wait for voltage reference to be stable */
    while(!ADCCON2bits.BGVRRDY); // Wait until the reference voltage is ready
    while(ADCCON2bits.REFFLT); // Wait if there is a fault with the reference voltage
/* Enable clock to analog circuit */

    ADCANCONbits.ANEN2 = 1; // Enable the clock to analog bias
/* Wait for ADC to be ready */

    while(!ADCANCONbits.WKRDY2); // Wait until ADC2 is ready
/* Enable the ADC module */
    ADCCON3bits.DIGEN2 = 1; // Enable ADC2
    while (1) {
    /* Trigger a conversion */
        ADCCON3bits.GSWTRG = 1;
        while (ADCDSTAT1bits.ARDY2 == 0);
    /* fetch the result */
        a = ADCDATA2;
        if(a>=5)LATF=0x8;
    }   
}

All the setup was copied, the only change is using the timer instead of continuously reading the ADC.

Cheers
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf