PIC32 ADC help - Page 1
Forum section: electronics / general

author: mapexmbirch
author_rank: Contributor
timestamp: March 07, 2017, 03:16:29 pm
content: HelloI 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:#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 = OFFunsigned 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 samplingADCCON3bits.GSWTRG = 1; //trigger conversion//ADCCON3bits.RQCNVRT = 1; //Begin samplingLATB = 0x2000;while(!ADCDSTAT1bits.ARDY2);//while(!ADCCON2bits.EOSRDY); //Wait until completeADCCON3bits.SAMP=1;LATB = 0;a = ADCDATA2;if(a>=5) LATF=0x8;}int main(void) {//Osc configPB2DIV = 0x8003; //Clock div for UART clock, Div = 4, CLK = 8MHzPB3DIV = 0x8000; //Timer clock//Outputs/inputsTRISF = 0;TRISB = 0x2; //RB2 ADC inputCNPUBbits.CNPUB2 = 0; //Pull up disabledANSELBbits.ANSB2 = 1; //Analog input//Interrupts: TM1 (ADC) TM2 (NPC) UART1asm("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 clockADC2TIMEbits.SELRES = 3; //12bitsADC2TIMEbits.ADCDIV = 1; //2*Tq=TAD2ADC2TIMEbits.SAMC = 2; //4TAD sample timeADCANCONbits.ANEN2 = 1; //Enable ADC2ADCTRG1bits.TRGSRC2 = 1; //Software trigger//ADCFSTATbits.ADC2EN = 1;ADCTRGMODEbits.STRGEN2 = 1; //ADCCSS1bits.CSS2 = 1;ADCCON1bits.FSPBCLKEN = 1; //Use Prephial clockADCCON1bits.FSSCLKEN = 1; //Use system clockADCCON1bits.STRGSRC = 1; //Global software triggerADCCON1bits.SELRES = 3; //12bits//ADCCON1bits.TRBMST = 2; //ADC2 is master (not needed, just incase)ADCCON1bits.ON = 1;*///Timer 1T1CON = 0x8040;//Timer on, Prescaler 256PR1 =1562;//(2*256*(1562+1))/32M = 25ms (32M*T/2*256)-1=PR1//Timer 2PR2 = 1000; //T2CON = 0x8040; //Timer onwhile (1) {}}Any help would be greatly appreciated!

author: Lunasix
author_rank: Regular Contributor
timestamp: March 07, 2017, 06:51:40 pm
content: 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 !

author: mapexmbirch
author_rank: Contributor
timestamp: March 07, 2017, 07:18:59 pm
content: 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!

author: mapexmbirch
author_rank: Contributor
timestamp: March 07, 2017, 09:30:12 pm
content: 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.

author: Lunasix
author_rank: Regular Contributor
timestamp: March 08, 2017, 02:08:56 pm
content: 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 useADCCON3bits.GSWTRG = 1;So, with some effort, should work !

author: mapexmbirch
author_rank: Contributor
timestamp: March 08, 2017, 07:28:45 pm
content: 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:void __ISR_AT_VECTOR(_TIMER_1_VECTOR, IPL1SOFT) T1Interrupt(void) {IFS0bits.T1IF = 0;ADCCON3bits.GSWTRG = 1; //Start conversionwhile (ADCDSTAT1bits.ARDY2 == 0); //Waita = ADCDATA2; //Read dataif(a>=5)LATF=0x8; //Light the LED if ADC value greater that 5}This code works fine:Code:#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 = OFFunsigned 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 = 8MHzPB3DIV = 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 sourceADCCON3bits.CONCLKDIV = 1; // Control clock frequency is half of input clockADCCON3bits.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 = TAD2ADC2TIMEbits.SAMC = 10; // ADC2 sampling time = 5 * TAD2ADC2TIMEbits.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 formatADCIMCON1bits.DIFF2 = 0; // Single ended mode/* Configure ADCGIRQENx */ADCGIRQEN1 = 0; // No interrupts are usedADCGIRQEN2 = 0;/* Configure ADCCSSx */ADCCSS1 = 0; // No scanning is usedADCCSS2 = 0;/* Set up the trigger sources */ADCTRGSNSbits.LVL2 = 0; // Edge triggerADCTRG1bits.TRGSRC2 = 1; // Set AN2 to trigger from software./* Early interrupt */ADCEIEN1 = 0; // No early interruptADCEIEN2 = 0;/* Turn the ADC on */ADCCON1bits.ON = 1;/* Wait for voltage reference to be stable */while(!ADCCON2bits.BGVRRDY); // Wait until the reference voltage is readywhile(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 ADC2while (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