简体   繁体   English

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

[英]STM32F746NG-Discovery : Program Stuck after first ADC read

I am trying to read ADC values from an arduino shield connected to my board.我正在尝试从连接到我的电路板的 arduino 屏蔽中读取 ADC 值。 The Arduino shield is an already tested custom board which sends data when a contact between a sensor and a finger is detected. Arduino 扩展板是经过测试的定制板,可在检测到传感器和手指之间的接触时发送数据。

I developed a program using STM32Cube IDE to be able to read these values and display it periodically.我使用 STM32Cube IDE 开发了一个程序,以便能够读取这些值并定期显示。 This program is based on STemWin example.该程序基于 STemWin 示例。 Unfortunately, after first read from the program, the value is not updated and the rest of the features are not working anymore.不幸的是,在第一次从程序中读取后,该值没有更新,并且功能的 rest 不再工作。 The program is stuck.程序卡住了。 If I comment the code which periodically reads data from ADC then the program works normally.如果我注释定期从 ADC 读取数据的代码,则程序正常工作。

Here is the content of my main:以下是我的主要内容:

/* 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 (;;)
        ;

Here is the content of MX_ADC3_Init and MX_GPIO_Init functions:下面是 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);

}

And finally here is the GUIThread function which is called as a thread in main function.最后是 GUIThread function,它在主 function 中被称为线程。

/**
 * @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 */
    }
}

The while loop at the end contains the code that should allow me to read values periodically from GPIOPin0/ADC3Channel0.最后的 while 循环包含允许我定期从 GPIOPin0/ADC3Channel0 读取值的代码。 It works a first time since when I reset the board the value is changing.自从我重置电路板后,它第一次起作用,值正在改变。 But then the program is stuck.但随后程序卡住了。 I need your help to understand what I am doing wrong.我需要你的帮助来了解我做错了什么。 Thank you very much.非常感谢。

The ADC only converts one sample. ADC 仅转换一个样本。

This is caused by your call of res = HAL_ADC_PollForConversion(&hadc3, HAL_MAX_DELAY);这是由于您调用res = HAL_ADC_PollForConversion(&hadc3, HAL_MAX_DELAY);

This function will stop the ADC after the conversion is finished, so next time you come to this call your program get blocked since the EOC flag is never set.此 function 将在转换完成后停止 ADC,因此下次您进行此调用时,您的程序将被阻塞,因为 EOC 标志从未设置。

Simply add a HAL_ADC_Start(&hadc3);只需添加一个HAL_ADC_Start(&hadc3); within your while(1) loop and you will always get new values.在您的while(1)循环中,您将始终获得新值。

Later you could change your code to use DMA and the ADC could run without waiting:)稍后您可以更改代码以使用 DMA,ADC 无需等待即可运行:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM