STM32F746NG-Discovery: программа зависла после первого чтения АЦП - PullRequest
1 голос
/ 20 октября 2019

Я пытаюсь прочитать значения АЦП с экрана Arduino, подключенного к моей плате. Щит Arduino - это уже протестированная пользовательская плата, которая отправляет данные при обнаружении контакта между датчиком и пальцем.

Я разработал программу, использующую STM32Cube IDE, чтобы иметь возможность считывать эти значения и периодически отображать их. Эта программа основана на примере STemWin. К сожалению, после первого чтения из программы значение не обновляется, а остальные функции больше не работают. Программа зависла. Если я прокомментирую код, который периодически читает данные из АЦП, то программа работает нормально.

Вот содержимое моего основного сообщения:

/* 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 Ответ

2 голосов
/ 21 октября 2019

АЦП преобразует только один образец.

Это вызвано тем, что вы набрали res = HAL_ADC_PollForConversion(&hadc3, HAL_MAX_DELAY);

Эта функция остановит АЦП после завершения преобразования, поэтому в следующий раз вы придете кэтот вызов блокирует вашу программу, поскольку флаг EOC никогда не устанавливается.

Просто добавьте HAL_ADC_Start(&hadc3); в ваш цикл while(1), и вы всегда получите новые значения.

Позже вы можете изменитьВаш код для использования DMA и АЦП может работать без ожидания:)

...