STM32F746NG-发现:首次读取ADC后程序卡住

时间:2019-10-20 18:36:54

标签: c stm32 gpio adc stm32f7

我正在尝试从连接到我板上的arduino屏蔽读取ADC值。 Arduino屏蔽板是已经过测试的定制板,当检测到传感器和手指之间的接触时,该板将发送数据。

我使用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函数,在主函数中被称为线程。

/**
 * @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读取值的代码。自从我重置开发板以来,值一直在变化,这是第一次工作。但是随后程序被卡住了。 我需要您的帮助,以了解我在做什么错。 非常感谢。

1 个答案:

答案 0 :(得分:2)

ADC仅转换一个样本。

这是由于您致电res = HAL_ADC_PollForConversion(&hadc3, HAL_MAX_DELAY);

引起的

此函数将在转换完成后停止ADC,因此,由于从未设置EOC标志,因此下次访问该程序时,程序将被阻塞。

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

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