STM32F746NG-Discovery:程序在第一次读取 ADC 后卡住

STM32F746NG-Discovery : Program Stuck after first ADC read

我正在尝试从连接到我的电路板的 arduino 扩展板读取 ADC 值。 Arduino shield 是一个已经过测试的定制板,它会在检测到传感器和手指之间的接触时发送数据。

我使用 STM32Cube IDE 开发了一个程序,以便能够读取这些值并定期显示。该程序基于 STemWin 示例。不幸的是,在第一次从程序中读取后,该值没有更新,其余功能不再起作用。程序卡住了。如果我评论定期从 ADC 读取数据的代码,那么程序可以正常工作。

这是我的主要内容:

/* Configure the MPU attributes */
    MPU_Config();

    /* Invalidate I-Cache : ICIALLU register */
    SCB_InvalidateICache();

    /* Enable branch prediction */
    SCB->CCR |= (1 << 18);
    __DSB();

    /* Invalidate I-Cache : ICIALLU register */
    SCB_InvalidateICache();

    /* Enable I-Cache */
    SCB_EnableICache();

    SCB_InvalidateDCache();
    SCB_EnableDCache();

    /* STM32F7xx HAL library initialization:
     - Configure the Flash ART accelerator on ITCM interface
     - Configure the Systick to generate an interrupt each 1 msec
     - Set NVIC Group Priority to 4
     - Global MSP (MCU Support Package) initialization
     */
    HAL_Init();

    /* Configure the system clock @ 200 Mhz */
    SystemClock_Config();

    /* Init GPIO */

    MX_GPIO_Init();
    /* Init ADC3 */
    MX_ADC3_Init();

    /* Configure the board */
    k_BspInit();

    /* Initialize RTC */
    k_CalendarBkupInit();

    /* Create GUI task */
    osThreadDef(GUI_Thread, GUIThread, osPriorityNormal, 0, 2 * 1024);
    osThreadCreate(osThread(GUI_Thread), NULL);

    /* Add Modules*/
    k_ModuleInit();

    /* Link modules */
    k_ModuleAdd(&audio_player_board);
    k_ModuleAdd(&redfrog_loader_board);
    k_ModuleAdd(&redfrog_workstation_board);
#if !defined ( __GNUC__ )
  k_ModuleAdd(&video_player_board);
  #endif
    /*k_ModuleAdd(&audio_recorder_board);
     k_ModuleAdd(&vnc_server);
     k_ModuleAdd(&gardening_control_board);
     k_ModuleAdd(&home_alarm_board);
     k_ModuleAdd(&games_board);
     k_ModuleAdd(&settings_board);*/

    /* Start scheduler */
    osKernelStart();

    /* We should never get here as control is now taken by the scheduler */
    for (;;)
        ;

这里是MX_ADC3_Init和MX_GPIO_Init函数的内容:

/**
 * @brief ADC3 Initialization Function
 * @param None
 * @retval None
 */
static void MX_ADC3_Init(void) {

    /* USER CODE BEGIN ADC3_Init 0 */

    /* USER CODE END ADC3_Init 0 */

    ADC_ChannelConfTypeDef sConfig = { 0 };

    /* USER CODE BEGIN ADC3_Init 1 */
    __HAL_RCC_ADC3_CLK_ENABLE()
    ;
    /* USER CODE END ADC3_Init 1 */
    /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
     */
    hadc3.Instance = ADC3;
    hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc3.Init.Resolution = ADC_RESOLUTION_12B;
    hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc3.Init.ContinuousConvMode = ENABLE;
    hadc3.Init.DiscontinuousConvMode = DISABLE;
    hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc3.Init.NbrOfConversion = 1;
    hadc3.Init.DMAContinuousRequests = ENABLE;
    hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    if (HAL_ADC_Init(&hadc3) != HAL_OK) {
        printf("NOK");
    }
    /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
     */
    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
    if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) {
        printf("NOK");
    }
    /* USER CODE BEGIN ADC3_Init 2 */

    /* USER CODE END ADC3_Init 2 */

}

static void MX_GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = { 0 };

    __HAL_RCC_GPIOA_CLK_ENABLE()
    ;

    /*Configure GPIO pin : PA0 */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(ADC_IRQn);

}

最后是 GUIThread 函数,在 main 函数中作为线程调用。

/**
 * @brief  Start task
 * @param  argument: pointer that is passed to the thread function as start argument.
 * @retval None
 */
static void GUIThread(void const *argument) {
    /* Initialize Storage Units */
    k_StorageInit();

    /* Initialize GUI */
    GUI_Init();

    WM_MULTIBUF_Enable(1);
    GUI_SetLayerVisEx(1, 0);
    GUI_SelectLayer(0);

    GUI_SetBkColor(GUI_WHITE);
    GUI_Clear();

    /* Set General Graphical proprieties */
    k_SetGuiProfile();

    /* Demo Startup */
    k_StartUp();
    /* Create Touch screen Timer */
    osTimerDef(TS_Timer, TimerCallback);
    lcd_timer = osTimerCreate(osTimer(TS_Timer), osTimerPeriodic, (void*) 0);

    /* Start the TS Timer */
    osTimerStart(lcd_timer, 100);

    /* Show the main menu */
    k_InitMenu();
    WM_HWIN hItem = TEXT_CreateEx(350, 100, 80, 15, WM_GetDesktopWindowEx(0),
    WM_CF_SHOW, 0, 33, "0");
    TEXT_SetFont(hItem, GUI_FONT_13B_ASCII);
    TEXT_SetTextColor(hItem, GUI_BLACK);

    HAL_ADC_Start(&hadc3);
    HAL_StatusTypeDef res;
    /* Gui background Task */
    while (1) {
        uint32_t InitTick = 0;
        GUI_Exec(); /* Do the background work ... Update windows etc.) */

        res = HAL_ADC_PollForConversion(&hadc3,
        HAL_MAX_DELAY);
        switch (res) {
        case HAL_OK:
            if ((WM_IsVisible(hItem))
                    && ((osKernelSysTick() - InitTick) > 500)) {
                g_ADCValue = HAL_ADC_GetValue(&hadc3);
                g_MeasurementNumber++;
                hItem = WM_GetDialogItem(WM_GetDesktopWindowEx(0), 33);
                char str[12];
                sprintf((char*) str, "%lu", g_ADCValue);
                TEXT_SetText(hItem, str);
                WM_InvalidateWindow(hItem);
                WM_Update(hItem);
            }
            break;
        case HAL_ERROR:
            printf("ERROR");
            break;
        case HAL_BUSY:
            printf("BUSY");
            break;
        case HAL_TIMEOUT:
            printf("TIMEOUT");
            break;
        }
        osDelay(20); /* Nothing left to do for the moment ... Idle processing */
    }
}

末尾的 while 循环包含允许我定期从 GPIOPin0/ADC3Channel0 读取值的代码。这是第一次工作,因为当我重置电路板时值正在改变。但是随后程序卡住了。 我需要你的帮助来理解我做错了什么。 非常感谢。

ADC 仅转换一个样本。

这是由于您调用res = HAL_ADC_PollForConversion(&hadc3, HAL_MAX_DELAY);

造成的

此函数将在转换完成后停止 ADC,因此下次调用此函数时您的程序将被阻止,因为从未设置 EOC 标志。

只需在 while(1) 循环中添加一个 HAL_ADC_Start(&hadc3);,您将始终获得新值。

稍后您可以更改代码以使用 DMA,ADC 可以 运行 无需等待 :)