提问人:vishnu m c 提问时间:10/19/2023 最后编辑:Issylinvishnu m c 更新时间:10/23/2023 访问量:77
为什么 HAL 会减慢 UART 传输速度。?
Why HAL slow down the UART transmission.?
问:
我正在使用 Nucleo 板 STML073Rz 对频率为 1khz 的正弦波进行采样。我的STMCubeIDE配置如下。
系统频率 : HSE 8Mhz
蒂默尔2
预标量:8-1, 比分 : 100-1, 定时器过流频率:10000Hz, 触发事件选择:更新事件
模数转换器
预标量:同步时钟模式除以 2, ADC分辨率:8bit分辨率, 数据对齐方式:右, 外部触发转换源:Timer2触发输出事件
串口2
时钟:sysclock 8Mhz, 波特率 : 115200, 字长:8bit, 溢出:禁用
我的要求是对正弦波进行采样,该正弦波以 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 会延迟传输?
答:
假设这是标记 10000Hz (100us) 间隔的事件时间线。|
Timer2 和 ADC 的配置方式是,每次转换时都会触发 TIM2 和 ADC。从数据手册中可以看出,ADC转换相对于100us间隔非常快(0.4uz),因此我们可以假设ADC转换回调与图中的触发同时发生。
|------|------|-----|-----|------|
^Tim2 IRQ / ADC trigger / HAL_ADC_ConvCpltCallback
就像@the-busybee的评论所提到的,UART速度是相关的。UART配置为轮询模式,因此这也很重要。 在 115200Hz 波特率线上发送 10 位(不是 ~bytes~,感谢 @pmacfarlane),这将需要大约 ~100us(这是来自 10/115200 的粗略幅度猜测)。HAL_UART_Transmit(&huart1, &adc_value, 1, 10);
上一个带有定时器和ADC事件的时间线发生在后台的硬件中。同时,在主循环中运行的代码同时在前台的软件中发生。如果 UART 传输时间超过 100 微秒,那么以下是正在发生的事情的可能时间表:do {} while
|------|------|-----|-----|------|
^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 传输仍在进行中,但由于 UART 完成后被重置,因此环路必须等待另一个 TIM2 IRQ 读取和传输另一个样本。endOfConversion
我认为您可以通过在 UART 传输之前重置来解决这个问题,以在上面的软件时间线中取出所有这些“.”状态,如下所示:endOfConversion
if(endOfConversion==1)
{
adc_value = HAL_ADC_GetValue(&hadc);
endOfConversion=0;
HAL_UART_Transmit(&huart1, &adc_value, 1, 10);
txcount+=1;
}
如果此解决方案导致有趣的采样率问题,那么您需要做一些更高级的事情,例如缓存数据以供以后传输,或者使用更高的波特率 UART(如果可能)。
这就是我所说的缓存数据,以便在您有足够的内存时稍后传输的意思。
numsamples=4500;
txcount = 0;
endOfConversion=0;
uint16_t samples[4500];
// Measure all of the samples
do
{
if(endOfConversion==1)
{
adc_value = HAL_ADC_GetValue(&hadc);
samples[txcount] = adc_value;
endOfConversion=0;
txcount+=1;
}
}while(txcount<=numsamples);
HAL_ADC_Stop_IT(&hadc);
// Transmit the samples
for(int i = 0; i < numsamples; i++){
adc_value = samples[i]
HAL_UART_Transmit(&huart1, &adc_value, 1, 10);
}
评论
HAL_UART_Transmit(&huart1, &adc_value, 1, 8)
评论