简体   繁体   English

在队列 FreeRTOS 中传递变量

[英]Passing Variables in a Queue FreeRTOS

On the STM32F103 I measure the voltage and display the result on the LCD.在 STM32F103 上,我测量电压并将结果显示在 LCD 上。 The result is displayed, the code is as follows:显示结果,代码如下:

HAL_ADCEx_InjectedStart(&hadc1);
HAL_ADC_PollForConversion(&hadc1,100);
u0= 180 - (180*(3 - ((float)HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_1))*3/4096));      
sprintf(str,"%.1fV",u0);
LCD_String(str);
HAL_ADCEx_InjectedStop(&hadc1);

I wanted to separate the operations into tasks, that is, we measure in the StartADC task and pass it through the queue to the StartLCDTask task, which displays the result on the display.我想将操作分离为任务,即我们在 StartADC 任务中测量并通过队列将其传递给 StartLCDTask 任务,该任务将结果显示在显示器上。 But instead of the measured value, the display shows 0V.但显示器显示的不是测量值,而是 0V。 Where did I go wrong?我哪里做错了?

/* Definitions for UARTQueue*/
osMessageQueueId_t UARTQueueHandle 
/* creation of UARTQueue*/
UARTQueueHandle = osMessageQueueNew (8, sizeof(uint8_t), &UARTQueue_attributes);

typedef struct {
   char Buf;
} QUEUE_t;

void StartADC(void *argument)
{
   char u0;
  for(;;)
  {
   HAL_ADCEx_InjectedStart(&hadc1);
   HAL_ADC_PollForConversion(&hadc1,100);
   u0= 180 - (180*(3 - ((float)HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_1))*3/4096));      
   osMessageQueuePut(UARTQueueHandle, &u0, 0, osWaitForever);
   HAL_ADCEx_InjectedStop(&hadc1);
   osDelay(200);
  }
}

void StartLCDTask(void *argument)
{
   QUEUE_t msg;
   char str[9];
  for(;;)
  {
   osMessageQueueGet(UARTQueueHandle, &msg, 0, osWaitForever);
   sprintf(str,"%.0fV", (double)msg.Buf);
   LCD_SetPos(0,0);
   LCD_String(str);
  }
}

In your first example, you do:在您的第一个示例中,您执行以下操作:

sprintf(str,"%.1fV",u0);

This implies u0 is float .这意味着u0float If it's not, then this is UB (undefined behavior)如果不是,那么这是 UB(未定义的行为)

But, in your second example, u0 is char u0;但是,在您的第二个示例中, u0char u0; You are truncating a floating point value to a char .您正在将浮点值截断为char The fractional part will be lost.小数部分将丢失。

Then, you enqueue it and send it.然后,您将其排入队列并发送。

And, you're "cheating" a bit:而且,你有点“作弊”:

  1. You're sending a char but receiving a QUEUE_t .您正在发送char但收到QUEUE_t
  2. The queue is initialized with a msg_size of sizeof(uint8_t) instead of sizeof(QUEUE_t)队列使用sizeof(uint8_t)而不是sizeof(QUEUE_t)msg_size初始化

This "happens" to work but it's sloppy.这“碰巧”有效,但很草率。 It's not very extensible.它不是很可扩展。 It would break if the QUEUE_t struct was extended and needed multiple values to be sent.如果QUEUE_t结构被扩展并且需要发送多个值,它将中断。 We'll need to fix that below.我们需要在下面解决这个问题。

The recipient StartLCDTask does:收件人StartLCDTask会:

sprintf(str, "%.0fV", (double) msg.Buf);

The two sprintf are not equivalent.这两个sprintf等价。


Now that you have two tasks you have the choice of which task/function does the calculation/conversion of the raw ADC value (which is a uint32_t ).现在您有两个任务,您可以选择哪个任务/函数来计算/转换原始 ADC 值(即uint32_t )。 In either case, we'll need to change QUEUE_t to handle the value.无论哪种情况,我们都需要更改QUEUE_t来处理该值。

Here is a version that enqueues the raw value and has the display task do the conversion.这是一个将原始值排入队列并让显示任务进行转换的版本。

/* Definitions for UARTQueue*/
osMessageQueueId_t UARTQueueHandle;

typedef struct {
    uint32_t adcraw;
} QUEUE_t;

/* creation of UARTQueue*/
void
init_queue(void)
{
    UARTQueueHandle = osMessageQueueNew(8, sizeof(QUEUE_t),
        &UARTQueue_attributes);
}

void
StartADC(void *argument)
{
    QUEUE_t msg;

    for (;;) {
        HAL_ADCEx_InjectedStart(&hadc1);
        HAL_ADC_PollForConversion(&hadc1, 100);

        msg.adcraw = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1);

        osMessageQueuePut(UARTQueueHandle, &msg, 0, osWaitForever);

        HAL_ADCEx_InjectedStop(&hadc1);

        osDelay(200);
    }
}

void
StartLCDTask(void *argument)
{
    QUEUE_t msg;
    float_t u0;
    char str[20];

    for (;;) {
        osMessageQueueGet(UARTQueueHandle, &msg, 0, osWaitForever);

        u0 = msg.adcraw;
        u0 = 180 - (180 * (3 - u0 * 3 / 4096));

        sprintf(str, "%.0fV", u0);

        LCD_SetPos(0, 0);
        LCD_String(str);
    }
}

UPDATE:更新:

Although I noted this before, I didn't realize the possible impact.虽然我之前注意到了这一点,但我没有意识到可能的影响。

In the single task code, the format is:在单任务代码中,格式为:

"%.1fV"

But, this got changed for the multiple task code:但是,这已针对多任务代码进行了更改:

"%.0fV"

I suspect that this is a typo.我怀疑这是一个错字。 I think the format should be the same in both cases.我认为这两种情况的格式应该是一样的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM