• AVR Freaks

Hot!PIC32MZ - Looking for a ADCHS with DMA example

Author
bazmrl
Starting Member
  • Total Posts : 33
  • Reward points : 0
  • Joined: 2008/09/01 08:06:00
  • Location: 0
  • Status: offline
2018/12/15 10:38:27 (permalink)
0

PIC32MZ - Looking for a ADCHS with DMA example

I am trying to work out how to capture analogue using DMA and getting lost.
 
Does anyone have a worked example of how to do it using  PIC32MZ2048EFM064?
 
Thanks
 
#1

3 Replies Related Threads

    Howard Long
    Super Member
    • Total Posts : 681
    • Reward points : 0
    • Joined: 2005/04/04 08:50:32
    • Status: offline
    Re: PIC32MZ - Looking for a ADCHS with DMA example 2018/12/15 14:05:54 (permalink)
    0
    Here is some old code of mine from over a couple of years ago for the PIC32MZEF SK. I've checked that it builds and runs.
     
    It reads AN3 (RB3), and is conversions are triggered by by TMR3/OC3.
     
    It implements a ping pong buffer, 2 x 512 words.
     
    It outputs the 16 bit (padded) data in the main superloop via SPI at 25Mbps (RD1 SCLK & RF5 SDO) as well as the lower eight bits via RS232 at 25Mbps (pin RF2).
     
    Please note that this was a work in progress so you'll have to excuse the raw nature of it. You'll see that there is some other initialisation going on for OC1 and OC5 for example. Somewhere I have a more recent version, if I find it I'll post it.
     
    The specific pins are chosen to match the J12 connections on the starter kit. At the time I had an LA semi permanently hooked up to several pins on the board, hence the LAT_D01-LAT_D15 defines, which are _not_ LATD!!!!
     

    // Include dir: c:/microchip/harmony/v1_08_01/framework/
    // Lib: C:\microchip\harmony\v1_08_01\bin\framework\peripheral\PIC32MZ1024EFM144_peripherals.a
    // DEVCFG0
    #pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
    #pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
    /*** DEVCFG1 ***/
    #pragma config FNOSC =      0 //FRCDIV, note that setting this to 7 instead of 0 causes a clock failure, and COSC set to BFRC
    #pragma config IESO =       OFF
    #pragma config POSCMOD =    OFF
    #pragma config OSCIOFNC =   ON
    #pragma config FCKSM =      CSECMD
    #pragma config FWDTEN =     OFF
    #pragma config FDMTEN =     OFF
    #define PLIB_DISABLE_OPTIMIZATION_WARNING
    #include "peripheral/peripheral.h"
    #include <xc.h>
    #include <sys/attribs.h> // Interrupt macros
    #include <stdint.h>
    #include <stdbool.h>
    #define TRIS_LED0 TRISHbits.TRISH0
    #define TRIS_LED1 TRISHbits.TRISH1
    #define TRIS_LED2 TRISHbits.TRISH2
    #define TRIS_SW1 TRISBbits.TRISB12
    #define TRIS_SW2 TRISBbits.TRISB13
    #define TRIS_SW3 TRISBbits.TRISB14
    #define TRIS_D00 TRISAbits.TRISA3
    #define TRIS_D01 TRISAbits.TRISA2
    #define TRIS_D02 TRISAbits.TRISA14
    #define TRIS_D03 TRISGbits.TRISG6
    #define TRIS_D04 TRISDbits.TRISD0
    #define TRIS_D05 TRISFbits.TRISF2
    #define TRIS_D06 TRISJbits.TRISJ13
    #define TRIS_D07 TRISKbits.TRISK1
    #define TRIS_D08 TRISKbits.TRISK2
    #define TRIS_D09 TRISFbits.TRISF5
    #define TRIS_D10 TRISFbits.TRISF4
    #define TRIS_D11 TRISKbits.TRISK3
    #define TRIS_D12 TRISDbits.TRISD1
    #define TRIS_D13 TRISJbits.TRISJ5
    #define TRIS_D14 TRISJbits.TRISJ7
    #define TRIS_D15 TRISDbits.TRISD10
    #define LAT_LED0 LATHbits.LATH0
    #define LAT_LED1 LATHbits.LATH1
    #define LAT_LED2 LATHbits.LATH2
    #define LATINV_LED0() {LATHINV=0x0001;}
    #define LATINV_LED1() {LATHINV=0x0002;}
    #define LATINV_LED2() {LATHINV=0x0004;}
    #define LATSET_LED0() {LATHSET=0x0001;}
    #define LATSET_LED1() {LATHSET=0x0002;}
    #define LATSET_LED2() {LATHSET=0x0004;}
    #define LATCLR_LED0() {LATHCLR=0x0001;}
    #define LATCLR_LED1() {LATHCLR=0x0002;}
    #define LATCLR_LED2() {LATHCLR=0x0004;}
    #define PORT_SW1 PORTBbits.RB12
    #define PORT_SW2 PORTBbits.RB13
    #define PORT_SW3 PORTBbits.RB14
    #define LAT_D00 LATAbits.LATA3
    #define LAT_D01 LATAbits.LATA2
    #define LAT_D02 LATAbits.LATA14
    #define LAT_D03 LATGbits.LATG6
    #define LAT_D04 LATDbits.LATD0
    #define LAT_D05 LATFbits.LATF2
    #define LAT_D06 LATJbits.LATJ13
    #define LAT_D07 LATKbits.LATK1
    #define LAT_D08 LATKbits.LATK2
    #define LAT_D09 LATFbits.LATF5
    #define LAT_D10 LATFbits.LATF4
    #define LAT_D11 LATKbits.LATK3
    #define LAT_D12 LATDbits.LATD1
    #define LAT_D13 LATJbits.LATJ5
    #define LAT_D14 LATJbits.LATJ7
    #define LAT_D15 LATDbits.LATD10
    #define PORT_D00 PORTAbits.RA3
    #define PORT_D01 PORTAbits.RA2
    #define PORT_D02 PORTAbits.RA14
    #define PORT_D03 PORTGbits.RG6
    #define PORT_D04 PORTDbits.RD0
    #define PORT_D05 PORTFbits.RF2
    #define PORT_D06 PORTJbits.RJ13
    #define PORT_D07 PORTKbits.RK1
    #define PORT_D08 PORTKbits.RK2
    #define PORT_D09 PORTFbits.RF5
    #define PORT_D10 PORTFbits.RF4
    #define PORT_D11 PORTKbits.RK3
    #define PORT_D12 PORTDbits.RD1
    #define PORT_D13 PORTJbits.RJ5
    #define PORT_D14 PORTJbits.RJ7
    #define PORT_D15 PORTDbits.RD10
    #define NUM_SAMPLES 1024
    #define NUM_ADCS 1
    static volatile uint16_t __attribute__((coherent,aligned(16))) _aau16[NUM_ADCS][NUM_SAMPLES];
    static volatile uint16_t __attribute__((coherent,aligned(16))) _aau16Out[NUM_SAMPLES][NUM_ADCS];
    static volatile bool _bPingPong=false;
    static volatile bool _bReady=false;
    static volatile int _aanTimer[NUM_ADCS][16];
    static volatile int _anLast[NUM_ADCS];
    static volatile int _anCount[NUM_ADCS];
    // declared static in case exception condition would prevent
    // auto variable being created
    static enum {
     EXCEP_IRQ = 0,   // interrupt
     EXCEP_AdEL = 4,   // address error exception (load or ifetch)
     EXCEP_AdES,    // address error exception (store)
     EXCEP_IBE,    // bus error (ifetch)
     EXCEP_DBE,    // bus error (load/store)
     EXCEP_Sys,    // syscall
     EXCEP_Bp,    // breakpoint
     EXCEP_RI,    // reserved instruction
     EXCEP_CpU,    // coprocessor unusable
     EXCEP_Overflow,   // arithmetic overflow
     EXCEP_Trap,    // trap (possible divide by zero)
     EXCEP_IS1 = 16,   // implementation specfic 1
     EXCEP_CEU,    // CorExtend Unuseable
     EXCEP_C2E    // coprocessor 2
    } _excep_code;
    static unsigned int _epc_code;
    static unsigned int _excep_addr;
    void _nmi_handler (void)
    {
     asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
     asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
     _excep_code = (_excep_code & 0x0000007C) >> 2;
     while (1)
        {
            Nop();
        }
    }
    void _simple_tlb_refill_exception_handler(void)
    {
     asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
     asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
     _excep_code = (_excep_code & 0x0000007C) >> 2;
     while (1)
        {
            Nop();
        }
    }
    void _cache_err_exception_handler(void)
    {
     asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
     asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
     _excep_code = (_excep_code & 0x0000007C) >> 2;
     while (1)
        {
            Nop();
        }
    }
    void _general_exception_handler(void)
    {
     asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
     asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
     _excep_code = (_excep_code & 0x0000007C) >> 2;
     while (1)
        {
            Nop();
        }
    }

    void __ISR(_TIMER_4_VECTOR,IPL5AUTO) __Timer4Interrupt(void)
    {
        static int i=0;
       
        IFS0CLR=_IFS0_T4IF_MASK; 
        i++;
       
        if (i>=10000)
        {
            i=0;
            LATINV_LED0();
        }
    }
    void __ISR(_DMA3_VECTOR,IPL5AUTO) __DMA3Interrupt(void)
    {
        IFS4CLR=_IFS4_DMA3IF_MASK;
        if (DCH3INTbits.CHDDIF)
        {
            int n=_CP0_GET_COUNT();
            int nIdx=_anCount[3] & 0x000F;
            int nLast=_anLast[3];
           
            _aanTimer[3][nIdx]=n-nLast;
            _anLast[3]=n;
            _anCount[3]++;
            Nop();
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_3,DMA_INT_DESTINATION_DONE); // Atomic version
           
            _bReady=true;
            _bPingPong=false;
        }
        if (DCH3INTbits.CHDHIF)
        {
            Nop();
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_3,DMA_INT_DESTINATION_HALF_FULL); // Atomic version
            _bReady=true;
            _bPingPong=true;
        }
    }
    static void CPUInit(void)
    {
        // Note that cache is already configured by startup code
        // C:\Program Files\Microchip\xc32\v1.42\pic32-libs\libpic32\stubs\pic32_init_cache.S
       
        // Set up wait states
        PLIB_PCACHE_WaitStateSet(PCACHE_ID_0, 2); // Adjust as appropriate for memory and clock
       
        // Set up prefetch
        if (PLIB_PCACHE_ExistsPrefetchEnable(PCACHE_ID_0))
        {
            PLIB_PCACHE_PrefetchEnableSet(PCACHE_ID_0, PLIB_PCACHE_PREFETCH_ENABLE_ALL);
        }
       
        // Set up interrupt controller
        PLIB_INT_MultiVectorSelect(INT_ID_0);
        PLIB_INT_Enable(INT_ID_0);
    }
    static void OSCInit(void)
    {
        // Switch to 200MHz PLL sourced from 24MHz EC POSC
        PLIB_DEVCON_SystemUnlock ( DEVCON_ID_0 );
    //    PLIB_OSC_SysPLLInputDivisorSet(OSC_ID_0, OSC_SYSPLL_IN_DIV_3); // Generate 8MHz from 24MHz POSC
        PLIB_OSC_SysPLLInputDivisorSet(OSC_ID_0, OSC_SYSPLL_IN_DIV_1); // Generate 8MHz from FRC
        PLIB_OSC_SysPLLFrequencyRangeSet(OSC_ID_0, OSC_SYSPLL_FREQ_RANGE_5M_TO_10M);   
    //    PLIB_OSC_SysPLLInputClockSourceSet(OSC_ID_0, OSC_SYSPLL_IN_CLK_SOURCE_PRIMARY);
        PLIB_OSC_SysPLLInputClockSourceSet(OSC_ID_0, OSC_SYSPLL_IN_CLK_SOURCE_FRC);
        PLIB_OSC_SysPLLMultiplierSelect(OSC_ID_0, 50);
        PLIB_OSC_SysPLLOutputDivisorSet(OSC_ID_0, OSC_SYSPLL_OUT_DIV_2);
    //    PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_PRIMARY_WITH_PLL);
        PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_FRC_WITH_PLL);
        while (!PLIB_OSC_ClockSwitchingIsComplete(OSC_ID_0))
        {
            Nop();
        }
        PLIB_DEVCON_SystemLock ( DEVCON_ID_0 );
    }
    static void ADCClass1_2DMA(void)
    {
        // General DMA configuration
        DMACON=0;
        DMACONbits.ON=1;
      
        // General ADC configuration
        /* initialize ADC calibration setting */
        ADC0CFG = DEVADC0;
        ADC1CFG = DEVADC1;
        ADC2CFG = DEVADC2;
        ADC3CFG = DEVADC3;
        ADC4CFG = DEVADC4;
        ADC7CFG = DEVADC7;
        ADCCON1 = 0; // No ADCCON1 features are enabled including: Stop-in-Idle, turbo,
                    // CVD mode, Fractional mode and scan trigger source.
        ADCCON2 = 0; // Since, we are using only the Class 1 inputs, no setting is
                    // required for ADCDIV
        ADCCON3 = 0;
        ADCCSS1 = 0; // No scanning is used
        ADCCSS2 = 0;
       
        ADCTRGMODE=0;
        ADCGIRQEN1 = 0;
        ADCGIRQEN2 = 0;
       
        ADCCMPCON1 = 0; // No digital comparators are used. Setting the ADCCMPCONx
        ADCCMPCON2 = 0; // register to '0' ensures that the comparator is disabled.
        ADCCMPCON3 = 0; // Other registers are ?don't care?.
        ADCCMPCON4 = 0;
        ADCCMPCON5 = 0;
        ADCCMPCON6 = 0;
       
        ADCFLTR1 = 0; // No oversampling filters are used.
        ADCFLTR2 = 0;
        ADCFLTR3 = 0;
        ADCFLTR4 = 0;
        ADCFLTR5 = 0;
        ADCFLTR6 = 0;
        /* Configure ADCCON1 */
        ADCCON1bits.FRACT = 0; // use Integer output format //**2
        ADCCON1bits.SELRES = 3; // ADC7 resolution is 12 bits //**2
        ADCCON1bits.STRGSRC = 0; // No scan trigger. //**2
       
        // DS60001320D-page 427 - Notes 1 & 2 in textbox
        ADCCON1bits.AICPMPEN=0; // 0 -> Vdd>=2.5v (Analog Input Charge Pump off)
        CFGCONbits.IOANCPEN=0; // 0 -> Vdd>=2.5v (I/O analogue charge pump off)
       
        // DS60001344B-page 22-77
    //    ADCCON1bits.FSSCLKEN=1;
    //    ADCCON1bits.FSPBCLKEN=1;
       
        /* Configure ADCCON2 */
    //    ADCCON2bits.SAMC = 5; // ADC7 sampling time = 5 * TAD7 //**2
        ADCCON2bits.SAMC = 3; // ADC7 sampling time = 5 * TAD7 [Tsamp=Tad*(SAMC+2)] //**2
    //    ADCCON2bits.ADCDIV = 1; // ADC7 clock freq is half of control clock = TAD7 [Tad7=Tq/2 (20ns/50MHz)] //**2
        ADCCON2bits.ADCDIV = 2; // ADC7 clock freq is half of control clock = TAD7 [Tad7=Tq/4 (20ns/50MHz)] //**2
       
        /* Initialize warm up time register */
        ADCANCON = 0;
        ADCANCONbits.WKUPCLKCNT = 5; // Wakeup exponent = 32 * TADx
       
        /* Clock setting */
    //    ADCCON3bits.ADCSEL = 0b00; // Select input clock source 0b00 -> Tclk=PBCLK3 (10ns/100MHz)
        ADCCON3bits.ADCSEL = 0b01; // Select input clock source, 0b01 -> Tclk=Tcy (5ns/200MHz)
    //    ADCCON3bits.CONCLKDIV = 1; // Control clock frequency is half of input clock 1 -> Tq=2*Tclk (10ns/100MHz)
        ADCCON3bits.CONCLKDIV = 0; // Control clock frequency is input clock 1 -> Tq=Tclk (5ns/200MHz)
        ADCCON3bits.VREFSEL = 0; // Select AVDD and AVSS as reference source
    // Channel specific configuration   
        ANSELBbits.ANSB3=1; // AN3
    // DMA channel specific config   
        DCH3CONbits.CHPRI=3; // 3 -> highest priority
        DCH3CONbits.CHAEN=1; // 1 -> Continuously enabled, auto restart after block completed
        DCH3ECON=0;
        DCH3ECONbits.CHSIRQ=_ADC_DATA3_VECTOR;
        DCH3ECONbits.SIRQEN=1; // 1 ->  Start channel cell transfer if an interrupt matching CHSIRQ occurs
        DCH3SSA=KVA_TO_PA(&ADCDATA3);
        DCH3DSA=KVA_TO_PA(&_aau16[3][0]);
        DCH3SSIZ=sizeof(_aau16[3][0]); // All sizes are in bytes
        DCH3DSIZ=sizeof(_aau16[3]);
        DCH3CSIZ=sizeof(_aau16[3][0]);
        DCH3INT=0;
        DCH3INTbits.CHDDIF=0; // Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ)
        DCH3INTbits.CHDDIE=1;
        DCH3INTbits.CHDHIF=0; // Channel Destination Pointer has reached midpoint of destination (CHDPTR = CHDSIZ/2)
        DCH3INTbits.CHDHIE=0;
        IPC34bits.DMA3IP=1;
        IPC34bits.DMA3IS=0;
        IFS4bits.DMA3IF=0;
        IEC4bits.DMA3IE=1;
        DCH3CONbits.CHEN=1;
       
    // ADC channel specific config   
    //    ADC3TIMEbits.ADCDIV = 1; // ADC3 clock frequency is half of control clock = TAD3 [Tad=Tq/2 (20ns/50MHz)]
        ADC3TIMEbits.ADCDIV = 2; // ADC3 clock frequency is half of control clock = TAD0 [Tad=Tq/4 (20ns/50MHz)]
        ADC3TIMEbits.SAMC = 3; // ADC3 sampling time = 5 * TAD3 [Tsamp=Tad*(SAMC+2)]
        ADC3TIMEbits.SELRES = 3; // ADC3 resolution is 12 bits
       
        /* Select analog input for ADC modules, no presync trigger, not sync sampling */
        ADCTRGMODEbits.SH3ALT = 0; // ADC3 = AN3
       
    //    ADCTRGMODEbits.SSAMPEN3=1; // 1 -> synchronous sampling for the first sample after being idle or disabled
       
        /* Select ADC input mode */
        ADCIMCON1bits.SIGN3 = 0; // unsigned data format
        ADCIMCON1bits.DIFF3 = 0; // Single ended mode
       
        /* Configure ADCGIRQENx */
        ADCGIRQEN1bits.AGIEN3=1;
       
        /* Set up the trigger sources */
        ADCTRGSNSbits.LVL3 = 0; // Edge trigger
       
    //    ADCTRG1bits.TRGSRC3 = 1; // Set AN3 to trigger from software.
    //    ADCTRG1bits.TRGSRC3 = 0b01000; // 0b01000 -> OCMP1
        ADCTRG1bits.TRGSRC3 = 0b01001; // 0b01001 -> OCMP3
    //    ADCTRG1bits.TRGSRC3 = 0b01010; // 0b01010 -> OCMP5
       
     
        /* 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.ANEN0 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN1 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN2 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN3 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN4 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN7 = 1; // Enable the clock to analog bias //**2
       
        /* Wait for ADC to be ready */
        while(!ADCANCONbits.WKRDY0); // Wait until ADC0 is ready
        while(!ADCANCONbits.WKRDY1); // Wait until ADC1 is ready
        while(!ADCANCONbits.WKRDY2); // Wait until ADC2 is ready
        while(!ADCANCONbits.WKRDY3); // Wait until ADC3 is ready
        while(!ADCANCONbits.WKRDY4); // Wait until ADC4 is ready
        while(!ADCANCONbits.WKRDY7); // Wait until ADC7 is ready //**2
       
        /* Enable the ADC module */
        ADCCON3bits.DIGEN0 = 1; // Enable ADC0
        ADCCON3bits.DIGEN1 = 1; // Enable ADC1
        ADCCON3bits.DIGEN2 = 1; // Enable ADC2
        ADCCON3bits.DIGEN3 = 1; // Enable ADC3
        ADCCON3bits.DIGEN4 = 1; // Enable ADC4
        ADCCON3bits.DIGEN7 = 1; // Enable ADC7 //**2
       
        // Set up timer 3
        TMR3=0;
        PR3=18*2-1;
    //    PR3=180-1;
        IPC3bits.T3IP=1;
        IPC3bits.T3IS=0;
        IFS0bits.T3IF=0;
        IEC0bits.T3IE=0;
        // Set up OC1
        OC1R=1;
        OC1RS=6;
        OC1CONbits.OCM=0b101; // 0b101=continuous pulses
        OC1CONbits.OCTSEL=1; // 1=TMR3
        RPD0Rbits.RPD0R=0b1100; // 0b1100=OC1
        OC1CONbits.ON=1;
       
        // Set up OC3
        OC3R=13;
        OC3RS=18;
    //    OC3R=61;
    //    OC3RS=66;
        OC3CONbits.OCM=0b101; // 0b101=continuous pulses
        OC3CONbits.OCTSEL=1; // 1=TMR3
    //    RPD10Rbits.RPD10R=0b1011; // 0b1011=OC3
        RPA14Rbits.RPA14R=0b1011; // 0b1011=OC3
        OC3CONbits.ON=1;
       
        // Set up OC5
        OC5R=25;
        OC5RS=30;
    //    OC5R=121;
    //    OC5RS=126;
        OC5CONbits.OCM=0b101; // 0b101=continuous pulses
        OC5CONbits.OCTSEL=1; // 1=TMR3
        RPG6Rbits.RPG6R=0b1011; // 0b1011=OC5
    //    RPD9Rbits.RPD9R=0b1011; // 0b1011=OC5
        OC5CONbits.ON=1;
        T3CONbits.ON=1;
    }
    void main(void)
    {
        CPUInit();
        OSCInit();
       
        // All digital GPIO except AN3 (RPB3) & AN9 (RPB14))
        ANSELA=0;
        ANSELB=0x4008;
        ANSELC=0;
        ANSELD=0;
        ANSELE=0;
        ANSELF=0;
        ANSELG=0;
        ANSELH=0;
       
        LATA=0;
        LATB=0;
        LATC=0;
        LATD=0;
        LATE=0;
        LATF=0;
        LATG=0;
        LATH=0;
        LATJ=0;
        TRISA=0;
        TRISB=0x4008;
        TRISC=0;
        TRISD=0;
        TRISE=0;
        TRISF=0;
        TRISG=0;
        TRISH=0;
        TRISJ=0;
       
        TRIS_SW1=1;
        TRIS_SW2=1;
        TRIS_SW3=1;
       
        RPF2Rbits.RPF2R=0b0010; // 0b0010->U2TX
        U2MODEbits.BRGH=1;
        U2STAbits.UTXEN=1;
        U2BRG=0;
        U2MODEbits.ON=1;
       
        RPF5Rbits.RPF5R=0b0101; // 0b0101->SDO1
        SPI1CONbits.MODE16=1;
        SPI1CONbits.MSTEN=1;
        SPI1CONbits.DISSDI=1;
        SPI1BRG=1;
        SPI1CONbits.ON=1;
       
        ADCClass1_2DMA();
        while (1)
        {
            if (_bReady)
            {
                volatile uint16_t *pu16=&_aau16[3][_bPingPong*(NUM_SAMPLES/2)];
                int i;
               
                _bReady=false;
               
                LAT_D14=1;
                for (i=0;i<NUM_SAMPLES/2;i++)
                {
    //                LAT_D13=1;
                    while (!SPI1STATbits.SPITBE)
                    {
                        Nop();
                    }
                    SPI1BUF;
                    SPI1BUF=*pu16;
                    while (!U2STAbits.TRMT)
                    {
                        Nop();
                    }
                    U2TXREG=*pu16++;
    //                LAT_D13=0;
                }
                LAT_D14=0;
            }
            Nop();
        }
    }

    #2
    Howard Long
    Super Member
    • Total Posts : 681
    • Reward points : 0
    • Joined: 2005/04/04 08:50:32
    • Status: offline
    Re: PIC32MZ - Looking for a ADCHS with DMA example 2018/12/15 14:40:23 (permalink)
    0
    Here's a version that seems to implement interleaved ping pong, combining six channels into two at three times the speed. It outputs the result on the EBI.
     

    // Include dir: c:/microchip/harmony/v1_08_01/framework/
    // Lib: C:\microchip\harmony\v1_08_01\bin\framework\peripheral\PIC32MZ1024EFM144_peripherals.a
    // DEVCFG0
    #pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
    #pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
    /*** DEVCFG1 ***/
    #pragma config FNOSC =      0 //FRCDIV, note that setting this to 7 instead of 0 causes a clock failure, and COSC set to BFRC
    #pragma config IESO =       OFF
    #pragma config POSCMOD =    OFF
    #pragma config OSCIOFNC =   ON
    #pragma config FCKSM =      CSECMD
    #pragma config FWDTEN =     OFF
    #pragma config FDMTEN =     OFF
    #define PLIB_DISABLE_OPTIMIZATION_WARNING
    #include "peripheral/peripheral.h"
    #include <xc.h>
    #include <sys/attribs.h> // Interrupt macros
    #include <stdint.h>
    #include <stdbool.h>
    #define NUM_SAMPLES 1024
    #define NUM_ADCS 6
    static volatile uint16_t __attribute__((coherent,aligned(16))) _aau16[NUM_ADCS][NUM_SAMPLES];
    static volatile uint16_t __attribute__((coherent,aligned(16))) _aau16Out[NUM_SAMPLES][NUM_ADCS];
    static volatile bool _bPingPong=false;
    static volatile bool _bReady=false;
    static volatile int _aanTimer[6][16];
    static volatile int _anLast[6]={0,0,0,0,0,0};
    static volatile int _anCount[6]={0,0,0,0,0,0};
    // declared static in case exception condition would prevent
    // auto variable being created
    static enum {
     EXCEP_IRQ = 0,   // interrupt
     EXCEP_AdEL = 4,   // address error exception (load or ifetch)
     EXCEP_AdES,    // address error exception (store)
     EXCEP_IBE,    // bus error (ifetch)
     EXCEP_DBE,    // bus error (load/store)
     EXCEP_Sys,    // syscall
     EXCEP_Bp,    // breakpoint
     EXCEP_RI,    // reserved instruction
     EXCEP_CpU,    // coprocessor unusable
     EXCEP_Overflow,   // arithmetic overflow
     EXCEP_Trap,    // trap (possible divide by zero)
     EXCEP_IS1 = 16,   // implementation specfic 1
     EXCEP_CEU,    // CorExtend Unuseable
     EXCEP_C2E    // coprocessor 2
    } _excep_code;
    static unsigned int _epc_code;
    static unsigned int _excep_addr;
    void _nmi_handler (void)
    {
     asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
     asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
     _excep_code = (_excep_code & 0x0000007C) >> 2;
     while (1)
        {
            Nop();
        }
    }
    void _simple_tlb_refill_exception_handler(void)
    {
     asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
     asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
     _excep_code = (_excep_code & 0x0000007C) >> 2;
     while (1)
        {
            Nop();
        }
    }
    void _cache_err_exception_handler(void)
    {
     asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
     asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
     _excep_code = (_excep_code & 0x0000007C) >> 2;
     while (1)
        {
            Nop();
        }
    }
    void _general_exception_handler(void)
    {
     asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
     asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
     _excep_code = (_excep_code & 0x0000007C) >> 2;
     while (1)
        {
            Nop();
        }
    }

    void __ISR(_TIMER_4_VECTOR,IPL5AUTO) __Timer4Interrupt(void)
    {
        static int i=0;
       
        IFS0bits.T4IF=0;
        i++;
       
        if (i>=10000)
        {
            i=0;
            LATHINV=1; // Toggle LED
        }
    }
    void __ISR(_DMA0_VECTOR,IPL5AUTO) __DMA0Interrupt(void)
    {
    //    IFS4bits.DMA0IF=0;
    //    IFS4CLR=1<<(6+0);
        PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_DMA_0); // Atomic version
        if (DCH0INTbits.CHDDIF)
        {
            int n=_CP0_GET_COUNT();
            int nIdx=_anCount[0] & 0x000F;
            int nLast=_anLast[0];
           
            _aanTimer[0][nIdx]=n-nLast;
            _anLast[0]=n;
            _anCount[0]++;
            Nop();
    //        DCH0INTbits.CHDDIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_0,DMA_INT_DESTINATION_DONE); // Atomic version
        }
        if (DCH0INTbits.CHDHIF)
        {
            Nop();
    //        DCH0INTbits.CHDHIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_0,DMA_INT_DESTINATION_HALF_FULL); // Atomic version
        }
    }
    void __ISR(_DMA1_VECTOR,IPL5AUTO) __DMA1Interrupt(void)
    {
    //    IFS4bits.DMA1IF=0;
    //    IFS4CLR=1<<(6+1);
        PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_DMA_1); // Atomic version
        if (DCH1INTbits.CHDDIF)
        {
            int n=_CP0_GET_COUNT();
            int nIdx=_anCount[1] & 0x000F;
            int nLast=_anLast[1];
           
            _aanTimer[1][nIdx]=n-nLast;
            _anLast[1]=n;
            _anCount[1]++;
            Nop();
    //        DCH1INTbits.CHDDIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_1,DMA_INT_DESTINATION_DONE); // Atomic version
        }
        if (DCH1INTbits.CHDHIF)
        {
            Nop();
    //        DCH1INTbits.CHDHIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_1,DMA_INT_DESTINATION_HALF_FULL); // Atomic version
        }
    }
    void __ISR(_DMA2_VECTOR,IPL5AUTO) __DMA2Interrupt(void)
    {
    //    IFS4bits.DMA2IF=0;
    //    IFS4CLR=1<<(6+2);
        PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_DMA_2); // Atomic version
        if (DCH2INTbits.CHDDIF)
        {
            int n=_CP0_GET_COUNT();
            int nIdx=_anCount[2] & 0x000F;
            int nLast=_anLast[2];
           
            _aanTimer[2][nIdx]=n-nLast;
            _anLast[2]=n;
            _anCount[2]++;
            Nop();
    //        DCH2INTbits.CHDDIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_2,DMA_INT_DESTINATION_DONE); // Atomic version
        }
        if (DCH2INTbits.CHDHIF)
        {
            Nop();
    //        DCH2INTbits.CHDHIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_2,DMA_INT_DESTINATION_HALF_FULL); // Atomic version
        }
    }
    void __ISR(_DMA3_VECTOR,IPL5AUTO) __DMA3Interrupt(void)
    {
    //    IFS4bits.DMA3IF=0;
    //    IFS4CLR=1<<(6+3);
        PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_DMA_3); // Atomic version
        if (DCH3INTbits.CHDDIF)
        {
            int n=_CP0_GET_COUNT();
            int nIdx=_anCount[3] & 0x000F;
            int nLast=_anLast[3];
           
            _aanTimer[3][nIdx]=n-nLast;
            _anLast[3]=n;
            _anCount[3]++;
            Nop();
    //        DCH3INTbits.CHDDIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_3,DMA_INT_DESTINATION_DONE); // Atomic version
        }
        if (DCH3INTbits.CHDHIF)
        {
            Nop();
    //        DCH3INTbits.CHDHIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_3,DMA_INT_DESTINATION_HALF_FULL); // Atomic version
        }
    }
    void __ISR(_DMA4_VECTOR,IPL5AUTO) __DMA4Interrupt(void)
    {
    //    IFS4bits.DMA4IF=0;
    //    IFS4CLR=1<<(6+4);
        PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_DMA_4); // Atomic version
        if (DCH4INTbits.CHDDIF)
        {
            int n=_CP0_GET_COUNT();
            int nIdx=_anCount[4] & 0x000F;
            int nLast=_anLast[4];
           
            _aanTimer[4][nIdx]=n-nLast;
            _anLast[4]=n;
            _anCount[4]++;
            Nop();
    //        DCH4INTbits.CHDDIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_4,DMA_INT_DESTINATION_DONE); // Atomic version
        }
        if (DCH4INTbits.CHDHIF)
        {
            Nop();
    //        DCH4INTbits.CHDHIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_4,DMA_INT_DESTINATION_HALF_FULL); // Atomic version
        }
    }
    void __ISR(_DMA5_VECTOR,IPL5AUTO) __DMA5Interrupt(void)
    {
    //    IFS4bits.DMA5IF=0;
    //    IFS4CLR=1<<(6+5);
        PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_DMA_5); // Atomic version
        if (DCH5INTbits.CHDDIF)
        {
            int n=_CP0_GET_COUNT();
            int nIdx=_anCount[5] & 0x000F;
            int nLast=_anLast[5];
           
            _aanTimer[5][nIdx]=n-nLast;
            _anLast[5]=n;
            _anCount[5]++;
            Nop();
    //        DCH5INTbits.CHDDIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_5,DMA_INT_DESTINATION_DONE); // Atomic version
           
            _bReady=true;
            _bPingPong=false;
            LATJSET=1<<12;
        }
        if (DCH5INTbits.CHDHIF)
        {
            Nop();
    //        DCH5INTbits.CHDHIF=0;
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,DMA_CHANNEL_5,DMA_INT_DESTINATION_HALF_FULL); // Atomic version
            _bReady=true;
            _bPingPong=true;
            LATJCLR=1<<12;
        }
    }
    static void CPUInit(void)
    {
        // Note that cache is already configured by startup code
        // C:\Program Files\Microchip\xc32\v1.42\pic32-libs\libpic32\stubs\pic32_init_cache.S
       
        // Set up wait states
        PLIB_PCACHE_WaitStateSet(PCACHE_ID_0, 2); // Adjust as appropriate for memory and clock
       
        // Set up prefetch
        if (PLIB_PCACHE_ExistsPrefetchEnable(PCACHE_ID_0))
        {
            PLIB_PCACHE_PrefetchEnableSet(PCACHE_ID_0, PLIB_PCACHE_PREFETCH_ENABLE_ALL);
        }
       
        // Set up interrupt controller
        PLIB_INT_MultiVectorSelect(INT_ID_0);
        PLIB_INT_Enable(INT_ID_0);
    }
    static void OSCInit(void)
    {
        // Switch to 200MHz PLL sourced from 24MHz EC POSC
        PLIB_DEVCON_SystemUnlock ( DEVCON_ID_0 );
    //    PLIB_OSC_SysPLLInputDivisorSet(OSC_ID_0, OSC_SYSPLL_IN_DIV_3); // Generate 8MHz from 24MHz POSC
        PLIB_OSC_SysPLLInputDivisorSet(OSC_ID_0, OSC_SYSPLL_IN_DIV_1); // Generate 8MHz from FRC
        PLIB_OSC_SysPLLFrequencyRangeSet(OSC_ID_0, OSC_SYSPLL_FREQ_RANGE_5M_TO_10M);   
    //    PLIB_OSC_SysPLLInputClockSourceSet(OSC_ID_0, OSC_SYSPLL_IN_CLK_SOURCE_PRIMARY);
        PLIB_OSC_SysPLLInputClockSourceSet(OSC_ID_0, OSC_SYSPLL_IN_CLK_SOURCE_FRC);
        PLIB_OSC_SysPLLMultiplierSelect(OSC_ID_0, 50);
        PLIB_OSC_SysPLLOutputDivisorSet(OSC_ID_0, OSC_SYSPLL_OUT_DIV_2);
    //    PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_PRIMARY_WITH_PLL);
        PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_FRC_WITH_PLL);
        while (!PLIB_OSC_ClockSwitchingIsComplete(OSC_ID_0))
        {
            Nop();
        }
        PLIB_DEVCON_SystemLock ( DEVCON_ID_0 );
    }
    static void ADCClass1_2DMA(void)
    {
        DMACON=0;
        DMACONbits.ON=1;
       
        DCH0CONbits.CHPRI=3; // 3 -> highest priority
        DCH0CONbits.CHAEN=1; // 1 -> Continuously enabled, auto restart after block completed
        DCH0ECON=0;
        DCH0ECONbits.CHSIRQ=_ADC_DATA0_VECTOR;
        DCH0ECONbits.SIRQEN=1; // 1 ->  Start channel cell transfer if an interrupt matching CHSIRQ occurs
        DCH0SSA=KVA_TO_PA(&ADCDATA0);
        DCH0DSA=KVA_TO_PA(&_aau16[0][0]);
        DCH0SSIZ=sizeof(_aau16[0][0]); // All sizes are in bytes
        DCH0DSIZ=sizeof(_aau16[0]);
        DCH0CSIZ=sizeof(_aau16[0][0]);
        DCH0INT=0;
        DCH0INTbits.CHDDIF=0; // Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ)
        DCH0INTbits.CHDDIE=1;
        DCH0INTbits.CHDHIF=0; // Channel Destination Pointer has reached midpoint of destination (CHDPTR = CHDSIZ/2)
        DCH0INTbits.CHDHIE=0;
        IPC33bits.DMA0IP=1;
        IPC33bits.DMA0IS=0;
        IFS4bits.DMA0IF=0;
        IEC4bits.DMA0IE=1;
        DCH0CONbits.CHEN=1;
       
        DCH1CONbits.CHPRI=3; // 3 -> highest priority
        DCH1CONbits.CHAEN=1; // 1 -> Continuously enabled, auto restart after block completed
        DCH1ECON=0;
        DCH1ECONbits.CHSIRQ=_ADC_DATA1_VECTOR;
        DCH1ECONbits.SIRQEN=1; // 1 ->  Start channel cell transfer if an interrupt matching CHSIRQ occurs
        DCH1SSA=KVA_TO_PA(&ADCDATA1);
        DCH1DSA=KVA_TO_PA(&_aau16[1][0]);
        DCH1SSIZ=sizeof(_aau16[1][0]); // All sizes are in bytes
        DCH1DSIZ=sizeof(_aau16[1]);
        DCH1CSIZ=sizeof(_aau16[1][0]);
        DCH1INT=0;
        DCH1INTbits.CHDDIF=0; // Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ)
        DCH1INTbits.CHDDIE=1;
        DCH1INTbits.CHDHIF=0; // Channel Destination Pointer has reached midpoint of destination (CHDPTR = CHDSIZ/2)
        DCH1INTbits.CHDHIE=0;
        IPC33bits.DMA1IP=1;
        IPC33bits.DMA1IS=0;
        IFS4bits.DMA1IF=0;
        IEC4bits.DMA1IE=1;
        DCH1CONbits.CHEN=1;
       
        DCH2CONbits.CHPRI=3; // 3 -> highest priority
        DCH2CONbits.CHAEN=1; // 1 -> Continuously enabled, auto restart after block completed
        DCH2ECON=0;
        DCH2ECONbits.CHSIRQ=_ADC_DATA2_VECTOR;
        DCH2ECONbits.SIRQEN=1; // 1 ->  Start channel cell transfer if an interrupt matching CHSIRQ occurs
        DCH2SSA=KVA_TO_PA(&ADCDATA2);
        DCH2DSA=KVA_TO_PA(&_aau16[2][0]);
        DCH2SSIZ=sizeof(_aau16[2][0]); // All sizes are in bytes
        DCH2DSIZ=sizeof(_aau16[2]);
        DCH2CSIZ=sizeof(_aau16[2][0]);
        DCH2INT=0;
        DCH2INTbits.CHDDIF=0; // Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ)
        DCH2INTbits.CHDDIE=1;
        DCH2INTbits.CHDHIF=0; // Channel Destination Pointer has reached midpoint of destination (CHDPTR = CHDSIZ/2)
        DCH2INTbits.CHDHIE=0;
        IPC34bits.DMA2IP=1;
        IPC34bits.DMA2IS=0;
        IFS4bits.DMA2IF=0;
        IEC4bits.DMA2IE=1;
        DCH2CONbits.CHEN=1;
       
        DCH3CONbits.CHPRI=3; // 3 -> highest priority
        DCH3CONbits.CHAEN=1; // 1 -> Continuously enabled, auto restart after block completed
        DCH3ECON=0;
        DCH3ECONbits.CHSIRQ=_ADC_DATA3_VECTOR;
        DCH3ECONbits.SIRQEN=1; // 1 ->  Start channel cell transfer if an interrupt matching CHSIRQ occurs
        DCH3SSA=KVA_TO_PA(&ADCDATA3);
        DCH3DSA=KVA_TO_PA(&_aau16[3][0]);
        DCH3SSIZ=sizeof(_aau16[3][0]); // All sizes are in bytes
        DCH3DSIZ=sizeof(_aau16[3]);
        DCH3CSIZ=sizeof(_aau16[3][0]);
        DCH3INT=0;
        DCH3INTbits.CHDDIF=0; // Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ)
        DCH3INTbits.CHDDIE=1;
        DCH3INTbits.CHDHIF=0; // Channel Destination Pointer has reached midpoint of destination (CHDPTR = CHDSIZ/2)
        DCH3INTbits.CHDHIE=0;
        IPC34bits.DMA3IP=1;
        IPC34bits.DMA3IS=0;
        IFS4bits.DMA3IF=0;
        IEC4bits.DMA3IE=1;
        DCH3CONbits.CHEN=1;
       
        DCH4CONbits.CHPRI=3; // 3 -> highest priority
        DCH4CONbits.CHAEN=1; // 1 -> Continuously enabled, auto restart after block completed
        DCH4ECON=0;
        DCH4ECONbits.CHSIRQ=_ADC_DATA4_VECTOR;
        DCH4ECONbits.SIRQEN=1; // 1 ->  Start channel cell transfer if an interrupt matching CHSIRQ occurs
        DCH4SSA=KVA_TO_PA(&ADCDATA4);
        DCH4DSA=KVA_TO_PA(&_aau16[4][0]);
        DCH4SSIZ=sizeof(_aau16[4][0]); // All sizes are in bytes
        DCH4DSIZ=sizeof(_aau16[4]);
        DCH4CSIZ=sizeof(_aau16[4][0]);
        DCH4INT=0;
        DCH4INTbits.CHDDIF=0; // Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ)
        DCH4INTbits.CHDDIE=1;
        DCH4INTbits.CHDHIF=0; // Channel Destination Pointer has reached midpoint of destination (CHDPTR = CHDSIZ/2)
        DCH4INTbits.CHDHIE=0;
        IPC34bits.DMA4IP=1;
        IPC34bits.DMA4IS=0;
        IFS4bits.DMA4IF=0;
        IEC4bits.DMA4IE=1;
        DCH4CONbits.CHEN=1;
       
        DCH5CONbits.CHPRI=3; // 3 -> highest priority
        DCH5CONbits.CHAEN=1; // 1 -> Continuously enabled, auto restart after block completed
        DCH5ECON=0;
        DCH5ECONbits.CHSIRQ=_ADC_DATA11_VECTOR;
        DCH5ECONbits.SIRQEN=1; // 1 ->  Start channel cell transfer if an interrupt matching CHSIRQ occurs
        DCH5SSA=KVA_TO_PA(&ADCDATA11);
        DCH5DSA=KVA_TO_PA(&_aau16[5][0]);
        DCH5SSIZ=sizeof(_aau16[5][0]); // All sizes are in bytes
        DCH5DSIZ=sizeof(_aau16[5]);
        DCH5CSIZ=sizeof(_aau16[5][0]);
        DCH5INT=0;
        DCH5INTbits.CHDDIF=0; // Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ)
        DCH5INTbits.CHDDIE=1;
        DCH5INTbits.CHDHIF=0; // Channel Destination Pointer has reached midpoint of destination (CHDPTR = CHDSIZ/2)
        DCH5INTbits.CHDHIE=0;
        IPC34bits.DMA5IP=1;
        IPC34bits.DMA5IS=0;
        IFS4bits.DMA5IF=0;
        IEC4bits.DMA5IE=1;
        DCH5CONbits.CHEN=1;
        ANSELBbits.ANSB0=1; // AN0
        ANSELBbits.ANSB1=1; // AN1
        ANSELBbits.ANSB2=1; // AN2
        ANSELBbits.ANSB3=1; // AN3
        ANSELBbits.ANSB4=1; // AN4
        ANSELGbits.ANSG9=1; // AN5
       
        /* initialize ADC calibration setting */
        ADC0CFG = DEVADC0;
        ADC1CFG = DEVADC1;
        ADC2CFG = DEVADC2;
        ADC3CFG = DEVADC3;
        ADC4CFG = DEVADC4;
        ADC7CFG = DEVADC7;
         /* Configure ADCCON1 */
        ADCCON1 = 0; // No ADCCON1 features are enabled including: Stop-in-Idle, turbo,
                    // CVD mode, Fractional mode and scan trigger source.
        ADCCON1bits.FRACT = 0; // use Integer output format //**2
        ADCCON1bits.SELRES = 3; // ADC7 resolution is 12 bits //**2
        ADCCON1bits.STRGSRC = 0; // No scan trigger. //**2
       
        // DS60001320D-page 427 - Notes 1 & 2 in textbox
        ADCCON1bits.AICPMPEN=0; // 0 -> Vdd>=2.5v (Analog Input Charge Pump off)
        CFGCONbits.IOANCPEN=0; // 0 -> Vdd>=2.5v (I/O analogue charge pump off)
       
        // DS60001344B-page 22-77
    //    ADCCON1bits.FSSCLKEN=1;
    //    ADCCON1bits.FSPBCLKEN=1;
       
        /* Configure ADCCON2 */
        ADCCON2 = 0; // Since, we are using only the Class 1 inputs, no setting is
                    // required for ADCDIV
    //    ADCCON2bits.SAMC = 5; // ADC7 sampling time = 5 * TAD7 //**2
        ADCCON2bits.SAMC = 3; // ADC7 sampling time = 5 * TAD7 [Tsamp=Tad*(SAMC+2)] //**2
    //    ADCCON2bits.ADCDIV = 1; // ADC7 clock freq is half of control clock = TAD7 [Tad7=Tq/2 (20ns/50MHz)] //**2
        ADCCON2bits.ADCDIV = 2; // ADC7 clock freq is half of control clock = TAD7 [Tad7=Tq/4 (20ns/50MHz)] //**2
       
        /* Initialize warm up time register */
        ADCANCON = 0;
        ADCANCONbits.WKUPCLKCNT = 5; // Wakeup exponent = 32 * TADx
       
        /* Clock setting */
        ADCCON3 = 0;
    //    ADCCON3bits.ADCSEL = 0b00; // Select input clock source 0b00 -> Tclk=PBCLK3 (10ns/100MHz)
        ADCCON3bits.ADCSEL = 0b01; // Select input clock source, 0b01 -> Tclk=Tcy (5ns/200MHz)
    //    ADCCON3bits.CONCLKDIV = 1; // Control clock frequency is half of input clock 1 -> Tq=2*Tclk (10ns/100MHz)
        ADCCON3bits.CONCLKDIV = 0; // Control clock frequency is input clock 1 -> Tq=Tclk (5ns/200MHz)
        ADCCON3bits.VREFSEL = 0; // Select AVDD and AVSS as reference source
       
        /* Select ADC sample time and conversion clock */
    //    ADC0TIMEbits.ADCDIV = 1; // ADC0 clock frequency is half of control clock = TAD0 [Tad=Tq/2 (20ns/50MHz)]
        ADC0TIMEbits.ADCDIV = 2; // ADC0 clock frequency is half of control clock = TAD0 [Tad=Tq/4 (20ns/50MHz)]
        ADC0TIMEbits.SAMC = 3; // ADC0 sampling time = 5 * TAD0 [Tsamp=Tad*(SAMC+2)]
        ADC0TIMEbits.SELRES = 3; // ADC0 resolution is 12 bits
    //    ADC1TIMEbits.ADCDIV = 1; // ADC1 clock frequency is half of control clock = TAD1 [Tad=Tq/2 (20ns/50MHz)]
        ADC1TIMEbits.ADCDIV = 2; // ADC1 clock frequency is half of control clock = TAD0 [Tad=Tq/4 (20ns/50MHz)]
        ADC1TIMEbits.SAMC = 3; // ADC1 sampling time = 5 * TAD1 [Tsamp=Tad*(SAMC+2)]
        ADC1TIMEbits.SELRES = 3; // ADC1 resolution is 12 bits
    //    ADC2TIMEbits.ADCDIV = 1; // ADC2 clock frequency is half of control clock = TAD2 [Tad=Tq/2 (20ns/50MHz)]
        ADC2TIMEbits.ADCDIV = 2; // ADC2 clock frequency is half of control clock = TAD0 [Tad=Tq/4 (20ns/50MHz)]
        ADC2TIMEbits.SAMC = 3; // ADC2 sampling time = 5 * TAD2 [Tsamp=Tad*(SAMC+2)]
        ADC2TIMEbits.SELRES = 3; // ADC2 resolution is 12 bits
    //    ADC3TIMEbits.ADCDIV = 1; // ADC3 clock frequency is half of control clock = TAD3 [Tad=Tq/2 (20ns/50MHz)]
        ADC3TIMEbits.ADCDIV = 2; // ADC3 clock frequency is half of control clock = TAD0 [Tad=Tq/4 (20ns/50MHz)]
        ADC3TIMEbits.SAMC = 3; // ADC3 sampling time = 5 * TAD3 [Tsamp=Tad*(SAMC+2)]
        ADC3TIMEbits.SELRES = 3; // ADC3 resolution is 12 bits
    //    ADC4TIMEbits.ADCDIV = 1; // ADC4 clock frequency is half of control clock = TAD4 [Tad=Tq/2 (20ns/50MHz)]
        ADC4TIMEbits.ADCDIV = 2; // ADC4 clock frequency is half of control clock = TAD0 [Tad=Tq/4 (20ns/50MHz)]
        ADC4TIMEbits.SAMC = 3; // ADC4 sampling time = 5 * TAD4 [Tsamp=Tad*(SAMC+2)]
        ADC4TIMEbits.SELRES = 3; // ADC4 resolution is 12 bits
       
        /* Select analog input for ADC modules, no presync trigger, not sync sampling */
        ADCTRGMODEbits.SH0ALT = 0; // ADC0 = AN0
        ADCTRGMODEbits.SH1ALT = 0; // ADC1 = AN1
        ADCTRGMODEbits.SH2ALT = 0; // ADC2 = AN2
        ADCTRGMODEbits.SH3ALT = 0; // ADC3 = AN3
        ADCTRGMODEbits.SH4ALT = 0; // ADC4 = AN4
       
    //    ADCTRGMODEbits.SSAMPEN0=1; // 1 -> synchronous sampling for the first sample after being idle or disabled
    //    ADCTRGMODEbits.SSAMPEN1=1; // 1 -> synchronous sampling for the first sample after being idle or disabled
    //    ADCTRGMODEbits.SSAMPEN2=1; // 1 -> synchronous sampling for the first sample after being idle or disabled
    //    ADCTRGMODEbits.SSAMPEN3=1; // 1 -> synchronous sampling for the first sample after being idle or disabled
    //    ADCTRGMODEbits.SSAMPEN4=1; // 1 -> synchronous sampling for the first sample after being idle or disabled
       
        /* Select ADC input mode */
        ADCIMCON1bits.SIGN0 = 0; // unsigned data format
        ADCIMCON1bits.DIFF0 = 0; // Single ended mode
        ADCIMCON1bits.SIGN1 = 0; // unsigned data format
        ADCIMCON1bits.DIFF1 = 0; // Single ended mode
        ADCIMCON1bits.SIGN2 = 0; // unsigned data format
        ADCIMCON1bits.DIFF2 = 0; // Single ended mode
        ADCIMCON1bits.SIGN3 = 0; // unsigned data format
        ADCIMCON1bits.DIFF3 = 0; // Single ended mode
        ADCIMCON1bits.SIGN4 = 0; // unsigned data format
        ADCIMCON1bits.DIFF4 = 0; // Single ended mode
        ADCIMCON1bits.SIGN11 = 0; // unsigned data format //**2
        ADCIMCON1bits.DIFF11 = 0; // Single ended mode //**2
       
        /* Configure ADCGIRQENx */
        ADCGIRQEN1 = 0; // No interrupts are used
        ADCGIRQEN2 = 0;
        ADCGIRQEN1bits.AGIEN0=1;
        ADCGIRQEN1bits.AGIEN1=1;
        ADCGIRQEN1bits.AGIEN2=1;
        ADCGIRQEN1bits.AGIEN3=1;
        ADCGIRQEN1bits.AGIEN4=1;
        ADCGIRQEN1bits.AGIEN11=1;
       
        /* Configure ADCCSSx */
        ADCCSS1 = 0; // No scanning is used
        ADCCSS2 = 0;
       
        /* Configure ADCCMPCONx */
        ADCCMPCON1 = 0; // No digital comparators are used. Setting the ADCCMPCONx
        ADCCMPCON2 = 0; // register to '0' ensures that the comparator is disabled.
        ADCCMPCON3 = 0; // Other registers are ?don't care?.
        ADCCMPCON4 = 0;
        ADCCMPCON5 = 0;
        ADCCMPCON6 = 0;
        /* Configure ADCFLTRx */
        ADCFLTR1 = 0; // No oversampling filters are used.
        ADCFLTR2 = 0;
        ADCFLTR3 = 0;
        ADCFLTR4 = 0;
        ADCFLTR5 = 0;
        ADCFLTR6 = 0;
       
        /* Set up the trigger sources */
        ADCTRGSNSbits.LVL0 = 0; // Edge trigger
        ADCTRGSNSbits.LVL1 = 0; // Edge trigger
        ADCTRGSNSbits.LVL2 = 0; // Edge trigger
        ADCTRGSNSbits.LVL3 = 0; // Edge trigger
        ADCTRGSNSbits.LVL4 = 0; // Edge trigger
        ADCTRGSNSbits.LVL11 = 0; // Edge trigger //**2
       
    //    ADCTRG1bits.TRGSRC0 = 1; // Set AN0 to trigger from software.
        ADCTRG1bits.TRGSRC0 = 0b01000; // 0b01000 -> OCMP1
    //    ADCTRG1bits.TRGSRC0 = 0b01001; // 0b01001 -> OCMP3
    //    ADCTRG1bits.TRGSRC0 = 0b01010; // 0b01010 -> OCMP5
       
    //    ADCTRG1bits.TRGSRC1 = 1; // Set AN1 to trigger from software.
        ADCTRG1bits.TRGSRC1 = 0b01000; // 0b01000 -> OCMP1
    //    ADCTRG1bits.TRGSRC1 = 0b01001; // 0b01001 -> OCMP3
    //    ADCTRG1bits.TRGSRC1 = 0b01010; // 0b01010 -> OCMP5
    //    ADCTRG1bits.TRGSRC1 = 0b00110; // 0b00110 -> TMR3
       
    //    ADCTRG1bits.TRGSRC2 = 1; // Set AN2 to trigger from software.
    //    ADCTRG1bits.TRGSRC2 = 0b01000; // 0b01000 -> OCMP1
        ADCTRG1bits.TRGSRC2 = 0b01001; // 0b01001 -> OCMP3
    //    ADCTRG1bits.TRGSRC2 = 0b01010; // 0b01010 -> OCMP5
       
    //    ADCTRG1bits.TRGSRC3 = 1; // Set AN3 to trigger from software.
    //    ADCTRG1bits.TRGSRC3 = 0b01000; // 0b01000 -> OCMP1
        ADCTRG1bits.TRGSRC3 = 0b01001; // 0b01001 -> OCMP3
    //    ADCTRG1bits.TRGSRC3 = 0b01010; // 0b01010 -> OCMP5
       
    //    ADCTRG2bits.TRGSRC4 = 1; // Set AN4 to trigger from software.
    //    ADCTRG2bits.TRGSRC4 = 0b01000; // 0b01000 -> OCMP1
    //    ADCTRG2bits.TRGSRC4 = 0b01001; // 0b01001 -> OCMP3
        ADCTRG2bits.TRGSRC4 = 0b01010; // 0b01010 -> OCMP5
       
    //    ADCTRG3bits.TRGSRC11 = 1; // Set AN11 to trigger from software //**2
    //    ADCTRG3bits.TRGSRC11 = 0b01000; // 0b01000 -> OCMP1
    //    ADCTRG3bits.TRGSRC11 = 0b01001; // 0b01001 -> OCMP3
        ADCTRG3bits.TRGSRC11 = 0b01010; // 0b01010 -> OCMP5
       
        /* 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.ANEN0 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN1 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN2 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN3 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN4 = 1; // Enable the clock to analog bias
        ADCANCONbits.ANEN7 = 1; // Enable the clock to analog bias //**2
       
        /* Wait for ADC to be ready */
        while(!ADCANCONbits.WKRDY0); // Wait until ADC0 is ready
        while(!ADCANCONbits.WKRDY1); // Wait until ADC1 is ready
        while(!ADCANCONbits.WKRDY2); // Wait until ADC2 is ready
        while(!ADCANCONbits.WKRDY3); // Wait until ADC3 is ready
        while(!ADCANCONbits.WKRDY4); // Wait until ADC4 is ready
        while(!ADCANCONbits.WKRDY7); // Wait until ADC7 is ready //**2
       
        /* Enable the ADC module */
        ADCCON3bits.DIGEN0 = 1; // Enable ADC0
        ADCCON3bits.DIGEN1 = 1; // Enable ADC1
        ADCCON3bits.DIGEN2 = 1; // Enable ADC2
        ADCCON3bits.DIGEN3 = 1; // Enable ADC3
        ADCCON3bits.DIGEN4 = 1; // Enable ADC4
        ADCCON3bits.DIGEN7 = 1; // Enable ADC7 //**2
       
        // Set up timer 3
        TMR3=0;
        PR3=18*2-1;
    //    PR3=180-1;
        IPC3bits.T3IP=1;
        IPC3bits.T3IS=0;
        IFS0bits.T3IF=0;
        IEC0bits.T3IE=0;
        T3CONbits.ON=1;
        // Set up OC1
        OC1R=1;
        OC1RS=6;
        OC1CONbits.OCM=0b101; // 0b101=continuous pulses
        OC1CONbits.OCTSEL=1; // 1=TMR3
        RPD0Rbits.RPD0R=0b1100; // 0b1100=OC1
        OC1CONbits.ON=1;
       
        // Set up OC3
        OC3R=13;
        OC3RS=18;
    //    OC3R=61;
    //    OC3RS=66;
        OC3CONbits.OCM=0b101; // 0b101=continuous pulses
        OC3CONbits.OCTSEL=1; // 1=TMR3
        RPD10Rbits.RPD10R=0b1011; // 0b1011=OC3
        OC3CONbits.ON=1;
       
        // Set up OC5
        OC5R=25;
        OC5RS=30;
    //    OC5R=121;
    //    OC5RS=126;
        OC5CONbits.OCM=0b101; // 0b101=continuous pulses
        OC5CONbits.OCTSEL=1; // 1=TMR3
        RPD9Rbits.RPD9R=0b1011; // 0b1011=OC5
        OC5CONbits.ON=1;
       
        // Timer 7 for test signal
        TMR2=0;
        PR2=(PR3+1)*4-1;
        IPC2bits.T2IP=1;
        IPC2bits.T2IS=0;
        IFS0bits.T2IF=0;
        IEC0bits.T2IE=0;
        T2CONbits.ON=1;
        // Set up OC7 - test signal
        OC7R=1;
        OC7RS=PR2/2;
        OC7CONbits.OCM=0b101; // 0b101=continuous pulses
        OC7CONbits.OCTSEL=0; // 0=TMR2
        RPD11Rbits.RPD11R=0b1100; // 0b1100=OC7
        OC7CONbits.ON=1;
    }
    void main(void)
    {
        CPUInit();
        OSCInit();
       
        // All digital GPIO except AN0-AN11 (RPB0-4, RPB10-15, RPG9)
        ANSELA=0;
        ANSELB=0xFC1F;
        ANSELC=0;
        ANSELD=0;
        ANSELE=0;
        ANSELF=0;
        ANSELG=0x0200;
        ANSELH=0;
       
        LATA=0;
        LATB=0;
        LATC=0;
        LATD=0;
        LATE=0;
        LATF=0;
        LATG=0;
        LATH=0;
        LATJ=0;
        TRISA=0;
        TRISB=0;
        TRISC=0;
        TRISD=0;
        TRISE=0;
        TRISF=0;
        TRISG=0;
        TRISH=0;
        TRISJ=0;
        TRISHbits.TRISH0=0; // LED output
        TRISJbits.TRISJ3=0; // J12 pin 40
       
        // Set up timer 4
        TMR4=0;
        PR4=10000;
        IPC4bits.T4IP=1;
        IPC4bits.T4IS=0;
        IFS0bits.T4IF=0;
        IEC0bits.T4IE=1;
    //    T4CONbits.ON=1;
    // Set up EBI
        //Controls access of pins shared with PMP
        CFGEBIA=0;
        CFGEBIAbits.EBIPINEN=1;
        CFGEBIAbits.EBIA0EN=1; // LSB is I/Q designator, for debugging
        CFGEBIC=0;
        CFGEBICbits.EBIWEEN=1;
        CFGEBICbits.EBICSEN0=1;
        CFGEBICbits.EBIDEN0=1;
        CFGEBICbits.EBIDEN1=1;
        //Connect CS0 to physical address
        EBICS0 = 0x20000000;
        // Memory size is set as 2 MB
        // Memory type is set as SRAM
        // Uses timing numbers in EBISMT0
        EBIMSK0=0;
        EBIMSK0bits.MEMTYPE=0b001; // 0b001 -> SRAM
        EBIMSK0bits.REGSEL=0b000; // 0b000 -> Use EBITMGR0;
        EBIMSK0bits.MEMSIZE=0b00001; // 0b00001 -> 64kbytes
        //Configure EBISMT0
        EBISMT0=0;
        EBISMT0bits.TBTA=1; // 0b001 -> bus turnaround time 1 cycle
        EBISMT0bits.TWP=0; // 0b00 -> Write pulse 1 cycle
        EBISMT0bits.TWR=1; // 0b01 -> Write address/data hold time 1 cycle
        EBISMT0bits.TAS=1; // 0b01 -> Write address setup time 1 cycle
        //Keep default data width to 16-bits
        EBISMCON = 0x00000000;
       
    #define SRAM_ADDR_CS0 0xC0000000
    #define RAM_SIZE 65536   
       
    #if 0   
        while (1)
        {
            uint32_t loop;
            uint16_t *addr;
            uint32_t val;
            addr = (uint16_t *)SRAM_ADDR_CS0;
            //Write loop
            for (loop=0; loop < RAM_SIZE/4; loop++)
            {
                *addr++ = (uint16_t)loop;
                Nop();
                Nop();
                Nop();
                Nop();
                Nop();
                Nop();
                Nop();
                Nop();
            }
        }
    #endif
       
        ADCClass1_2DMA();
        while (1)
        {
            if (_bReady)
            {
                volatile uint16_t *pu16=&_aau16[0][_bPingPong*(NUM_SAMPLES/2)];
                volatile uint16_t *pu16Out=(uint16_t *)SRAM_ADDR_CS0;
                int i;
               
                _bReady=false;
               
                LATHSET=1;
                for (i=0;i<NUM_SAMPLES/2;i++)
                {
                    LATHSET=2;
                    *pu16Out++=pu16[NUM_SAMPLES*0];
                    *pu16Out++=pu16[NUM_SAMPLES*1];
                    *pu16Out++=pu16[NUM_SAMPLES*2];
                    *pu16Out++=pu16[NUM_SAMPLES*3];
                    *pu16Out++=pu16[NUM_SAMPLES*4];
                    *pu16Out++=pu16[NUM_SAMPLES*5];
                    pu16++;
                    LATHCLR=2;
                }
                LATHCLR=1;
            }
            Nop();
        }
    }

    #3
    bazmrl
    Starting Member
    • Total Posts : 33
    • Reward points : 0
    • Joined: 2008/09/01 08:06:00
    • Location: 0
    • Status: offline
    Re: PIC32MZ - Looking for a ADCHS with DMA example 2018/12/15 22:24:07 (permalink)
    0
    Thanks for the help
    #4
    Jump to:
    © 2019 APG vNext Commercial Version 4.5