This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LM3S9B96 Digital Comparator Problem

Guru 22270 points

Replies: 8

Views: 3157

Here is what I want to do:
1) Read the ADC value
2) Send it to the digital comparator
3) If the value is above the set point then trigger the PWM Fault and shutdown the PWM that is set up as an H bridge with dead-band

Post edited by: greenja, at: 2010/04/27 21:10

8 Replies

  • Hello greenja,

    I have a few questions for you:

    Are you seeing the digital comparator trigger at least once?

    Have you been able to get the digital comparator to trigger with any other trigger mode?

    Why do you call the following:

    HWREG(ADC0_BASE + ADC_O_IM) |= ADC_IM_DCONSS3; // Allow for raw interrupt on DCONSS3

    I am trying to understand your reasoning for setting the interrupt mask even though you do not want to use interrupts.

    Also I would try removing the ADC_CTL_IE from "ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 |
    ADC_CTL_CMP0 | ADC_CTL_END | ADC_CTL_IE );" for the same reason.

    We have test code for the digital comparator but it is not at a state that can be released to the public. Keep a look out for future releases of Stellaris Ware for these code examples.

    -TI Yano
  • Guru 22270 points
    deleted by author

    Post edited by: greenja, at: 2010/04/27 21:11
  • Your reasons for not posting the code are not correct, but we won't get in to that. Here is the examples that we currently have.

    Code:


     
    //! This example shows how to setup 4 different digital comparators on a
    //! single ADC pin.  This example uses ADC0 sequence 0 to setup the 4 digital
    //! comparators on step 0 to step 3 and a single ADC sample on step 4.  We then
    //! look at the voltage on Port B pin 4 and use the digital comparators to see
    //! when the voltage passes above 1.05V or 2.05V and below 0.95V or 1.95V.  The
    //! 0.1V difference is used to avoid interrupting due to noise when coming near
    //! the low-band and high-band. 
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - ADC0 peripheral
    //! - GPIO Port B peripheral (for ADC0 pin)
    //! - AIN10 - PB4
    //!
    //! The following UART signals are configured only for displaying console
    //! messages for this example.  These are not required for operation of the
    //! ADC.
    //! - UART0 peripheral
    //! - GPIO Port A peripheral (for UART0 pins)
    //! - UART0RX - PA0
    //! - UART0TX - PA1
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - INT_ADC0 - ADC0Seq0IntHandler
    //!
    //
    //*****************************************************************************

    //*****************************************************************************
    //
    // Macro definitions for 0.95V, 1.05V, 1.95V, and 2.05V with 10-bit resolution.
    // The calculations can be seen below.
    //
    // 0.95V =>  (2^10 - 1) * (0.95V / 3.0V)      = 324
    // 1.05V => [(2^10 - 1) * (1.05V / 3.0V)] - 1 = 357
    // 1.95V =>  (2^10 - 1) * (1.95V / 3.0V)      = 665
    // 2.05V => [(2^10 - 1) * (2.05V / 3.0V)] - 1 = 698
    //
    // NOTE: Since the high_band is exclusive, we subtract 1 from 1.05V and 2.05V
    // so the digital comparators detect voltages that are greater than or equal
    // rather than just greater.  Since the low-band is inclusive, we leave the
    // 0.95V and 1.95V as is.
    //
    //*****************************************************************************
    #define ADC_VALUE_0_95V 323
    #define ADC_VALUE_1_05V 358
    #define ADC_VALUE_1_95V 664
    #define ADC_VALUE_2_05V 699

    //*****************************************************************************
    //
    // Macro definitions for the warning printouts.  Print a warning message based
    // on what digital comparator sent the interrupt.  UNDER_0_95V is the flag for
    // the digital comparator 0 interrupt, OVER_1_05V is the flag for the digital
    // comparator 1 interrupt, UNDER_1_95V is the flag for the digital comparator
    // 2 interrupt, and OVER_2_05V is the flag for the digital comparator 3
    // interrupt.
    //
    //*****************************************************************************
    #define UNDER_0_95V 0x01
    #define OVER_1_05V  0x02
    #define UNDER_1_95V 0x04
    #define OVER_2_05V  0x08 

    //*****************************************************************************
    //
    // Global variable to count the number of digital comparator interrupts.  This
    // variable is not needed for the proper operation of the ADC or digital
    // comparators.
    //
    //*****************************************************************************
    unsigned long g_ulNumOfInt;

    //*****************************************************************************
    //
    // Global variable to count the number of digital omparator interrupts that
    // have been triggered.  This variable is not needed for the proper operation
    // of the ADC or digital comparators.
    //
    //*****************************************************************************
    unsigned long g_ulDCIntStatus;

    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole
    (void)
    {
        
    //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

        
    //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //   
        
    GPIOPinConfigure(GPIO_PA0_U0RX);
        
    GPIOPinConfigure(GPIO_PA1_U0TX);

        
    //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        
    GPIOPinTypeUART(GPIO_PORTA_BASEGPIO_PIN_0 GPIO_PIN_1);

        
    //
        // Initialize the UART for console I/O.
        //
        
    UARTStdioInit(0);
    }

    //*****************************************************************************
    //
    // The interrupt handler for digital comparator 0.
    //
    //*****************************************************************************
    void
    ADC0Seq0IntHandler
    (void)
    {
        
    //
        // Read the digital comparator interrupt status register.  This global
        // variable will keep track of which digital comparator triggered the
        // interrupt.
        //
        
    g_ulDCIntStatus ADCComparatorIntStatus(ADC0_BASE);

        
    //
        // Clear all of the digital comparator interrupt bits.  We do this because
        // more than one digital comparator interrupt may have been triggered this
        // interrupt.
        //
        
    ADCComparatorIntClear(ADC0_BASE0x0F);

        
    //
        // Increment the variable that keeps track of how many interrupts have
        // been triggered.
        //
        
    g_ulNumOfInt++;   
    }

    //*****************************************************************************
    //
    // This example sets up sequence 0 on ADC 0.  Four of the steps on sequence 0
    // are set up to use digital comparators, and one step on sequence 0 is used
    // to read the ADC value.
    //
    //******************************************************************************
    int
    main
    (void)
    {    
        
    //
        // This array is used for storing the data read from the ADC FIFO.  It
        // must be as large as the FIFO for the sequencer in use.  This example
        // uses sequence 0 which has a FIFO depth of 8.  If another sequence
        // was used with a smaller FIFO, then the array size may be changed.
        //
        
    unsigned long ulADC0_Value[8];

        
    //
        // This variable is used to calculate the voltage based on the the ADC
        // data.
        //
        
    unsigned long ulADC0_Voltage;

        
    //
        // Set the clocking to run at 20 MHz (200 MHz / 10) using the PLL.  When
        // using the ADC, you must either use the PLL or supply a 16 MHz clock
        // source.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
        
    SysCtlClockSet(SYSCTL_SYSDIV_10 SYSCTL_USE_PLL SYSCTL_OSC_MAIN |
                       
    SYSCTL_XTAL_16MHZ);

        
    //
        // Set up the serial console to use for displaying messages.  This is
        // just for this example program and is not needed for ADC operation.
        //
        
    InitConsole();

        
    //
        // Display the setup on the console.
        // 
        
    UARTprintf("ADC ->
    "
    );  
        
    UARTprintf("  Type: Digital Comparators
    "
    );
        
    UARTprintf("  Input Pin: PB4
    "
    ); 
        
    UARTprintf("  Description: Use digital comparators to watch voltage
    "
    );
        
    UARTprintf("  Interrupt: ADC Sample Sequence 0

    "
    ); 

        
    //
        // The ADC0 peripheral must be enabled for use.
        //
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);  

        
    //
        // For this example ADC0 is used with AIN10 on Port B pin 4.  The actual
        // port and pins used may be different on your part, consult the data sheet
        // for more information.  GPIO port B needs to be enabled so these pins can
        // be used.
        // TODO: change this to whichever GPIO port you are using.
        //
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

        
    //
        // Select the analog ADC function for these pins.  Consult the data sheet
        // to see which functions are allocated per pin.
        // TODO: change this to select the port/pin you are using.
        //
        
    GPIOPinTypeADC(GPIO_PORTB_BASEGPIO_PIN_4);

        
    //
        // Enable processor interrupts.
        //
        
    IntMasterEnable();

        
    //
        // Enable the ADC sample sequence 0 interrupt on the processor (NVIC).
        //
        
    IntEnable(INT_ADC0);

        
    //
        // Enable sample sequence 0 with a continuous signal trigger and a priority
        // of zero.  Sequence 0 will sample continuouly until the program is
        // halted.
        //
        
    ADCSequenceConfigure(ADC0_BASE0ADC_TRIGGER_ALWAYS0);

        
    //
        // Configure step 0 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 0 (ADC_CTL_CMP0).  NOTE: When you send the ADC sample to the
        // digital comparator, you will no longer be able to read the raw ADC data
        // on that specific step.  The option is send the data to the FIFOs OR to
        // the digital comparator.  Sequence 0 has 8 programmable steps, sequence 1
        // and 2 have 4 programmable steps, and sequence 3 has 1 programmable step.
        // Since we are using 4 digital comparators and a single sample, we will
        // configure steps 0-4.  For more information on the ADC sequences and
        // steps, reference the datasheet.
        //   
        
    ADCSequenceStepConfigure(ADC0_BASE00ADC_CTL_CH10 ADC_CTL_CMP0);

        
    //
        // Configure step 1 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 1 (ADC_CTL_CMP1).
        //
        
    ADCSequenceStepConfigure(ADC0_BASE01ADC_CTL_CH10 ADC_CTL_CMP1);

        
    //
        // Configure step 2 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 2 (ADC_CTL_CMP2).
        //   
        
    ADCSequenceStepConfigure(ADC0_BASE02ADC_CTL_CH10 ADC_CTL_CMP2);                            

        
    //
        // Configure step 3 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 3 (ADC_CTL_CMP3).
        //       
        
    ADCSequenceStepConfigure(ADC0_BASE03ADC_CTL_CH10 ADC_CTL_CMP3);

        
    //
        // Configure step 4 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default).  Configure step 4 to be the last conversion
        // on sample sequence 0 (ADC_CTL_END).
        //   
        
    ADCSequenceStepConfigure(ADC0_BASE04ADC_CTL_CH10 ADC_CTL_END);

        
    //
        // Since sample sequence 0 is now configured, it must be enabled.
        //
        
    ADCSequenceEnable(ADC0_BASE0);

        
    //
        // Configure the ADC digital comparator.  For this example we will use the
        // "interrupt once hysteresis" mode.  This mode will interrupt only once
        // when the ADC value goes through the mid-band region and then through
        // the low/high region.  Digital comparators 0 and 2 are configured for
        // low-band hysteresis and digital comparators 1 and 3 and configured for
        // high-band hysteresis.  Reference the datasheet for more information on
        // the digital comparator regions.
        //
        
    ADCComparatorConfigure(ADC0_BASE0ADC_COMP_INT_LOW_HONCE);
        
    ADCComparatorConfigure(ADC0_BASE1ADC_COMP_INT_HIGH_HONCE);
        
    ADCComparatorConfigure(ADC0_BASE2ADC_COMP_INT_LOW_HONCE);
        
    ADCComparatorConfigure(ADC0_BASE3ADC_COMP_INT_HIGH_HONCE);

        
    //
        // Define the low-band and high-band for the digital comparators 0 and 1.
        // The low-band is defined as anything less or equal to ADC_VALUE_0_95V,
        // the mid-band is defined as anything greater than ADC_VALUE_0_95V and
        // less or equal to ADC_VALUE_1_05V, and the high-band is defined as
        // anything greater than ADC_VALUE_1_05V.  Note that the maximum value that
        // the low-band reference or high-band reference can be for the 10-bit ADCs
        // is 1023 and that the low-band reference has to be less than or equal to
        // the high-band reference.
        //
        
    ADCComparatorRegionSet(ADC0_BASE0ADC_VALUE_0_95VADC_VALUE_1_05V);
        
    ADCComparatorRegionSet(ADC0_BASE1ADC_VALUE_0_95VADC_VALUE_1_05V);

        
    //
        // Define the low-band and high-band for the digital comparators 2 and 3.
        // The low-band is defined as anything less or equal to ADC_VALUE_1_95V,
        // the mid-band is defined as anything greater than ADC_VALUE_1_95V and
        // less or equal to ADC_VALUE_2_05V, and the high-band is defined as
        // anything greater than ADC_VALUE_2_05V.  Note that the maximum value that
        // the low-band reference or high-band reference can be for the 10-bit ADCs
        // is 1023 and that the low-band reference has to be less than or equal to
        // the high-band reference.
        //     
        
    ADCComparatorRegionSet(ADC0_BASE2ADC_VALUE_1_95VADC_VALUE_2_05V);
        
    ADCComparatorRegionSet(ADC0_BASE3ADC_VALUE_1_95VADC_VALUE_2_05V);

        
    //
        // Initalize the digital comparator interrupt counter.
        //
        
    g_ulNumOfInt 0;

        
    //
        // Clear all the interrupts and and triggers for digital comparators 0 to
        // 3.  The "true" parameters clear the the trigger and interrupt flags.
        //
        
    ADCComparatorReset(ADC0_BASE0truetrue);
        
    ADCComparatorReset(ADC0_BASE1truetrue);
        
    ADCComparatorReset(ADC0_BASE2truetrue);
        
    ADCComparatorReset(ADC0_BASE3truetrue);

        
    //
        // Since the program constantly prints to the screen, have a 3 second delay
        // before starting so the user can read the setup.  The SysCtlDelay
        // function provides a means of generating a constant length delay.  The
        // function delay (in cycles) = 3 * parameter.
        //    
        
    UARTprintf("Program starting in 3 .
    "
    );
        
    SysCtlDelay(SysCtlClockGet() / 3);
        
    UARTprintf("Program starting in 2 . .
    "
    );
        
    SysCtlDelay(SysCtlClockGet() / 3);
        
    UARTprintf("Program starting in 1 . . .
    "
    );
        
    SysCtlDelay(SysCtlClockGet() / 3);

        
    //
        // Enable the digital comparator interrupts on sample sequence 0.
        //
        
    ADCComparatorIntEnable(ADC0_BASE0);    

        
    //
        // Sample the ADC forever.
        //
        
    while(1)
        {       
            
    //
            // Read ADC Value.
            //
            
    ADCSequenceDataGet(ADC0_BASE0ulADC0_Value);

            
    //
            // Calucualte the voltage base on the ADC value.  We will use fixed
            // point with a reolution of 0.01.  Make sure to divide last to avoid
            // dropout.
            //        
            
    ulADC0_Voltage = (ulADC0_Value[0] * 100) / 1023;

            
    //
            // Print out information on the console.  This includes a message
            // prompt, ADC voltage, ADC value, number of digital comparator
            // interrupts that occured, the hysteresis margin, and the screen
            // update rate.
            //
            
    UARTprintf("\f****************************************************
    "
    );                

            
    //
            // Based on the value of the  macro, output the proper warning
            // indication.  Note that the hysteresis condition is met on startup
            // so if the inital ADC volatge was in the mid-band, the interrupt
            // would still trigger once the voltage enters the configured band.
            // We have added a couple extra case statements to handle the inital
            // case.  The 3 determinable inital cases are:
            // (UNDER_0_95V + UNDER_1_95V), (OVER_1_05V + UNDER_1_95V), and
            // (OVER_1_05V + OVER_2_05V).  If the inital case is anything else, we
            // will not be able to tell what the inital message should be displayed
            // using only the digital comparator interrupts.
            //
            
    switch(g_ulDCIntStatus)
            {
                case 
    UNDER_0_95V:
                    
    UARTprintf("WARNING: Voltage under 1V!

    "
    );
                    break;

                case 
    OVER_1_05V:
                    
    UARTprintf("Voltage is between 1V and 2V.

    "
    );
                    break;

                case 
    UNDER_1_95V:
                    
    UARTprintf("Voltage is between 1V and 2V.

    "
    );
                    break;

                case 
    OVER_2_05V:
                    
    UARTprintf("WARNING: Voltage over 2V!

    "
    );
                    break;

                case 
    UNDER_0_95V UNDER_1_95V:
                    
    UARTprintf("WARNING: Voltage under 1V!

    "
    );
                    break;

                case 
    OVER_1_05V UNDER_1_95V:
                    
    UARTprintf("Voltage is between 1V and 2V.

    "
    );
                    break;

                case 
    OVER_1_05V OVER_2_05V:
                    
    UARTprintf("WARNING: Voltage over 2V!

    "
    );
                    break;

                default:
                    
    UARTprintf("Condition unknown.

    "
    );
                    break;
            }

            
    UARTprintf("ADC Volatge    = %3d V  (delta = 0.01)
    "
    ulADC0_Voltage);
            
    UARTprintf("ADC Value      = %d
    "
    ulADC0_Value[0]);
            
    UARTprintf("Number of Ints = %d
    "
    g_ulNumOfInt);
            
    UARTprintf("Hysterisis     = +/- 0.05V
    "
    );
            
    UARTprintf("Update Rate    = 375ms
    "
    );
            
    UARTprintf("****************************************************
    "
    );  

            
    //
            // This function provides a means of generating a constant length
            // delay.  The function delay (in cycles) = 3 * parameter.  Delay
            // 375ms arbitrarily.
            //
            
    SysCtlDelay(SysCtlClockGet() / 8);        
        }
    }




  • Guru 22270 points
    Thank you.

    Were do I send the cheque?

    Now, since the Digital Comparator does send interrupts, then it should be sending triggers as well if I add this:
    ADCComparatorConfigure(ADC0_BASE, 0, ADC_COMP_TRIG_LOW_HALWAYS | ADC_COMP_INT_LOW_HALWAYS);

    If you have code for the PWM trigger by DC Comparator, please post it. I'm sure I'm not the only one who would appreciate it.

    I'm obviously doing something wrong in this setup. Here is how I set up the PWM DC Trigger input so that the PWM shuts down when trigger is received:

    Post edited by: greenja, at: 2010/04/26 17:44

    Post edited by: greenja, at: 2010/04/27 21:11
  • Guru 22270 points
    O.K. Thanks for your help.

    I think I got it, the triggering is taking place! (How dare I question the mighty TI -Luminary)

    The results are not what I was expecting though. The PWM doesn't seem to shut down entirely. I'm still getting a pulse, the frequency is 15x less. What am I still doing wrong?

    Thanks

    Post edited by: greenja, at: 2010/04/27 21:13
  • Guru 22270 points
    Thank you for all your help.

    Post edited by: greenja, at: 2010/04/29 02:26nning.  This
        // function prevents the PWM signals from reaching the pins
        PWMOutputStatePWM_BASEPWM_OUT_0_BIT PWM_OUT_1_BIT PWM_OUT_2_BIT |
                        
    PWM_OUT_3_BITtrue);
         
    //
        // PWM Fault - pin voltage level when fault occurs
        
    PWMOutputFaultLevel(PWM_BASEPWM_OUT_0_BIT PWM_OUT_1_BIT PWM_OUT_2_BIT |
                            
    PWM_OUT_3_BITfalse);
        
    //
        // Enable fault driven output.disables outputs when fault occurs
        
    PWMOutputFault(PWM_BASE,PWM_OUT_0_BIT PWM_OUT_1_BIT PWM_OUT_2_BIT |
                               
    PWM_OUT_3_BITtrue);
        
    //
        // Configure PWM Generators for minimum fault time sensing and the level of
        // the fault pin input.
        //**CAUTION minimum fault time affects how well the PWM shuts down CAUTION**
        // Setting to 32768 is arbitrary right now.  PWM will still trigger when
        // a DC trigger fault is present.  Use with caution.  Use ADC interrupt to
        // shut down the PWM completely. Set the triggers for minimum and maximum
        // voltages and the interrupt for a critical shutdown voltage
        //
        
    PWMGenFaultConfigure(PWM_BASEPWM_GEN_0,32768,PWM_FAULT0_SENSE_HIGH);
        
    PWMGenFaultConfigure(PWM_BASEPWM_GEN_1,32768,PWM_FAULT0_SENSE_HIGH);
        
    //
        // Clear PWM generator Faults.
        
    PWMGenFaultClear(PWM_BASEPWM_GEN_0PWM_FAULT_GROUP_0PWM_FAULT_FAULT0);
        
    PWMGenFaultClear(PWM_BASEPWM_GEN_1PWM_FAULT_GROUP_0PWM_FAULT_FAULT0);
        
    PWMFaultIntClear(PWM_BASE);
        
    PWMFaultIntClearExt(PWM_BASEPWM_INT_FAULT1);
        
    //
        // This register specifies which Digital Comparator triggers from the ADC
        // a used to generate a fault condition on the
        // Set the Fault source to Fault Source 1 to allow for extended fault
        // functions for the PWM peripheral.  This setting configures the PWMnFLTSRC1
        // register.  The PWM_GEN_MODE_FAULT_EXT must be set to all this function to work.
        // Add additional digital comparators as required
         
    HWREG(PWM_BASE PWM_O_0_FLTSRC1)|= PWM_X_FLTSRC1_DCMP0 PWM_X_FLTSRC1_DCMP1 |
                                            
    PWM_X_FLTSRC1_DCMP2;
         
    HWREG(PWM_BASE PWM_O_1_FLTSRC1)|= PWM_X_FLTSRC1_DCMP0 PWM_X_FLTSRC1_DCMP1 |
                                            
    PWM_X_FLTSRC1_DCMP2;
        
    //
        // Enable the PWM generator.
        
    PWMGenEnable(PWM_BASEPWM_GEN_0);
        
    PWMGenEnable(PWM_BASEPWM_GEN_1);
    }

    void
    InitADC
    (void)
    {

        
    // Set the speed of the ADC to 1 million samples per second.
        // ***CAUTION has an effect on how well the PWM shuts down use 1MSPS***
        // 
        
    SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);
            
        
    //    
        // Enable sample sequence 0 with a continuous signal trigger and a priority
        // of zero.  Sequence 0 will sample continuouly until the program is
        // halted.
        //
        
    ADCSequenceConfigure(ADC0_BASE0ADC_TRIGGER_ALWAYS0);

        
    //
        // Configure step 0 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 0 (ADC_CTL_CMP0).  NOTE: When you send the ADC sample to the
        // digital comparator, you will no longer be able to read the raw ADC data
        // on that specific step.  The option is send the data to the FIFOs OR to
        // the digital comparator.  Sequence 0 has 8 programmable steps, sequence 1
        // and 2 have 4 programmable steps, and sequence 3 has 1 programmable step.
        // Since we are using 4 digital comparators and a single sample, we will
        // configure steps 0-4.  For more information on the ADC sequences and
        // steps, reference the datasheet.
        //   
        
    ADCSequenceStepConfigure(ADC0_BASE00ADC_CTL_CH0 ADC_CTL_CMP0);

        
    //
        // Configure step 1 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 1 (ADC_CTL_CMP1).
        //
        
    ADCSequenceStepConfigure(ADC0_BASE01ADC_CTL_CH0 ADC_CTL_CMP1);

        
    //
        // Configure step 2 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 2 (ADC_CTL_CMP2).
        //   
        
    ADCSequenceStepConfigure(ADC0_BASE02ADC_CTL_CH0 ADC_CTL_CMP2);                            

        
    //
        // Configure step 3 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 3 (ADC_CTL_CMP3).
        //       
     //   ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0 | ADC_CTL_CMP3);
        
    ADCSequenceStepConfigure(ADC0_BASE03ADC_CTL_CH0 ADC_CTL_END);

        
    //
        // Configure step 4 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default).  Configure step 4 to be the last conversion
        // on sample sequence 0 (ADC_CTL_END).
        //   
    //    ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH0 | ADC_CTL_END);

        //
        // Since sample sequence 0 is now configured, it must be enabled.
        //
        
    ADCSequenceEnable(ADC0_BASE0);

        
    //
        // Configure the ADC digital comparator.  For this example we will use the
        // "interrupt once hysteresis" mode.  This mode will interrupt only once
        // when the ADC value goes through the mid-band region and then through
        // the low/high region.  Digital comparators 0 and 2 are configured for
        // low-band hysteresis and digital comparators 1 and 3 and configured for
        // high-band hysteresis.  Reference the datasheet for more information on
        // the digital comparator regions.
        //
        
    ADCComparatorConfigure(ADC0_BASE0ADC_COMP_TRIG_HIGH_HALWAYS );
        
    ADCComparatorConfigure(ADC0_BASE1ADC_COMP_TRIG_NONE );
        
    ADCComparatorConfigure(ADC0_BASE2ADC_COMP_TRIG_HIGH_HALWAYS);
        
    ADCComparatorConfigure(ADC0_BASE3ADC_COMP_TRIG_NONE ADC_COMP_INT_NONE );

        
    //
        // Define the low-band and high-band for the digital comparators 0 and 1.
        // The low-band is defined as anything less or equal to ADC_VALUE_0_95V,
        // the mid-band is defined as anything greater than ADC_VALUE_0_95V and
        // less or equal to ADC_VALUE_1_05V, and the high-band is defined as
        // anything greater than ADC_VALUE_1_05V.  Note that the maximum value that
        // the low-band reference or high-band reference can be for the 10-bit ADCs
        // is 1023 and that the low-band reference has to be less than or equal to
        // the high-band reference.
        //
        
    ADCComparatorRegionSet(ADC0_BASE0ADC_VALUE_0_95VADC_VALUE_1_05V);
        
    ADCComparatorRegionSet(ADC0_BASE1ADC_VALUE_0_95VADC_VALUE_1_05V);

        
    //
        // Define the low-band and high-band for the digital comparators 2 and 3.
        // The low-band is defined as anything less or equal to ADC_VALUE_1_95V,
        // the mid-band is defined as anything greater than ADC_VALUE_1_95V and
        // less or equal to ADC_VALUE_2_05V, and the high-band is defined as
        // anything greater than ADC_VALUE_2_05V.  Note that the maximum value that
        // the low-band reference or high-band reference can be for the 10-bit ADCs
        // is 1023 and that the low-band reference has to be less than or equal to
        // the high-band reference.
        //     
        
    ADCComparatorRegionSet(ADC0_BASE2ADC_VALUE_1_95VADC_VALUE_2_05V);
        
    ADCComparatorRegionSet(ADC0_BASE3ADC_VALUE_1_95VADC_VALUE_2_05V);

        
    //
        // Initalize the digital comparator interrupt counter.
        //
        
    g_ulNumOfInt 0;

        
    //
        // Clear all the interrupts and and triggers for digital comparators 0 to
        // 3.  The "true" parameters clear the the trigger and interrupt flags.
        //
        
    ADCComparatorReset(ADC0_BASE0truetrue);
        
    ADCComparatorReset(ADC0_BASE1truetrue);
        
    ADCComparatorReset(ADC0_BASE2truetrue);
        
    ADCComparatorReset(ADC0_BASE3truetrue);

        
    //
        // Enable the digital comparator interrupts on sample sequence 0.
        //
        
    ADCComparatorIntEnable(ADC0_BASE0);    
        
    //
        // Sample the ADC forever.
        //
       

    }
    main (void)
    {    
        
    // Set the clocking to run at 80 MHz (200 MHz / 2.5) using the PLL.  When
        // using the ADC, you must either use the PLL or supply a 16 MHz clock
        // source.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
        
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 SYSCTL_USE_PLL SYSCTL_OSC_MAIN |
                        
    SYSCTL_XTAL_16MHZ);
        
    //
        // Set the clocking of PWM to run at 80 MHz (80 MHz / 1) using the 
         // system clock
        
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
        
    //
        // Enable all peripherals used in this program.
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);        //Enable ADC Controller
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);        //Enable ADC Controller
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);     //Enable UART on PortA
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);    //Enable PortB for PWM
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);    //Enable PortD PWM & LED
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);    //Enable PortE for ADC
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);    //Enable TIMER 1
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM);        //Enable PWM Controller
         //
        // Set Alternative Pin Functions AFSEL
        
    GPIOPinConfigure(GPIO_PG0_PWM0);            //PortG Pin 0 = GEN 0, PWM 0
        
    GPIOPinConfigure(GPIO_PG1_PWM1);            //PortG Pin 1 = GEN 0, PWM 1
        
    GPIOPinConfigure(GPIO_PD2_PWM2);            //PortD Pin 0 = GEN 1, PWM 0
        
    GPIOPinConfigure(GPIO_PD3_PWM3);            //PortD Pin 1 = GEN 1, PWM 1
        
    GPIOPinConfigure(GPIO_PE1_FAULT0);            //PortE Pin 1 = FAULT 0
        //
        // Set Pin Functions
        
    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE,GPIO_PIN_0);            //LED Output
        
    GPIOPinTypeUART(GPIO_PORTA_BASEGPIO_PIN_0 GPIO_PIN_1);    //Rx Tx pins
        
    GPIOPinTypeADC(GPIO_PORTE_BASEGPIO_PIN_7);                //ADC input
        
    GPIOPinTypePWM(GPIO_PORTG_BASEGPIO_PIN_0 GPIO_PIN_1);    //PWM Gen 0 PWM0 PWM1
        
    GPIOPinTypePWM(GPIO_PORTD_BASEGPIO_PIN_2 GPIO_PIN_3);    //PWM Gen 1 PWM1 PWM2
         //
        // Configure Fault Pin Port E Pin 1    with weak pull-down in order to allow for
        // a HIGH value to trigger a fault and shutdown the PWM using FAULT0
        
    GPIOPadConfigSet(GPIO_PORTE_BASEGPIO_PIN_1GPIO_STRENGTH_2MA,
                         
    GPIO_PIN_TYPE_STD_WPD);        
        
    GPIODirModeSet(GPIO_PORTE_BASEGPIO_PIN_1GPIO_DIR_MODE_HW);
        
    //
        // Initialize the UART for console I/O.
        //
        
    UARTStdioInit(0);
        
    //
        // Initialize PWM Generators for full bridge, deadband, Fault Shut down
        //
        
    InitPWM();
        
    //
        // Initialize ADC Digital Comparators and Interrupts
        //
        
    InitADC();
        
    //
        // Enable the ADC sample sequence 0 interrupt on the processor (NVIC).
        //
        
    IntEnable(INT_ADC0);
        
    // 
        // Enable processor interrupts.
         //
        
    IntMasterEnable();
        
    //
        // Since the program constantly prints to the screen, have a 3 second delay
        // before starting so the user can read the setup.  The SysCtlDelay
        // function provides a means of generating a constant length delay.  The
        // function delay (in cycles) = 3 * parameter.
        //    
        
    UARTprintf("Program starting in 3 .
    "
    );
        
    SysCtlDelay(SysCtlClockGet() / 3);
        
    UARTprintf("Program starting in 2 . .
    "
    );
        
    SysCtlDelay(SysCtlClockGet() / 3);
        
    UARTprintf("Program starting in 1 . . .
    "
    );
        
    SysCtlDelay(SysCtlClockGet() / 3);


      
     while(
    1)
        {
            
    // Read Fault status memory location 4002.8808
            //
            
    g_ulDCTrigStatus HWREG(PWM_BASE PWM_O_0_FLTSTAT1);
            
    //
     
            // Read ADC Value.
            //
            
    ADCSequenceDataGet(ADC0_BASE0ulADC0_Value);

            
    //
            // Calucualte the voltage base on the ADC value.  We will use fixed
            // point with a reolution of 0.01.  Make sure to divide last to avoid
            // dropout.
            //        
            
    ulADC0_Voltage = (ulADC0_Value[0] * 10) / 1023;

            
    //
            // Print out information on the console.  This includes a message
            // prompt, ADC voltage, ADC value, number of digital comparator
            // interrupts that occured, the hysteresis margin, and the screen
            // update rate.
            //
            
    UARTprintf("\f****************************************************
    "
    );                

            
    //
            // Based on the value of the  macro, output the proper warning
            // indication.  Note that the hysteresis condition is met on startup
            // so if the inital ADC volatge was in the mid-band, the interrupt
            // would still trigger once the voltage enters the configured band.
            // We have added a couple extra case statements to handle the inital
            // case.  The 3 determinable inital cases are:
            // (UNDER_0_95V + UNDER_1_95V), (OVER_1_05V + UNDER_1_95V), and
            // (OVER_1_05V + OVER_2_05V).  If the inital case is anything else, we
            // will not be able to tell what the inital message should be displayed
            // using the digital comparator interrupts and triggers.
            //
            
    switch(g_ulDCIntStatus)
            {
                case 
    UNDER_0_95V:
                    
    UARTprintf("WARNING: Voltage under 1V!

    "
    );
                    break;

                case 
    OVER_1_05V:
                    
    UARTprintf("Voltage is between 1V and 2V.

    "
    );
                    break;

                case 
    UNDER_1_95V:
                    
    UARTprintf("Voltage is between 1V and 2V.

    "
    );
                    break;

                case 
    OVER_2_05V:
                    
    UARTprintf("WARNING: Voltage over 2V!

    "
    );
                    break;

                case 
    UNDER_0_95V UNDER_1_95V:
                    
    UARTprintf("WARNING: Voltage under 1V!

    "
    );
                    break;

                case 
    OVER_1_05V UNDER_1_95V
  • We are investigating this.
  • Guru 22270 points
    Almost there!!! So close!

    The Trigger does not work consistently as per the following code. In order to see the trigger when the PWM is in FAULT mode by a Digital Comparator, you need to set your scope to 1V/Div and X-Y trigger. Go from trigger to no trigger voltage a few times and you will see that sometimes it is completely off and other times it isn't.

    Although it is always less than 1 volt, it is still triggering the PWM output.

    Here are the changes made to get it to completely turn off about 50% of the time.

    1) The PWM_GEN_MODE_FAULT_MINPER has to be set to the Period-1.
    PWMGenFaultConfigure(PWM_BASE, PWM_GEN_0,Period-1,PWM_FAULT0_SENSE_HIGH);

    2) The PWMGenPeriodSet has to be set to the Period
    PWMGenPeriodSet(PWM_BASE, PWM_GEN_1, Period);

    Where,
    Period = SysCtlClockGet() / TIMER_FREQ;
    and
    #define TIMER_FREQ 40000 // actual frequency for PWM

    Also, the ADC SPEED has to be,
    SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);

    Code:


     // Test program for setting up and using adc
    // and digital comparator

    #include "inc/hw_adc.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "inc/hw_pwm.h"
    #include "utils/uartstdio.h"
    #include "driverlib/adc.h"
    #include "driverlib/debug.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/pwm.h"
    #include "driverlib/gpio.h"
    #include "inc/hw_timer.h"
    #include "driverlib/timer.h"

    // types
    typedef signed int SWord32;
    // variables
    #define TIMER_FREQ         20000         // actual frequency for PWM
    #define PS_VOut_Min     13.5
    #define    PS_VOut_Max        15.0
    #define Battery_Opt        13.8
    #define    Battery_Low        11.0
    #define    Battery_Hi        14.2
    #define Wind_VOut_Min    13.8
    #define Wind_VOut_Max    14.4
    #define ADC_CMP_HiREF    1023


    #define ADC_CMP_LOWREF (PS_VOut_Min*ADC_CMP_HiREF/PS_VOut_Max)    // low reference voltage value for comparator
    #define FLAG_ADC_SAMPLES_AVAIL  0

    //*****************************************************************************
    //
    // Macro definitions for 0.95V, 1.05V, 1.95V, and 2.05V with 10-bit resolution.
    // The calculations can be seen below.
    //
    // 0.95V =>  (2^10 - 1) * (0.95V / 3.0V)      = 324
    // 1.05V => [(2^10 - 1) * (1.05V / 3.0V)] - 1 = 357
    // 1.95V =>  (2^10 - 1) * (1.95V / 3.0V)      = 665
    // 2.05V => [(2^10 - 1) * (2.05V / 3.0V)] - 1 = 698
    //
    // NOTE: Since the high_band is exclusive, we subtract 1 from 1.05V and 2.05V
    // so the digital comparators detect voltages that are greater than or equal
    // rather than just greater.  Since the low-band is inclusive, we leave the
    // 0.95V and 1.95V as is.
    //
    //*****************************************************************************
    #define ADC_VALUE_0_95V 323
    #define ADC_VALUE_1_05V 358
    #define ADC_VALUE_1_95V 664
    #define ADC_VALUE_2_05V 699

    //*****************************************************************************
    //
    // Macro definitions for the warning printouts.  Print a warning message based
    // on what digital comparator sent the interrupt.  UNDER_0_95V is the flag for
    // the digital comparator 0 interrupt, OVER_1_05V is the flag for the digital
    // comparator 1 interrupt, UNDER_1_95V is the flag for the digital comparator
    // 2 interrupt, and OVER_2_05V is the flag for the digital comparator 3
    // interrupt.
    //
    //*****************************************************************************
    #define UNDER_0_95V 0x01
    #define OVER_1_05V  0x02
    #define UNDER_1_95V 0x04
    #define OVER_2_05V  0x08 

    //*****************************************************************************
    // Definition of triggers from comparators. Flags are printed for status

    #define UNDER_0_95V 0x01
    #define OVER_1_05V  0x02
    #define UNDER_1_95V 0x04
    #define OVER_2_05V  0x08 

    //*****************************************************************************
    // Definition of triggers from comparators. Flags are printed for status
    #define CMP_0_TRIG 0x01
    #define CMP_1_TRIG 0x02
    #define CMP_2_TRIG 0x04
    #define CMP_3_TRIG 0x08

    static SWord32 Period;                    // 100% PWM duty value
    unsigned    long    gADC[1];
    unsigned    long    gFlags;    
    unsigned     long     gSeq3DataBuffer[1];    // Incoming ADC sample buffer
    unsigned    long    gDutyCycle;            // Duty cycle for a given PWM frequency
    unsigned    long    gPercentDuty;        // Percent PWM duty cycle

    //*****************************************************************************
    //
    // Global variable to count the number of digital comparator interrupts.  This
    // variable is not needed for the proper operation of the ADC or digital
    // comparators.
    //
    //*****************************************************************************
    unsigned long g_ulNumOfInt;

    //*****************************************************************************
    //
    // Global variable to count the number of digital omparator interrupts and 
    // triggers that have been triggered.  This variable is not needed for the 
    // proper operation of the ADC or digital comparators.
    //
    //*****************************************************************************
    unsigned long g_ulDCIntStatus;
    unsigned long g_ulDCTrigStatus;

    //*****************************************************************************
    // This array is used for storing the data read from the ADC FIFO.  It
    // must be as large as the FIFO for the sequencer in use.  This example
    // uses sequence 0 which has a FIFO depth of 8.  If another sequence
    // was used with a smaller FIFO, then the array size may be changed.
    //
    unsigned long ulADC0_Value[8];
    //
    // This variable is used to calculate the voltage based on the the ADC data
    //
    unsigned long ulADC0_Voltage;
    //*****************************************************************************


    //*****************************************************************************
    //
    // This function sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole
    (void)
    {
        
    //
        // Enable GPIO port A which is used for UART0 pins.
        // TODO: change this to whichever GPIO port you are using.
        //
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

        
    //
        // Configure the pin muxing for UART0 functions on port A0 and A1.
        // This step is not necessary if your part does not support pin muxing.
        // TODO: change this to select the port/pin you are using.
        //   
        
    GPIOPinConfigure(GPIO_PA0_U0RX);
        
    GPIOPinConfigure(GPIO_PA1_U0TX);

        
    //
        // Select the alternate (UART) function for these pins.
        // TODO: change this to select the port/pin you are using.
        //
        
    GPIOPinTypeUART(GPIO_PORTA_BASEGPIO_PIN_0 GPIO_PIN_1);

        
    //
        // Initialize the UART for console I/O.
        //
        
    UARTStdioInit(0);
    }

    //*****************************************************************************
    //
    // This function sets up PWM_GEN_0 and PWM_GEN_1 for a full bridge output with
    // deadband.  Both the PWM generators are set up to shut down on a DC Comparator
    // trigger.  The trigger is ORed with the FAULT0 pin
    //
    //*****************************************************************************
    void
    InitPWM
    (void)
    {
        
    // Set the PWM period TIMER_FREQ is the frequency in Hz (20000 Hz)
        //
        
    Period SysCtlClockGet() / TIMER_FREQ;
        
    gPercentDuty 50;
         
    gDutyCycle Period gPercentDuty/100;
        
    //
        // Configure step 0. Configure PWM Generators 0 and 1. Both PWM_GEN_0 & PWM_GEN_1
        // are configured in the same way.  
        //- The PWM_GEN_MODE_UP_DOWN sets the counting mode for center-aligned overlapping
        //     PWM signals with different duty cycles.
        //- PWM_GEN_MODE_FAULT_EXT allows for extended fault functions by setting the
        //     FLTSCR bit in the PWMnCTL register.  This allows the extended FAULT0 conditions
        //     to be ORed with the Fault Pins. Set to PWM_GEN_MODE_FAULT_LEGACY if extended
        //     fault conditions are not supported.
        //-    PWM_GEN_MODE_FAULT_UNLATCHED causes faults to be held only as long as the fault
        //    condition is present.  Setting to PWM_GEN_MODE_FAULT_LATCHED latches the faults
        //    until cleared
        //- PWM_GEN_MODE_FAULT_MINPER sets the minimum time that a fault signal is held 
        //    after being triggered.  PWM_GEN_MODE_FAULT_NO_MINPER disables this function
        //**CAUTION minimum time causes PWM to retrigger during DC_Comp fault condition**
        //
           
    PWMGenConfigure(PWM_BASEPWM_GEN_0PWM_GEN_MODE_UP_DOWN PWM_GEN_MODE_FAULT_EXT |
                          
    PWM_GEN_MODE_FAULT_LATCHED PWM_GEN_MODE_FAULT_MINPER);
           
    PWMGenConfigure(PWM_BASEPWM_GEN_1PWM_GEN_MODE_UP_DOWN PWM_GEN_MODE_FAULT_EXT |
                        
    PWM_GEN_MODE_FAULT_LATCHED PWM_GEN_MODE_FAULT_MINPER);
        
    //
        // Set the PWM period for both PWM Generators 0 and 1. The period is 50 usec
        // or frequency of 20 KHz, In this case PWM Clock = SysCtlClock/2 (4220/2), 
        // TIMER_FREQ = 20 000
        //
        
    PWMGenPeriodSet(PWM_BASEPWM_GEN_1Period);
        
    PWMGenPeriodSet(PWM_BASEPWM_GEN_0Period);

        
    //
        // Set dead time for both PWM Generators.
        // Configure half-bridge mode with 1 us deadtime
        
    PWMDeadBandEnable(PWM_BASEPWM_GEN_055);                            
           
    PWMDeadBandEnable(PWM_BASEPWM_GEN_155);

        
    //
        // Disable selected outputs when fault is triggered.  A true will 
        // allow the PWM to continue to function during a triggered fault A false
        // prevents the PWM signal from reaching the selected pins
           
    PWMOutputFaultPWM_BASEPWM_OUT_0_BIT PWM_OUT_1_BIT PWM_OUT_2_BIT 
                        
    PWM_OUT_3_BITfalse);
        
    //
        // Synchronise generator 0 and 1 timebases
        
    PWMSyncTimeBase(PWM_BASEPWM_GEN_0_BIT PWM_GEN_1_BIT);
        
        
    // Set up ADC trigger when PWM counter matches PWM_B down value
        
    PWMGenIntTrigEnable(PWM_BASEPWM_GEN_1PWM_TR_CNT_BD);

        
    //
        // Set PWM to a duty cycle by changing gPercentDuty
        
    PWMPulseWidthSet(PWM_BASEPWM_OUT_0gDutyCycle);
        
    PWMPulseWidthSet(PWM_BASEPWM_OUT_2gDutyCycle);

        
    //
        // Enable the PWM output signals.  A true places the selected PWM outputs
        // in the active state.  A false places the outputs in an inactive state
        // The PWM peripheral is still enabled and PWM counters are running.  This
        // function prevents the PWM signals from reaching the pins
        
    PWMOutputStatePWM_BASEPWM_OUT_0_BIT PWM_OUT_1_BIT PWM_OUT_2_BIT |
                        
    PWM_OUT_3_BITtrue);
         
    //
        // PWM Fault - pin voltage level when fault occurs
        
    PWMOutputFaultLevel(PWM_BASEPWM_OUT_0_BIT PWM_OUT_1_BIT PWM_OUT_2_BIT |
                            
    PWM_OUT_3_BITfalse);
        
    //
        // Enable fault driven output.disables outputs when fault occurs
        
    PWMOutputFault(PWM_BASE,PWM_OUT_0_BIT PWM_OUT_1_BIT PWM_OUT_2_BIT |
                               
    PWM_OUT_3_BITtrue);
        
    //
        // Configure PWM Generators for minimum fault time sensing and the level of
        // the fault pin input.
        //**CAUTION minimum fault time affects how well the PWM shuts down CAUTION**
        //  PWM will still trigger when
        // a DC trigger fault is present.  Use with caution.  Use ADC interrupt to
        // shut down the PWM completely. Set the triggers for minimum and maximum
        // voltages and the interrupt for a critical shutdown voltage
        //
        
    PWMGenFaultConfigure(PWM_BASEPWM_GEN_0,Period-1,PWM_FAULT0_SENSE_HIGH);
        
    PWMGenFaultConfigure(PWM_BASEPWM_GEN_1,Period-1,PWM_FAULT0_SENSE_HIGH);
        
    //
        // Clear PWM generator Faults.
        
    PWMGenFaultClear(PWM_BASEPWM_GEN_0PWM_FAULT_GROUP_0PWM_FAULT_FAULT0);
        
    PWMGenFaultClear(PWM_BASEPWM_GEN_1PWM_FAULT_GROUP_0PWM_FAULT_FAULT0);
        
    PWMFaultIntClear(PWM_BASE);
        
    PWMFaultIntClearExt(PWM_BASEPWM_INT_FAULT1);
        
    //
        // This register specifies which Digital Comparator triggers from the ADC
        // a used to generate a fault condition on the
        // Set the Fault source to Fault Source 1 to allow for extended fault
        // functions for the PWM peripheral.  This setting configures the PWMnFLTSRC1
        // register.  The PWM_GEN_MODE_FAULT_EXT must be set to all this function to work.
        // Add additional digital comparators as required
         
    HWREG(PWM_BASE PWM_O_0_FLTSRC1)|= PWM_X_FLTSRC1_DCMP0 PWM_X_FLTSRC1_DCMP1 |
                                            
    PWM_X_FLTSRC1_DCMP2;
         
    HWREG(PWM_BASE PWM_O_1_FLTSRC1)|= PWM_X_FLTSRC1_DCMP0 PWM_X_FLTSRC1_DCMP1 |
                                            
    PWM_X_FLTSRC1_DCMP2;
        
    //
        // Enable the PWM generator.
        
    PWMGenEnable(PWM_BASEPWM_GEN_0);
        
    PWMGenEnable(PWM_BASEPWM_GEN_1);
    }

    void
    InitADC
    (void)
    {

        
    // Set the speed of the ADC to 1 million samples per second.
        // 
        
    SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS);
            
        
    //    
        // Enable sample sequence 0 with a continuous signal trigger and a priority
        // of zero.  Sequence 0 will sample continuouly until the program is
        // halted.
        //
        
    ADCSequenceConfigure(ADC0_BASE0ADC_TRIGGER_ALWAYS0);

        
    //
        // Configure step 0 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 0 (ADC_CTL_CMP0).  NOTE: When you send the ADC sample to the
        // digital comparator, you will no longer be able to read the raw ADC data
        // on that specific step.  The option is send the data to the FIFOs OR to
        // the digital comparator.  Sequence 0 has 8 programmable steps, sequence 1
        // and 2 have 4 programmable steps, and sequence 3 has 1 programmable step.
        // Since we are using 4 digital comparators and a single sample, we will
        // configure steps 0-4.  For more information on the ADC sequences and
        // steps, reference the datasheet.
        //   
        
    ADCSequenceStepConfigure(ADC0_BASE00ADC_CTL_CH0 ADC_CTL_CMP0);

        
    //
        // Configure step 1 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 1 (ADC_CTL_CMP1).
        //
        
    ADCSequenceStepConfigure(ADC0_BASE01ADC_CTL_CH0 ADC_CTL_CMP1);

        
    //
        // Configure step 2 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 2 (ADC_CTL_CMP2).
        //   
        
    ADCSequenceStepConfigure(ADC0_BASE02ADC_CTL_CH0 ADC_CTL_CMP2);                            

        
    //
        // Configure step 3 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default) and send the ADC sample to digital
        // comparator 3 (ADC_CTL_CMP3).
        //       
        
    ADCSequenceStepConfigure(ADC0_BASE03ADC_CTL_CH0 ADC_CTL_CMP3);

        
    //
        // Configure step 4 on sequence 0.  Sample channel 10 (ADC_CTL_CH10) in
        // single-ended mode (default).  Configure step 4 to be the last conversion
        // on sample sequence 0 (ADC_CTL_END).
        //   
        
    ADCSequenceStepConfigure(ADC0_BASE04ADC_CTL_CH0 ADC_CTL_END);

        
    //
        // Since sample sequence 0 is now configured, it must be enabled.
        //
        
    ADCSequenceEnable(ADC0_BASE0);

        
    //
        // Configure the ADC digital comparator.  For this example we will use the
        // "interrupt once hysteresis" mode.  This mode will interrupt only once
        // when the ADC value goes through the mid-band region and then through
        // the low/high region.  Digital comparators 0 and 2 are configured for
        // low-band hysteresis and digital comparators 1 and 3 and configured for
        // high-band hysteresis.  Reference the datasheet for more information on
        // the digital comparator regions.
        //
        
    ADCComparatorConfigure(ADC0_BASE0ADC_COMP_TRIG_HIGH_HALWAYS |ADC_COMP_INT_LOW_HONCE );
        
    ADCComparatorConfigure(ADC0_BASE1ADC_COMP_TRIG_NONE ADC_COMP_INT_HIGH_HONCE );
        
    ADCComparatorConfigure(ADC0_BASE2ADC_COMP_TRIG_HIGH_HALWAYS |ADC_COMP_INT_LOW_HONCE);
        
    ADCComparatorConfigure(ADC0_BASE3ADC_COMP_TRIG_NONE ADC_COMP_INT_HIGH_HONCE);

        
    //
        // Define the low-band and high-band for the digital comparators 0 and 1.
        // The low-band is defined as anything less or equal to ADC_VALUE_0_95V,
        // the mid-band is defined as anything greater than ADC_VALUE_0_95V and
        // less or equal to ADC_VALUE_1_05V, and the high-band is defined as
        // anything greater than ADC_VALUE_1_05V.  Note that the maximum value that
        // the low-band reference or high-band reference can be for the 10-bit ADCs
        // is 1023 and that the low-band reference has to be less than or equal to
        // the high-band reference.
        //
        
    ADCComparatorRegionSet(ADC0_BASE0ADC_VALUE_0_95VADC_VALUE_1_05V);
        
    ADCComparatorRegionSet(ADC0_BASE1ADC_VALUE_0_95VADC_VALUE_1_05V);

        
    //
        // Define the low-band and high-band for the digital comparators 2 and 3.
        // The low-band is defined as anything less or equal to ADC_VALUE_1_95V,
        // the mid-band is defined as anything greater than ADC_VALUE_1_95V and
        // less or equal to ADC_VALUE_2_05V, and the high-band is defined as
        // anything greater than ADC_VALUE_2_05V.  Note that the maximum value that
        // the low-band reference or high-band reference can be for the 10-bit ADCs
        // is 1023 and that the low-band reference has to be less than or equal to
        // the high-band reference.
        //     
        
    ADCComparatorRegionSet(ADC0_BASE2ADC_VALUE_1_95VADC_VALUE_2_05V);
        
    ADCComparatorRegionSet(ADC0_BASE3ADC_VALUE_1_95VADC_VALUE_2_05V);

        
    //
        // Initalize the digital comparator interrupt counter.
        //
        
    g_ulNumOfInt 0;

        
    //
        // Clear all the interrupts and and triggers for digital comparators 0 to
        // 3.  The "true" parameters clear the the trigger and interrupt flags.
        //
        
    ADCComparatorReset(ADC0_BASE0truetrue);
        
    ADCComparatorReset(ADC0_BASE1truetrue);
        
    ADCComparatorReset(ADC0_BASE2truetrue);
        
    ADCComparatorReset(ADC0_BASE3truetrue);

        
    //
        // Enable the digital comparator interrupts on sample sequence 0.
        //
        
    ADCComparatorIntEnable(ADC0_BASE0);    
        
    //
        // Sample the ADC forever.
        //
       

    }
    main (void)
    {    
        
    // Set the clocking to run at 80 MHz (200 MHz / 2.5) using the PLL.  When
        // using the ADC, you must either use the PLL or supply a 16 MHz clock
        // source.
        // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
        // crystal on your board.
        //
        
    SysCtlClockSet(SYSCTL_SYSDIV_2_5 SYSCTL_USE_PLL SYSCTL_OSC_MAIN |
                        
    SYSCTL_XTAL_16MHZ);
        
    //
        // Set the clocking of PWM to run at 80 MHz (80 MHz / 1) using the 
         // system clock
        
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
        
    //
        // Enable all peripherals used in this program.
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);        //Enable ADC Controller
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);        //Enable ADC Controller
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);     //Enable UART on PortA
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);    //Enable PortB for PWM
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);    //Enable PortD PWM & LED
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);    //Enable PortE for ADC
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);    //Enable TIMER 1
        
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM);        //Enable PWM Controller
         //
        // Set Alternative Pin Functions AFSEL
        
    GPIOPinConfigure(GPIO_PG0_PWM0);            //PortG Pin 0 = GEN 0, PWM 0
        
    GPIOPinConfigure(GPIO_PG1_PWM1);            //PortG Pin 1 = GEN 0, PWM 1
        
    GPIOPinConfigure(GPIO_PD2_PWM2);            //PortD Pin 0 = GEN 1, PWM 0
        
    GPIOPinConfigure(GPIO_PD3_PWM3);            //PortD Pin 1 = GEN 1, PWM 1
        
    GPIOPinConfigure(GPIO_PE1_FAULT0);            //PortE Pin 1 = FAULT 0
        //
        // Set Pin Functions
        
    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE,GPIO_PIN_0);            //LED Output
        
    GPIOPinTypeUART(GPIO_PORTA_BASEGPIO_PIN_0 GPIO_PIN_1);    //Rx Tx pins
        
    GPIOPinTypeADC(GPIO_PORTE_BASEGPIO_PIN_7);                //ADC input
        
    GPIOPinTypePWM(GPIO_PORTG_BASEGPIO_PIN_0 GPIO_PIN_1);    //PWM Gen 0 PWM0 PWM1
        
    GPIOPinTypePWM(GPIO_PORTD_BASEGPIO_PIN_2 GPIO_PIN_3);    //PWM Gen 1 PWM1 PWM2
         //
        // Configure Fault Pin Port E Pin 1    with weak pull-down in order to allow for
        // a HIGH value to trigger a fault and shutdown the PWM using FAULT0
        
    GPIOPadConfigSet(GPIO_PORTE_BASEGPIO_PIN_1GPIO_STRENGTH_2MA,
                         
    GPIO_PIN_TYPE_STD_WPD);        
        
    GPIODirModeSet(GPIO_PORTE_BASEGPIO_PIN_1GPIO_DIR_MODE_HW);
        
    //
        // Initialize the UART for console I/O.
        //
        
    UARTStdioInit(0);
        
    //
        // Initialize PWM Generators for full bridge, deadband, Fault Shut down
        //
        
    InitPWM();
        
    //
        // Initialize ADC Digital Comparators and Interrupts
        //
        
    InitADC();
        
    //
        // Enable the ADC sample sequence 0 interrupt on the processor (NVIC).
        //
        
    IntEnable(INT_ADC0);
        
    // 
        // Enable processor interrupts.
         //
        
    IntMasterEnable();
        
    //
        // Enable the ADC sample sequence 0 interrupt on the processor (NVIC).
        //
        
    IntEnable(INT_ADC0);
        
    //
        // Since the program constantly prints to the screen, have a 3 second delay
        // before starting so the user can read the setup.  The SysCtlDelay
        // function provides a means of generating a constant length delay.  The
        // function delay (in cycles) = 3 * parameter.
        //    
        
    UARTprintf("Program starting in 3 .
    "
    );
        
    SysCtlDelay(SysCtlClockGet() / 3);
        
    UARTprintf("Program starting in 2 . .
    "
    );
        
    SysCtlDelay(SysCtlClockGet() / 3);
        
    UARTprintf("Program starting in 1 . . .
    "
    );
        
    SysCtlDelay(SysCtlClockGet() / 3);


      
     while(
    1)
        {
            
    // Read Fault status memory location 4002.8808
            //
            
    g_ulDCTrigStatus HWREG(PWM_BASE PWM_O_0_FLTSTAT1);
            
    //
     
            // Read ADC Value.
            //
            
    ADCSequenceDataGet(ADC0_BASE0ulADC0_Value);

            
    //
            // Calucualte the voltage base on the ADC value.  We will use fixed
            // point with a reolution of 0.01.  Make sure to divide last to avoid
            // dropout.
            //        
            
    ulADC0_Voltage = (ulADC0_Value[0] * 10) / 1023;

            
    //
            // Print out information on the console.  This includes a message
            // prompt, ADC voltage, ADC value, number of digital comparator
            // interrupts that occured, the hysteresis margin, and the screen
            // update rate.
            //
            
    UARTprintf("\f****************************************************
    "
    );                

            
    //
            // Based on the value of the  macro, output the proper warning
            // indication.  Note that the hysteresis condition is met on startup
            // so if the inital ADC volatge was in the mid-band, the interrupt
            // would still trigger once the voltage enters the configured band.
            // We have added a couple extra case statements to handle the inital
            // case.  The 3 determinable inital cases are:
            // (UNDER_0_95V + UNDER_1_95V), (OVER_1_05V + UNDER_1_95V), and
            // (OVER_1_05V + OVER_2_05V).  If the inital case is anything else, we
            // will not be able to tell what the inital message should be displayed
            // using the digital comparator interrupts and triggers.
            //
            
    switch(g_ulDCIntStatus)
            {
                case 
    UNDER_0_95V:
                    
    UARTprintf("WARNING: Voltage under 1V!

    "
    );
                    break;

                case 
    OVER_1_05V:
                    
    UARTprintf("Voltage is between 1V and 2V.

    "
    );
                    break;

                case 
    UNDER_1_95V:
                    
    UARTprintf("Voltage is between 1V and 2V.

    "
    );
                    break;

                case 

    This thread has been locked.

    If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.