为什么HAL会减慢UART传输速度?

问题描述 投票:0回答:1

我正在使用Nucleo板STML073Rz来采样频率为1khz的正弦波。我的STMCubeIDE配置如下。

系统时钟:HSE 8Mhz

蒂默2

预标量:8-1, 实际收益:100-1, 定时器溢出频率:10000Hz, 触发事件选择:更新事件

ADC

Prescalar:同步时钟模式除以2, ADC分辨率:8位分辨率, 数据对齐:右, 外部触发转换源:Timer2触发输出事件

UART2

时钟:系统时钟8Mhz, 波特率:115200, 字长:8位, 溢出:禁用

我的要求是以10000Hz的采样频率对进入ADC6通道的正弦波进行采样。我使用以下逻辑将样本发送到网关。

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    endOfConversion = 1;
    HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}

HAL_TIM_Base_Start(&htim2);
HAL_ADC_Start_IT(&hadc);

numsamples=4500;
txcount = 0;
endOfConversion=0;
do
{
    if(endOfConversion==1)
    {
        adc_value = HAL_ADC_GetValue(&hadc);
        HAL_UART_Transmit(&huart1, &adc_value, 1, 10);
        endOfConversion=0;
        txcount+=1;
    }
}while(txcount<=numsamples);
HAL_ADC_Stop_IT(&hadc);

这里只展示逻辑,不展示全部代码。在网关处,我绘制了样本的 fft,它显示峰值为 2000Hz,而不是 1000Hz。

经过一些调试,我发现 HAL 延迟了 1 个字节的传输,因此只有交替样本被发送到网关。

为什么HAL UART延迟传输?

embedded stm32 nucleo stm
1个回答
0
投票

可以说这是事件的时间线,其中

|
标记了 10000Hz(100us)的间隔。

Timer2 和 ADC 的配置方式,每次转换时都会有一个 TIM2 和一个 ADC 触发器。从数据表来看,相对于 100us 间隔,ADC 转换速度非常快 (0.4uz),我们可以假装 ADC 转换回调与图中的触发器同时发生。

|------|------|-----|-----|------|
^Tim2 IRQ / ADC trigger / HAL_ADC_ConvCpltCallback

就像 @the-busybee 的评论提到的那样,UART 速度是相关的。 UART 配置为轮询模式,因此这也相关。

HAL_UART_Transmit(&huart1, &adc_value, 1, 10);
通过 115200Hz 波特率线路发送 10 个字节,大约需要 100us(这是来自 10/115200 的粗略幅度猜测)。

之前带有定时器和 ADC 事件的时间线发生在后台的硬件中。同时,在主

do {} while
循环中运行的代码同时在前台软件中发生。如果 UART 传输时间超过 100us,那么以下是发生情况的可能时间表:

|------|------|-----|-----|------|
^Tim2 IRQ / ADC trigger / HAL_ADC_ConvCpltCallback

|......Auuuuuuur....Auuuuuur......A
  |    | |     ^ The main loop resets the conversion flag with `endOfConversion=0`
  |    | ^ Time spent transmitting the read value over the UART
  |    ^ main loop reads ADC value HAL_ADC_GetValue(&hadc);
  ^ The main while loop is waiting for `if(endOfConversion==1)` to be true

当下一个 irq 发生时,UART 传输仍在进行中,但由于

endOfConversion
在 UART 完成后重置,因此循环必须等待另一个 TIM2 IRQ 来读取并传输另一个样本。

我认为你可以通过在 UART 传输之前重置

endOfConversion
来解决这个问题,以取出所有这些“。”上面的软件时间线中的状态如下:

    if(endOfConversion==1)
    {
        adc_value = HAL_ADC_GetValue(&hadc);
        endOfConversion=0;       
        HAL_UART_Transmit(&huart1, &adc_value, 1, 10);
        txcount+=1;
    }

如果此解决方案导致有趣的采样率问题,那么您需要执行一些更奇特的操作,例如缓存数据以便稍后传输,或使用更高波特率的 UART(如果可能)。

© www.soinside.com 2019 - 2024. All rights reserved.