ST意法半导体
直播中

kmno4

12年用户 965经验值
私信 关注
[问答]

如何解决FreeRTOS数据采集上采样率不一致的问题呢?

我是 Freertos 的新手。我有一个关于两个线程的练习项目。一个线程用于AD7606的数据采集,另一个线程用于labview中uart的数据传输。不幸的是,当我在 LabVIEW 中显示从线程 2 获取的数据时,我发现它会丢失数据或采样率不一致。我该如何解决这个问题?  
到目前为止,我不知道解决方案是否是 freertos 中的定时器中断。
请给我提示或一些我可以参考的教程。有需要请指教。 非常感谢你。
  • void StartDefaultTask(void const * argument)
  • {
  •   /* USER CODE BEGIN 5 */
  •   /* Infinite loop */
  •   for(;;)
  •   {
  •          xSemaphoreTake(DeliverHandle,portMAX_DELAY);
  •          // START read AD7607
  •          Read_AI();
  •          float value = (float)aio_data.c2_values_in[0];
  •          // END read AD7607
  •          // Send data in MyQueue
  •           xQueueSendToBack(MyQueue, (void*)&value, (tickType_t)1);
  •           xSemaphoreGive(DeliverHandle);
  •           osDelay(20);
  •         }
  • }
  •   /* USER CODE END 5 */
  • /* USER CODE BEGIN Header_StartTask02 */
  • /**
  • * @brief Function implementing the myTask02 thread.
  • * @param argument: Not used
  • * @retval None
  • */
  • /* USER CODE END Header_StartTask02 */
  • void StartTask02(void const * argument)
  • {
  •   /* USER CODE BEGIN StartTask02 */
  •   /* Infinite loop */
  •   int messagesWaiting,j;
  •         float value_f;
  •         uint32_t value_u32;
  •   for(;;)
  •   {
  •          //START test queue number
  •          messagesWaiting = uxQueueMessagesWaiting(MyQueue);
  •          xSemaphoreTake(DeliverHandle, portMAX_DELAY);
  •          if ( messagesWaiting >= 8 ) {
  •                   for(j = 0; j < messagesWaiting; j++){
  •                           xQueueReceive(MyQueue, &value_f, (TickType_t)1);
  •                           value_u32 = Convert_float_To_U32(value_f);
  •                          Covert_U32_To_4U8(value_u32, Tx_data+4*j);
  •                         }
  •                         HAL_UART_Transmit(&huart2, Tx_data, 32, 1000);
  •     }
  •                 osDelay(20);
  •                 xSemaphoreGive(DeliverHandle);
  •                 }
  •   /* USER CODE END StartTask02 */
  • }

回帖(1)

杜永强

2023-1-5 14:39:53
AD7606 具有 SPI 或并行输出。我假设您正在以设定的时间间隔从 SPI 或 GPIO 引脚读取最近的转换。如果您需要精确的采样率,请根据您的间隔设置硬件 TIM 计时器,并使用 TIM 中断读取 GPIO 引脚,或启动 SPI 移位周期。
首先,如果要保证时延,你的采集任务必须运行在FreeRTOS配置的最高优先级。由于任务上下文开销和运行优先级高于 ADC 任务的任何任务,您仍然需要针对一些抖动进行调整。您没有提及哪些中断处于活动状态,或者您是否使用 AD7606 中断请求对 ADC 进行采样。软定时器必须考虑中断延迟(即 SYSTICK 或您用于 RTOS 时基的任何定时器)。中断服务例程中的回调(ST 程序员的最爱)可能是低延迟的杀手。
另请记住,在 daq 任务中读取 ADC 样本所花费的时间会影响您的时间间隔。如果您有自旋锁(即持续轮询状态标志),您的获取时间可能是不确定的(即不可预测的)。
如果您使用的是 FreeRTOS V9 或更高版本,您可能希望查看任务通知而不是常规信号量。只要仅在两个任务之间,通知就需要较少的处理时间。
您的信号量被配置为互斥锁(互斥),但这似乎不是必需的。输出队列本身可以起到同步两个任务的作用。将您的 MyQueue 大小设置为 8(您的主机)消息大小?_并将 xQueueSend 延迟设置为零。这将丢弃到达太快而无法在每个间隔速率 8 个样本的一条输出消息中发送的样本。您不需要在输出任务中调用任何 osDelay,因为它是由队列中样本的到达驱动的事件。假设 daq 任务以正确的速率采样,您的输出消息将完全填满输出队列。  
这还假设输出消息从队列中读取样本的速度快于转换率(如果速度不快,您将遇到溢出情况)。如果您将 MyQueue 限制为样本的一个主机消息大小,您可以抢占较慢的输出任务并转换新样本,同时仍在处理先前的样本集。搜索流数据的“双缓冲区”概念,因为它是处理您的要求的常用方法。
如果您的输出队列增长速度快于您向主机发送数据的速度,会发生什么情况?看来您的采集任务最终将在您的采样间隔之外的很长一段时间内被阻止。您将在丢失数据的主机上遇到周期性的丢失。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分