How to refresh the value collected by ADC(DMA mode + FREERTOS)

Important: posts that do not use this template will be ignored or closed.

Before posting

  • Get familiar with Markdown to format and structure your post
  • Be sure to update lvgl from the latest version from the master branch.
  • Be sure you have checked the relevant part of the documentation. We will not respond in detail to posts where you haven’t read the relevant documentation.
  • If applicable use the Simulator to eliminate hardware related issues.

Delete this section if you read and applied the mentioned points.

Description

What MCU/Processor/Board and compiler are you using?

STM32

What LVGL version are you using?

V7.0

What do you want to achieve?

Refreshes the value collected by the ADC

What have you tried so far?

in HAL_ADC_ConvCpltCallback inside release

Code to reproduce

Add a code snippet which can run in the simulator. It should contain only the relevant code that compiles without errors when separated from your main code base.

The code block(s) should be formatted like:

/*You code here*/

HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* ADC)
{
osSemaphoreRelease();
}

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

Trigger a FreeRTOS task that calls the appropriate LVGL method. Cube typically calls its callbacks from an interrupt handler so you can’t use LVGL methods inside a Cube callback.

Hi, W-wonderfu. Could you provide the code that waits the semaphore to update the value in a thread?

Hello

My English is not very good.Are there any examples?This allows me to understand the workflow more intuitively.

osSemaphoreid bsem;
osSemaphoreDef(bsem);
bsem = osSemaphoreCreate (osSemaphore(bsem), 1);
osSemaphoreWait (bsem, osWaitForever);

Ok, thank you. I see that you are waiting for the semaphore at least once. But this is not enough. To answer your question, we need to know at least:

  • How did you get the value from the ADC?
  • How did you display this value?

Check if the ADC value is measured and changed according to the input signal and sent to the GUI correctly. If you need help with these issues, you need to provide the code responsible for these parts.

Hello: Trouble you
float get_batt(void)
{
if(!adc1Sem)
{
osSemaphoreDef(adc1Sem);
adc1Sem = osSemaphoreCreate(osSemaphore(adc1Sem),1);
osSemaphoreWait(adc1Sem,osWaiteForever);
}
HAL_ADC_Start_DMA(&adc1,(uint32_t )&adc1_buff[0],1);
Vbattery_ADC_Value = adc1_value[0];
Vbattery_V = (float)(14.0f
Vbattery_ADC_Value)/12285.0f;
return Vbattery_V;
}

void HAL_ADC_ConvCallback(ADC_HandleTypeDef* AdcHandle)
{
if(AdcHandle == &adc1 && adc1Sem)
osSemaphoreRelease(adc1Sem);
}

void HAL_ADC_ErrorCallback(ADC_HandleTypeDef* AdcHandle)
{
if(AdcHandle == &adc1 && adc1Sem)
osSemaphoreRelease(adc1Sem);
}

static lv_obj_t * labelBatt;
float Vbattery_Value = 0.0;

static void lv_test_cell(lv_task_t * task)
{
Vbattery_Value = get_batt();

const char * battSymbol[] = {
LV_SYMBOL_BATTERY_EMPTY,
LV_SYMBOL_BATTERY_1,
LV_SYMBOL_BATTERY_2,
LV_SYMBOL_BATTERY_3,
LV_SYMBOL_BATTERY_FULL
};
int symIndx = fmap(Vbattery_Value,3.2f,4.2f,0,__Sizeof( battSymbol));
lv_label_set_text(labelBatt,battSymbol[symIndx ]);
}

static void lv_test_cell_interface(void)
{

static lv_style_t style1;
lv_style_init(&style1);
labelBatt = lv_label_create(lv_scr_act(),NULL);
lv_obj_add_style(labelBatt,lv_LABEL_PART_MAIN,&style1);
lv_obj_align(labelBatt ,NULL,LV_ALIGN_CENTER,50,-50);

lv_task_t * task_date;
task_date = lv_task_create(lv_test_cell,1000,LV_TASK_PRIO_HIGH,NULL);
lv_test_cell(task_date);

}

void test_batt(void)
{
xSemaphoreTake(SYSMutexHandle,osWaiteForever);
lv_test_cell_interface();
xSemaphoreGive(SYSMutexHandle);
}

int mian(void)
{

lv_init();
lv_port_disp_init();
test_batt();

}

void PeriodicTask(void const * argument)
{
for(;:wink:
{
lv_tick_inc(5);
lv_task_handler();
osDelay(5);
}
}

Hello:
I’m sorry to trouble you.The code has been sent to you

Your code is missing FreeRTOS initialization, and semaphores only start working after you call osKernelStart (). Also I can’t find where your PriodicTask () is called periodically. There are some other semantic issues with your code and I can’t imagine how you compiled it :thinking: .

PS Why Mian :slight_smile: ?

I just showed you the main code.

My code is on another computer.I’ll upload all the code tomorrow.

Ok, if infrastructure code is fine you have a logical bug here: waiting for the semaphore forever while ADC conversion is not started. osSemaphoreWait() should stand after HAL_ADC_Start_DMA() as far as I understand.

SYS_adc.c (1.3 KB) test.c (1.6 KB) freertos.c (2.0 KB) main.c (16.0 KB) ossemaphorewait();This semaphore is not used in the same way as a mutex(xSemaphoreTake).,. 50 meters too large for the whole project, some files will be uploaded

Check out line 26 in SYS_adc.c: you are overriding the type of the uint32_t pointer to the uint16_t pointer. This leads to memory corruption.

,in use uint16_t adc_value[];I added cast(uint32_t).
HAL_ADC_Start_DMA(&adc1,(uint32_t *)&adc1_value[0],1);

HAL_ADC_Start_DMA() will write 4 bytes to the variable that only contains 2 bytes. You only have 2 bytes in memory for adc1_value[0] and next 2 bytes is something that we don’t know. These 2 bytes can be another critical variable or empty space.

Hello
I’m using an on-chip ADC, 12 bits. 2 bytes With enough。That shouldn’t be the problem. I use LV Task Create ();It should be circular.But My simulation is not looping(I’m going to give it a fixed value(Vbattery_Value)).I think that’s the problem. ADC that’s also problematic,Should we solve it first LV Task Create ();

Hi. 2 bytes will be enough to store data from the ADC, but you have an interface HAL_ADC_Start_DMA () that requires a 4 byte location in memory, and you only give a 2 byte location, suppressing the compiler warning. This may not be the cause of your current problem, but it may cause your software to malfunction. And this can be easily fixed by changing the type adc1_buff to uint32_t.

Check the code in main.c: 131: inside LVGL_test () you are calling xSemaphoreTake(), but the FreeRTOS kernel hasn’t started yet.

Hello:
I also found this problem,I have already corrected.Question about ADC. I modified it as you suggested,But still no.I’m trying to find out why.
void PeriodicTask(void const * argument)
{
LVGL_test();
for(;:wink:
{

}
}