C语言 STM32F746NG发现:程序在第一次读取ADC后卡住



我正在尝试从连接到电路板的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 读取值。自从我重置电路板以来,它第一次工作,值正在发生变化。但是程序随后卡住了。 我需要你的帮助来了解我做错了什么。 谢谢。

ADC仅转换一个样本。

这是由您的res = HAL_ADC_PollForConversion(&hadc3, HAL_MAX_DELAY);

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

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

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

相关内容

  • 没有找到相关文章

最新更新