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.

TM4C123GH6PM: ADC sampling time limited by LCD screen

Part Number: TM4C123GH6PM

I am using the Tiva C LaunchPad and Kentec boosterpack.  My original goal is to take readings from 2 ADC's, compare them, and flash an LED when I get a pin interrupt if ADC1>ADC2.  I have that code and circuitry working fine.

Now I am moving on to trying to display values on the screen of each of the ACD's.  I figured I'd start small and just try to get an image to show up on the Kentec screen while the rest of the circuit is functioning.  After messing around for a while I finally got an image to pop up on the screen along with all the other parts of the program functioning properly.  However, I discovered that I need to have the ADC sampling be <2 samples/second or the image will not load properly.  As I increase the samples/second less and less of the image will load.

For the real screen I am just going to have basic text, buttons, and inputs.  But I'm concerned that the processor might not be able to handle the screen as well as the functions I need it to do in order to do the "main" job of the controller.

Should this processor be able to handle both a small screen (maybe up to 5") as well as basic motor control with 10 samples/sec and outputting a signal at up to 120Hz?

  • Are you trying to update the display with each ADC conversion? I suspect the problem is not the time to do the ADC conversions, but rather the time to update the display. The trick is to have the screen update done in the background. This might be a good application for an RTOS. Also, the GRLIB (graphic driver library) was built for portability and readability. It is not the most efficient, particularly when you only want to update only a portion of the screen.
  • After doing some research I believe you are correct that RTOS is probably the way to go long term. However, I am trying to develop a bare bones digital motor controller to replace a low-end analog controller. It doesn't have to be pretty or ultra-fast. Simple text and buttons will do as long as the motor runs at the correct speed/torque.

    At this point I am just displaying one image in main and that's it. I ran into this problem with sampling and would like some guidance as far as if I'm wasting my time pursuing this route.

    Most importantly I need to output a pulse on pin up to 1,200/sec and read the motor feedback at some decent rate, say 10 samples/sec. Updating the screen can be slow, maybe 1/sec?

    If you had to ballpark would you say I could get away with running at 80MHz and doing all of that? Or would you say definately go to an RTOS based system and not even bother with a non-OS system? Or could I just have another chip that handles the screens and let the main processor just worry about the motor control?

    Thank you
  • //******************************************************************************
    //                          Declare Header Files
    #include <stdint.h>
    #include <stdbool.h>
    #include "grlib/grlib.h"
    #include "inc/tm4c123gh6pm.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/gpio.h"
    #include "driverlib/timer.h"
    #include "driverlib/debug.h"
    #include "driverlib/adc.h"
    #include "driverlib/fpu.h"
    #include "driverlib/rom.h"
    #include "grlib/grlib.h"
    #include "initialize.h"
    #include "Sample.h"
    #include "ZeroCrossing.h"
    #include "SCR_firing.h"
    #include "Kentec320x240x16_ssd2119_8bit.h"
    #include "touch.h"
    
    
    
    
    
    
    //******************************************************************************
    
    //******************************************************************************
    //                          Declare Functions
    
    void Sample(void);
    int Control(void);
    int Manipulation(void);
    void ZeroCrossing(void);
    void Timer0(void);
    void ClrScreen(void);
    //******************************************************************************
    
    //******************************************************************************
    //                          Declare/Initialize Variables
    uint32_t Theta=0;
    extern const uint8_t g_pui8Image_DSI_logo[];
    tContext sContext;
    tRectangle sRect;
    
    
    //******************************************************************************
    
    
    int main(void)
    {
        //Initialize system clock to 50MHz
        SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    
        Kentec320x240x16_SSD2119Init();
        Initialize();   //Initialization routine
        GrContextInit(&sContext, &g_sKentec320x240x16_SSD2119);
        ClrScreen();
    
        GrImageDraw(&sContext, g_pui8Image_DSI_logo, 0, 0);
        GrFlush(&sContext);
    
    
    
        //Run an infinite loop and let interrupts do the hard work
        while(1)
        {
        }
    }
    
    
    //*********************************************************************************
    //***************************   Function Declarations   ***************************
    //*********************************************************************************
    
    
    
    void ClrScreen()
    {
    sRect.i16XMin = 0;
    sRect.i16YMin = 0;
    sRect.i16XMax = 319;
    sRect.i16YMax = 239;
    GrContextForegroundSet(&sContext, ClrBlack);
    GrRectFill(&sContext, &sRect);
    GrFlush(&sContext);
    }
    
    //*********************************************************************************
    //                                  Sample() function
    
    #define SYSCYC_DEG 1852     //The number of system clock cycles/degree of firing angle
                                //Results from:
                                //40MHz (system clock freq)
                                //--------------------------
                                //[60 (line freq)*2(we are only interested in half cycles)*180(number of degrees in 1 half cycle)
                                //= 1851.8 cycles/degree of firing angle in 1/2 of the line frequency sine wave
    
    uint32_t FireTime=0;
    int32_t  Error=0;
    uint32_t Reference=0;
    uint32_t VelocityFB=0;
    
    
    
    
    void Sample(void){
    
        //clear the ADC interrupt status flag
        ADCIntClear(ADC0_BASE, 0);
        ADCIntClear(ADC1_BASE, 0);
    
        //trigger the ADC
        ADCProcessorTrigger(ADC0_BASE, 0);
        //SysCtlDelay(3);
        ADCProcessorTrigger(ADC1_BASE, 0);
        //SysCtlDelay(3);
    
        //Get sample and put it into buffer
        ADCSequenceDataGet(ADC0_BASE, 0, &Reference);
        ADCSequenceDataGet(ADC1_BASE, 0, &VelocityFB);
    
        //Calculate error
        Error=(Reference-VelocityFB);
    
        //If error is greater than 0 then we calculate Theta
        if(Error>0){
            //  Calculate the firing time by getting the % error and multiplying that by 180
            //  to get the number of degrees we need to fire at.  Then we multiply by the
            //  cycles/degree to get the firing time that is shoved into Timer0.
            //  The equation looks strange because we are dealing with integers so the division
            //  will lead to truncation and thus is needs to happen last.
            FireTime= (SYSCYC_DEG*(4095-Error)*180)/4095;
        }
        //If error is less than 0 then we set firing time to 333,361 which is 1 above the maximum value
        //  of the equation above for FireTime
        else
        {   FireTime=333361;
    
        }
    
    }
    //**********************************************************************
    

  • It does not make sense that if you are not updating the display except at the beginning, that the image will not load properly. I suggest you profile your interrupt routines. Perhaps they are taking much longer than you expect. Driving an unused GPIO line high when in a specific routine and then looking at the signal on a scope should give you a good idea about the relative amount of time you spend in each routine.
  • It turns out I was using half the code from the Tiva Workshop and half of my own code so I wasn't clearing interrupts for the ADC sampling. This is what was causing the processor to lock in a loop for sampling both the ADC's without doing anything else.

    After fixing this problem I was able to easily display characters to the screen.

    Thanks for informing me about the benefits of RTOS. Eventually I'll switch but for now I've got the screen working with the main program.