Hi there, i hope someone could get back to me with this problem as soon as possible because im supposed to finish up my school's final year project and have it presented in less than 24hours time.
I've came up with this program being able to display waveform input from function generator and calculates the breathing rate per minute and displaying it within a tap on the pushbutton of the LCD screen.
However, im experiencing a problem with my CLEAR button.
It clears well for the first time, does its job.
However, in next few times, it gave me a problem which was my LCD's widgets went missing after being tapped on the second, third time.
LCD Display: Kentec Display EB-LM4F120-L35
Microcontroller: Tiva C Series TM4C123G
//************************************************************************************** /* * This program is written by student of Biomedical Engineering (Diploma) in * Ngee Ann Polytechnic, Tan Michelle (Student Number: S10128640) as part of * the requirement of the final year project - Asthma Sensing Mat. * * Supervisor: Mr. Johnny Chee (chj) * * This main.c comprises of ADC, peak detection, displaying of waveforms ranging from * 0v-3.3v, recording waveform data, displaying recorded waveform data, * split screen display function as well as the clearing of recorded/running wavefroms. */ //************************************************************************************** #include <stdint.h> #include <stdbool.h> #include "driverlib/fpu.h" //floating point unit #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/debug.h" #include "driverlib/gpio.h" #include "driverlib/adc.h" #include "driverlib/sysctl.h" #include "grlib/grlib.h" #include "driverlib/timer.h" #include "driverlib/interrupt.h" #include "inc/tm4c123gh6pm.h" #include "Kentec320x240x16_ssd2119_8bit.h" #include "grlib/widget.h" #include "grlib/canvas.h" #include "grlib/pushbutton.h" #include "touch.h" #include "conversion.h" #include "Wave.h" #include "displayDraw.h" #include "ClrScreen.h" #include "widgetPaint.h" #include "timer.h" tContext sContext; //initialize tContext tRectangle sRect; //initialize tRectangle extern tCanvasWidget g_sBackground; extern tPushButtonWidget g_sSingleBtn; extern tPushButtonWidget g_sDualBtn; extern tPushButtonWidget g_sClearBtn; extern tPushButtonWidget g_sMainBtn; extern tPushButtonWidget g_sDisplayBtn; extern tPushButtonWidget g_sStartBtn; extern tPushButtonWidget g_sStopBtn; extern tPushButtonWidget g_sBreathingRateDisplayBtn; uint32_t count=1; //to count the number 'x-values' uint32_t ADCDisplayFlag; // determines where the breathing will be displayed in both screens uint32_t DisplayFlag; // determines where the waveform and recording breath per minute will be displayed in DUAL screen uint32_t clearFlag;// determines which screen to be cleared uint32_t startFlag; // determines which screen to start waveform plotting uint32_t ui32ADCOutput; //declare ADC Output uint32_t ui32ADCOutputArr[240]; //to store ADC values for plotting of graph uint32_t ui32ADCOutput1; uint32_t ui32ADC0Value[4]; //array of ADC values for averaging signal uint32_t ui32BreathingRateArr[1]; uint32_t ui32BreathingRate; uint32_t ui32Period; uint32_t x=1; //initial value of X which will be used to plot the X-axis of graph uint32_t y; //variable Y for graph plotting of Y-axis uint32_t z; //variable Z for graph plotting of Y-axis from the recorded array (ui32ADCOutputArr[240]) uint32_t GraphPlotFlag; //to set flag for enabling graph plotting and stopping it 1 uint32_t uiPkPkInterval; uint32_t ui32LongValue; uint8_t aui8DisplayValue[5]; // Array to store 5 byte uint8_t aui8DisplayValue2[5];// Array to store 5 byte int iPkPkAmplitude; unsigned char ucCycleDetected; #ifdef DEBUG void__error__(char *pcFilename, uint32_t ulLine){ } #endif void SingleButtonPress(tWidget *pWidget); void DualButtonPress(tWidget *pWidget); void ClearButtonPress(tWidget *pWidget); void MainButtonPress(tWidget *pWidget); void DisplayButtonPress(tWidget *pWidget); void StartButtonPress(tWidget *pWidget); void StopButtonPress(tWidget *pWidget); void BreathingRateButtonPress(tWidget *pWidget); Canvas(g_sHeading, &g_sBackground, 0, &g_sSingleBtn, &g_sKentec320x240x16_SSD2119, 65, 50, 180, 20, (CANVAS_STYLE_FILL | CANVAS_STYLE_OUTLINE | CANVAS_STYLE_TEXT ), ClrBlack, ClrWhite, ClrWhite, g_psFontCm12, "MENU SELECTION:", 0, 0); Canvas(g_sBackground, WIDGET_ROOT, 0, &g_sHeading, &g_sKentec320x240x16_SSD2119, 0, 23, 320, (240 - 100), CANVAS_STYLE_FILL, ClrBlack, 0, 0, 0, 0, 0, 0); RectangularButton(g_sSingleBtn, &g_sHeading, &g_sDualBtn, 0, &g_sKentec320x240x16_SSD2119, 240, 180, 70, 25, (PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT | PB_STYLE_FILL), ClrBlack, ClrWhite, ClrTurquoise, ClrTurquoise, g_psFontCmss14b, "SINGLE", 0, 0, 0, 0, SingleButtonPress); RectangularButton(g_sDualBtn, &g_sHeading, &g_sMainBtn, 0, &g_sKentec320x240x16_SSD2119, 240, 210, 70, 25, (PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT | PB_STYLE_FILL), ClrBlack, ClrWhite, ClrTurquoise, ClrTurquoise, g_psFontCmss14b, "DUAL", 0, 0, 0, 0, DualButtonPress); RectangularButton(g_sMainBtn, &g_sHeading, &g_sDisplayBtn, 0, &g_sKentec320x240x16_SSD2119, 0, 180, 70, 25, (PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT | PB_STYLE_FILL), ClrBlack, ClrWhite, ClrYellow, ClrYellow, g_psFontCmss14b, "MENU", 0, 0, 0, 0, MainButtonPress); RectangularButton(g_sDisplayBtn, &g_sHeading, &g_sClearBtn, 0, &g_sKentec320x240x16_SSD2119, 0, 210, 70, 25, (PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT | PB_STYLE_FILL), ClrBlack, ClrWhite, ClrYellow, ClrYellow, g_psFontCmss14b, "DISPLAY", 0, 0, 0, 0, DisplayButtonPress); RectangularButton(g_sClearBtn, &g_sHeading, &g_sBreathingRateDisplayBtn, 0, &g_sKentec320x240x16_SSD2119, 80, 180, 70, 25, (PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT | PB_STYLE_FILL), ClrBlack, ClrWhite, ClrOrange, ClrOrange, g_psFontCmss14b, "CLEAR", 0, 0, 0, 0, ClearButtonPress); RectangularButton(g_sBreathingRateDisplayBtn, &g_sHeading, &g_sStartBtn, 0, &g_sKentec320x240x16_SSD2119, 80, 210, 70, 25, (PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT | PB_STYLE_FILL), ClrBlack, ClrWhite, ClrBlue, ClrBlue, g_psFontCmss14b, "BR/MIN", 0, 0, 0, 0, BreathingRateButtonPress); RectangularButton(g_sStartBtn, &g_sHeading, &g_sStopBtn, 0, &g_sKentec320x240x16_SSD2119, 160, 180, 70, 25, (PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT | PB_STYLE_FILL), ClrBlack, ClrWhite, ClrLime, ClrLime, g_psFontCmss14b, "START", 0, 0, 0, 0, StartButtonPress); RectangularButton(g_sStopBtn, &g_sHeading, 0, 0, &g_sKentec320x240x16_SSD2119, 160, 210, 70, 25, (PB_STYLE_OUTLINE | PB_STYLE_TEXT_OPAQUE | PB_STYLE_TEXT | PB_STYLE_FILL), ClrBlack, ClrWhite, ClrRed, ClrRed, g_psFontCmss14b, "STOP", 0, 0, 0, 0, StopButtonPress); void DisplayButtonPress(tWidget *pWidget){ //displaying of recorded data (ui32ADCOutputArr[x]) if(DisplayFlag==2){ while (x < count){ x++; z=(150-(ui32ADCOutputArr[x]/17)); GrContextForegroundSet(&sContext, ClrPink); GrPixelDraw(&sContext, x, z); ui32LongValue = convertIntHextoLongBCD(ui32BreathingRateArr[0]); convertIntToAsciiHex4(ui32LongValue, &aui8DisplayValue2[0]); GrContextForegroundSet(&sContext, ClrWhite); GrContextFontSet(&sContext, &g_sFontCmss12b); GrStringDraw(&sContext, (const char*) aui8DisplayValue2, -1, 250, 6, 0); GrContextForegroundSet(&sContext, ClrWhite); GrContextFontSet(&sContext, &g_sFontCmss12b); GrStringDraw(&sContext, "br/min", -1, 280, 6, 0); } } } void BreathingRateButtonPress(tWidget *pWidget){ //displaying of ADC value of PK-PK amplitude (iPkPkAmplitude) if(ADCDisplayFlag==1){ ui32BreathingRate = ((60/(uiPkPkInterval*0.02))*2); ui32LongValue = convertIntHextoLongBCD(ui32BreathingRate); convertIntToAsciiHex4(ui32LongValue, &aui8DisplayValue[0]); ui32BreathingRateArr[0]=ui32BreathingRate; GrContextForegroundSet(&sContext, ClrWhite); GrContextFontSet(&sContext, &g_sFontCmss12b); GrStringDraw(&sContext, (const char*) aui8DisplayValue, -1, 240, 6, 0); GrContextForegroundSet(&sContext, ClrWhite); GrContextFontSet(&sContext, &g_sFontCmss12b); GrStringDraw(&sContext, "br/min", -1, 270, 6, 0); } else if (ADCDisplayFlag==2){ ui32BreathingRate = ((60/(uiPkPkInterval*0.02))*2); ui32LongValue = convertIntHextoLongBCD(ui32BreathingRate); convertIntToAsciiHex4(ui32LongValue, &aui8DisplayValue[0]); GrContextForegroundSet(&sContext, ClrWhite); GrContextFontSet(&sContext, &g_sFontCmss12b); GrStringDraw(&sContext, (const char*) aui8DisplayValue, -1, 240, 100, 0); GrContextForegroundSet(&sContext, ClrWhite); GrContextFontSet(&sContext, &g_sFontCmss12b); GrStringDraw(&sContext, "br/min", -1, 270, 100, 0); } } void StartButtonPress(tWidget *pWidget){ //start graph plotting in SPLIT (1) display if(startFlag==1){ x=1; GraphPlotFlag = 1; } else if(startFlag==2){ x=1; GraphPlotFlag=2; } } void ClearButtonPress(tWidget *pWidget){ //clear plotted graph as well as recorded data (ui32ADCOutputArr[x]) in SPLIT (1) display if(clearFlag==1){ DrawSplit1Display(); x=1; AddPaintWidget(); while (x<count){ x++; ui32ADCOutputArr[x] = 0; } } else if (clearFlag==2){ DrawSplit2Display(); x=1; AddPaintWidget(); while (x<count){ x++; ui32ADCOutputArr[x] = 0; } } } void StopButtonPress(tWidget *pWidget){ //stops graph plotting in both SPLIT (1) display and SPLIT (2) display GraphPlotFlag = 0; x=1; } void SingleButtonPress(tWidget *pWidget){ //splits screen into 1 display (current running waveform) ADCDisplayFlag=1; clearFlag=1; startFlag=1; DrawSplit1Display(); AddPaintWidget(); } void DualButtonPress(tWidget *pWidget){ //splits screen into 2 display (current running waveform and recorded waveform) ADCDisplayFlag=2; clearFlag=2; startFlag=2; DisplayFlag=2; DrawSplit2Display(); AddPaintWidget(); } void MainButtonPress(tWidget *pWidget){ //returns to menu selection screen clearFlag=0; startFlag=0; ADCDisplayFlag=0; ClrScreen(); WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sBackground); WidgetPaint(WIDGET_ROOT); AddPaintWidget(); } int main(void){ Wave_init(); //initialise to detect peak and trough Wave_setGapThreshold(25); //set hysteresis threshold for peak & trough detection SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ); //Configure the system clock to run at 40MHz SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //enable port E SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); //enable port F GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3); GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3); //the pins connected to the LEDs as outputs SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //configures Timer 0 as a 32-bit timer in periodic mode TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); ui32Period = (SysCtlClockGet() / 50) / 2; //50 interrupts a second, 0.02s per interrupt TimerLoadSet(TIMER0_BASE, TIMER_A, ui32Period -1); ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0); ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END); TouchScreenInit(); //initialise touchscreen function file TouchScreenCallbackSet(WidgetPointerMessage); WidgetAdd(WIDGET_ROOT, (tWidget *)&g_sBackground); WidgetPaint(WIDGET_ROOT); Kentec320x240x16_SSD2119Init(); //initialise Kentec Display file GrContextInit(&sContext, &g_sKentec320x240x16_SSD2119); ClrScreen(); GrFlush(&sContext); ClrScreen(); IntEnable(INT_TIMER0A); TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); //enabling timer 0 subtimer A IntMasterEnable(); TimerEnable(TIMER0_BASE, TIMER_A); while(1){ WidgetMessageQueueProcess(); } } void Timer0Inthandler(void){ timer(); if(GraphPlotFlag == 1){ x++; if(x>319){ GraphPlotFlag = 0; //stops graph plotting } else{ count++; // count number of 'X-values' y=(215-(ui32ADCOutput/17)); //Y-axis pixel value ui32ADCOutputArr[x]= ui32ADCOutput; GrContextForegroundSet(&sContext, ClrGoldenrod); GrPixelDraw(&sContext, x, y); } } else if (GraphPlotFlag == 2){ x++; if(x>319){ ClearDualDisplay(); x=1;//restart plotting to beginning of x-axis } else{ ui32ADCOutput1=(ui32ADCOutput/2); //to minimize the waveform to fit into the smaller display range set y=(190-(ui32ADCOutput1/17)); //Y-axis pixel value GrContextForegroundSet(&sContext, ClrGoldenrod); GrPixelDraw(&sContext, x, y); } } ucCycleDetected=Wave_detectPkTr(ui32ADCOutput); //1=Peak detected if (ucCycleDetected>0){ //1=peak detected; 2=trough detected if(ucCycleDetected ==1){ GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x02); } else if(ucCycleDetected == 2){ GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0x00); //Cycle deteced, Red LED will be turned on } uiPkPkInterval=Wave_getPkPkInterval(); } }
void AddPaintWidget(void){ //adding & painting of widgets
WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sDisplayBtn); WidgetPaint((tWidget *)&g_sDisplayBtn); WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sMainBtn); WidgetPaint((tWidget *)&g_sMainBtn); WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sDualBtn); WidgetPaint((tWidget *)&g_sDualBtn); WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sSingleBtn); WidgetPaint((tWidget *)&g_sSingleBtn); WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sStartBtn); WidgetPaint((tWidget *)&g_sStartBtn); WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sClearBtn); WidgetPaint((tWidget *)&g_sClearBtn); WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sStopBtn); WidgetPaint((tWidget *)&g_sStopBtn); WidgetAdd((tWidget *)&g_sHeading, (tWidget *)&g_sBreathingRateDisplayBtn); WidgetPaint((tWidget *)&g_sBreathingRateDisplayBtn); }
void DrawSplit1Display(void){ //Drawing of SPLIT (1) Display on LCD ClrScreen(); sRect.i16XMin = 1; sRect.i16YMin = 1; sRect.i16XMax = 318; sRect.i16YMax = 238; GrContextForegroundSet(&sContext, ClrWhite); GrContextFontSet(&sContext, &g_sFontCmss16b); GrStringDraw(&sContext, "Current", -1, 10, 2, 0); sRect.i16XMin = 158; sRect.i16YMin = 1; sRect.i16XMax = 318; sRect.i16YMax = 21; GrContextForegroundSet(&sContext, ClrWhite); GrContextFontSet(&sContext, &g_sFontCmss12b); GrStringDraw(&sContext, "BREATHING", -1, 160, 1, 0); GrStringDraw(&sContext, "RATE:", -1, 180, 11, 0); GrRectDraw(&sContext, &sRect); sRect.i16XMin = 0; sRect.i16YMin = 170; sRect.i16XMax = 319; sRect.i16YMax = 170; GrContextForegroundSet(&sContext , ClrHotPink); GrRectDraw(&sContext, &sRect); }
Those are my codes and the codes for my different functions, hoping someone can help me with this problem.
Thankyou!