为什么 HAL_UART_Transmit_DMA 无法正确传输我的 adc_buf 数组?

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

使用:

  • STM32CubeMX版本:6.10.0
  • STM32CubeIDE版本:1.13.1
  • Nucleo-F767ZI

我正在开展一个 DIY 示波器项目,我想尝试尽可能提高 STM32F7 系列 ADC 的速度和精度。我正在阅读有关该主题的文献并不断获得见解,我逐渐了解到,使用 DMA 管道是一种有效的数据流传输方式,且不会导致 CPU 陷入困境。我能够成功地用相对准确的 12 位 ADC 值填充缓冲区,并且在调试时可以看到它们被填充到 DMA 寄存器中。当我尝试将 adc_buf 数组传输到我设备的板载 uart 端口 huart3 时,出现了问题。

我已经验证了uart3口可以传输buffer。我发送了一个字符数组,

char msg[] = "\n\rThe cow jumped over the moon\r\n";
HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 0xFFFF);
。请参阅下面的输出,了解腻子窗口上的结果。我还尝试使用 for 循环来使用 snprintf 并分配另一个缓冲区来传输,但这既不起作用也不符合项目的目标。我猜 for 循环不是最有效的方法。我看到其他答案表明初始化 DMA 和 UART 的顺序很重要,但最新的 CubeMX 更新似乎已经解决了这个问题。这不是问题。

/* Initialize all configured peripherals */  
MX_GPIO_Init();
MX_DMA_Init();
MX_USART3_UART_Init();
MX_ADC1_Init();
MX_ETH_Init();
MX_USB_OTG_FS_PCD_Init();

简单来说,我的工作流程是这样的:

/* USER CODE BEGIN PD */
#define ADC_BUF_LEN 8
/* USER CODE END PD */

/* USER CODE BEGIN PV */
uint16_t adc_buf[ADC_BUF_LEN];
/* USER CODE END PV */

int main(void)
{
    /* USER CODE BEGIN 1 */
    char msg[] = "\n\rThe cow jumped over the moon\r\n";
    char buffer[50];
    /* USER CODE END 1 */
    //...Inits
    /* USER CODE BEGIN 2 */
    HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 0xFFFF); // transmits cow message fine
    HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_buf, ADC_BUF_LEN);
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1) {
        // wait for huart3 instance to write?
        while (READ_BIT(huart3.Instance->ISR, USART_ISR_TC)==0){asm("nop");}
        HAL_UART_Transmit_DMA(&huart3, (uint8_t*)adc_buf, ADC_BUF_LEN * sizeof(uint8_t));
        // Must start ADC->DMA process again or values don't seem to be read continuously
        HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_buf, ADC_BUF_LEN);
    }
    /* USER CODE END WHILE */
}

我希望我的结果看起来像这样:

The cow jumped over the moon
4095
4095
4095
4092

等等。但我得到的却是垃圾:

/
The cow jumped over the moon
▒;▒▒Z*▒S=▒Z*▒S=▒P▒▒=KR2▒]▒▒RgG7▒]▒▒RgG7▒
▒▒
}▒:▒▒
     ▒▒▒4▒▒
           ▒▒▒4▒▒▒▒▒▒1▒▒▒▒
▒1▒▒▒▒

再往下,我尝试编写一些中断,它们似乎触发得很好。

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc) {
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

当我在这里设置断点时,这些中断似乎运行正常。我已经在 usart3 外设上设置了全局中断,并确保 DMA、usart3 和 ADC1 设置为正常而不是循环。 DMA 和 USART 似乎独立运行良好,只是不能一起运行。

感谢您的宝贵时间。

c embedded stm32 hal stm32cubeide
1个回答
0
投票
  • HAL_UART_Transmit_DMA(&huart3, (uint8_t*)adc_buf ...
    它不会打印 ADC 读数的 ASCII 表示形式。您需要将
    uint16_t
    数字转换为字符串,然后传输该字符串。该转换必须与 ADC DMA 同步。

  • 检测 DMA 事务结束并不容易。 TC 标志并不意味着 DMA 事务已完成。您需要检查 DMA 标志,然后检查 TC。然后你就可以忍受另一个转变了。

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