/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * *

© Copyright (c) 2019 STMicroelectronics. * All rights reserved.

* * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "cmsis_os.h" #include "usb_device.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include #include #include #include "ili9341.h" #include "ili9341_touch.h" #include "fonts.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ I2C_HandleTypeDef hi2c1; RTC_HandleTypeDef hrtc; SPI_HandleTypeDef hspi2; TIM_HandleTypeDef htim2; UART_HandleTypeDef huart2; osThreadId defaultTaskHandle; osThreadId myTask02Handle; /* USER CODE BEGIN PV */ RTC_TimeTypeDef sTime = {0}; RTC_DateTypeDef DateToUpdate = {0}; char time_str[64] = {0,}; int32_t radius = 79, x_center = 210, y_center = 130; int32_t encoder = 0, encoder_prev = 0; int32_t capture = 0, capture_prev = 0; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_I2C1_Init(void); static void MX_SPI2_Init(void); static void MX_USART2_UART_Init(void); static void MX_TIM2_Init(void); static void MX_RTC_Init(void); void StartDefaultTask(void const * argument); void StartTask02(void const * argument); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_I2C1_Init(); MX_SPI2_Init(); MX_USART2_UART_Init(); MX_TIM2_Init(); MX_RTC_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* USER CODE BEGIN RTOS_MUTEX */ /* add mutexes, ... */ /* USER CODE END RTOS_MUTEX */ /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ /* Create the thread(s) */ /* definition and creation of defaultTask */ osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128); defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL); /* definition and creation of myTask02 */ osThreadDef(myTask02, StartTask02, osPriorityNormal, 0, 128); myTask02Handle = osThreadCreate(osThread(myTask02), NULL); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ /* USER CODE END RTOS_THREADS */ /* Start scheduler */ osKernelStart(); /* We should never get here as control is now taken by the scheduler */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USB; PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } } /** * @brief I2C1 Initialization Function * @param None * @retval None */ static void MX_I2C1_Init(void) { /* USER CODE BEGIN I2C1_Init 0 */ /* USER CODE END I2C1_Init 0 */ /* USER CODE BEGIN I2C1_Init 1 */ /* USER CODE END I2C1_Init 1 */ hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2C1_Init 2 */ /* USER CODE END I2C1_Init 2 */ } /** * @brief RTC Initialization Function * @param None * @retval None */ static void MX_RTC_Init(void) { /* USER CODE BEGIN RTC_Init 0 */ /* USER CODE END RTC_Init 0 */ RTC_TimeTypeDef sTime = {0}; RTC_DateTypeDef DateToUpdate = {0}; /* USER CODE BEGIN RTC_Init 1 */ /* USER CODE END RTC_Init 1 */ /** Initialize RTC Only */ hrtc.Instance = RTC; hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND; hrtc.Init.OutPut = RTC_OUTPUTSOURCE_ALARM; if (HAL_RTC_Init(&hrtc) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN Check_RTC_BKUP */ /* USER CODE END Check_RTC_BKUP */ /** Initialize RTC and set the Time and Date */ sTime.Hours = 14; sTime.Minutes = 54; sTime.Seconds = 0; if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY; DateToUpdate.Month = RTC_MONTH_JANUARY; DateToUpdate.Date = 1; DateToUpdate.Year = 0; if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN RTC_Init 2 */ /* USER CODE END RTC_Init 2 */ } /** * @brief SPI2 Initialization Function * @param None * @retval None */ static void MX_SPI2_Init(void) { /* USER CODE BEGIN SPI2_Init 0 */ /* USER CODE END SPI2_Init 0 */ /* USER CODE BEGIN SPI2_Init 1 */ /* USER CODE END SPI2_Init 1 */ /* SPI2 parameter configuration*/ hspi2.Instance = SPI2; hspi2.Init.Mode = SPI_MODE_MASTER; hspi2.Init.Direction = SPI_DIRECTION_2LINES; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi2.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI2_Init 2 */ /* USER CODE END SPI2_Init 2 */ } /** * @brief TIM2 Initialization Function * @param None * @retval None */ static void MX_TIM2_Init(void) { /* USER CODE BEGIN TIM2_Init 0 */ /* USER CODE END TIM2_Init 0 */ TIM_Encoder_InitTypeDef sConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; /* USER CODE BEGIN TIM2_Init 1 */ /* USER CODE END TIM2_Init 1 */ htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 65535; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; sConfig.EncoderMode = TIM_ENCODERMODE_TI12; sConfig.IC1Polarity = TIM_ICPOLARITY_RISING; sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI; sConfig.IC1Prescaler = TIM_ICPSC_DIV1; sConfig.IC1Filter = 0; sConfig.IC2Polarity = TIM_ICPOLARITY_RISING; sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI; sConfig.IC2Prescaler = TIM_ICPSC_DIV1; sConfig.IC2Filter = 0; if (HAL_TIM_Encoder_Init(&htim2, &sConfig) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM2_Init 2 */ /* USER CODE END TIM2_Init 2 */ } /** * @brief USART2 Initialization Function * @param None * @retval None */ static void MX_USART2_UART_Init(void) { /* USER CODE BEGIN USART2_Init 0 */ /* USER CODE END USART2_Init 0 */ /* USER CODE BEGIN USART2_Init 1 */ /* USER CODE END USART2_Init 1 */ huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART2_Init 2 */ /* USER CODE END USART2_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET); /*Configure GPIO pin : PA4 */ GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pins : PA5 PA6 PA7 */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ void initDisplay() { ILI9341_Unselect(); ILI9341_TouchUnselect(); ILI9341_Init(); } void UART_Printf(const char* fmt, ...) { char buff[256]; va_list args; va_start(args, fmt); vsnprintf(buff, sizeof(buff), fmt, args); HAL_UART_Transmit(&huart2, (uint8_t*) buff, strlen(buff), HAL_MAX_DELAY); va_end(args); } void drawLineCircle (int32_t centreX, int32_t centreY, int32_t diameter, uint16_t color) { int32_t dxOuter, dyOuter, dxi, dyi; for (float i = 0; i <360; i = i + 22.5) { dxOuter = diameter * cos((i-90)*M_PI/180.0); dyOuter = diameter * sin((i-90)*M_PI/180.0); dxi = dxOuter * 0.98; dyi = dyOuter * 0.98; ILI9341_writeLine(dxi+centreX,dyi+centreY,dxOuter+centreX,dyOuter+centreY,color); } } void drawStatic (void) { ILI9341_FillScreen(ILI9341_BLACK); ILI9341_WriteString(0, 0, "ANTENNA ROTATOR", Font_11x18, ILI9341_RED, ILI9341_BLACK); ILI9341_WriteString(30, 18, "CONTROLLER", Font_11x18, ILI9341_RED, ILI9341_BLACK); ILI9341_WriteString(5, 80, "Cur pos:", Font_11x18, ILI9341_RED, ILI9341_BLACK); ILI9341_WriteString(55, 100, "O", Font_7x10, ILI9341_RED, ILI9341_BLACK); ILI9341_WriteString(5, 126, "Set pos:", Font_11x18, ILI9341_RED, ILI9341_BLACK); ILI9341_WriteString(55, 145, "O", Font_7x10, ILI9341_RED, ILI9341_BLACK); ILI9341_WriteString(x_center+radius+7, y_center-5, "90", Font_7x10, ILI9341_GREEN, ILI9341_BLACK); ILI9341_WriteString(x_center-radius-28, y_center-5, "270", Font_7x10, ILI9341_GREEN, ILI9341_BLACK); ILI9341_WriteString(x_center-10, y_center+radius+7, "180", Font_7x10, ILI9341_GREEN, ILI9341_BLACK); ILI9341_WriteString(x_center-3, y_center-radius-17, "0", Font_7x10, ILI9341_GREEN, ILI9341_BLACK); } void drawDirection (int32_t angle, int32_t x, int32_t y, uint16_t color) { if((angle < 22.5) || (angle > 337.5 )) ILI9341_WriteString(x,y,"North ",Font_16x26,color, ILI9341_BLACK); if((angle > 22.5) && (angle < 67.5 )) ILI9341_WriteString(x,y,"North-East",Font_16x26,color, ILI9341_BLACK); if((angle > 67.5) && (angle < 112.5 )) ILI9341_WriteString(x,y,"East ",Font_16x26,color, ILI9341_BLACK); if((angle > 112.5) && (angle < 157.5 )) ILI9341_WriteString(x,y,"South-East",Font_16x26,color, ILI9341_BLACK); if((angle > 157.5) && (angle < 202.5 )) ILI9341_WriteString(x,y,"South ",Font_16x26,color, ILI9341_BLACK); if((angle > 202.5) && (angle < 247.5 )) ILI9341_WriteString(x,y,"South-West",Font_16x26,color, ILI9341_BLACK); if((angle > 247.5) && (angle < 292.5 )) ILI9341_WriteString(x,y,"West ",Font_16x26,color, ILI9341_BLACK); if((angle > 292.5) && (angle < 337.5 )) ILI9341_WriteString(x,y,"North-West",Font_16x26,color, ILI9341_BLACK); } void GetTime (void) { HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN); snprintf(time_str, 63, "%02d:%02d:%02d", sTime.Hours, sTime.Minutes, sTime.Seconds); } void GetEncoder (void) { capture = TIM2->CNT / 4; if (capture > 8000) { capture -= 65535 / 4; } if (capture != capture_prev) { encoder_prev = encoder; } else { encoder_prev = 10000; } encoder += capture - capture_prev; encoder = (encoder + 360) % 360; if (encoder == 0) { TIM2->CNT = 0; } if (encoder > 360) {TIM2->CNT = 0; } capture_prev = capture; } /* USER CODE END 4 */ /* USER CODE BEGIN Header_StartDefaultTask */ /** * @brief Function implementing the defaultTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void const * argument) { /* init code for USB_DEVICE */ MX_USB_DEVICE_Init(); /* USER CODE BEGIN 5 */ /* Infinite loop */ for (;;) { osDelay(1); } /* USER CODE END 5 */ } /* USER CODE BEGIN Header_StartTask02 */ /** * @brief Function implementing the myTask02 thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartTask02 */ void StartTask02(void const * argument) { /* USER CODE BEGIN StartTask02 */ char buf[25]; initDisplay(); hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL); drawStatic(); /* Infinite loop */ for (;;) { GetTime(); GetEncoder(); if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == 0) { } sprintf(buf, "%03ld", encoder); drawDirection(encoder,0,210, ILI9341_CYAN); ILI9341_WriteString(5, 100, buf, Font_16x26, ILI9341_RED, ILI9341_BLACK); ILI9341_WriteString(5, 145, buf, Font_16x26, ILI9341_RED, ILI9341_BLACK); ILI9341_WriteString(229, 0, time_str, Font_11x18, ILI9341_GREEN, ILI9341_BLACK); ILI9341_DrawArrow(x_center, y_center, x_center+radius*cos((encoder/180.0*M_PI)-(90/180.0*M_PI)), y_center+radius*sin((encoder/180.0*M_PI)-(90/180.0 * M_PI)), 0.23, ILI9341_RED); ILI9341_drawCircle(x_center, y_center, radius, ILI9341_RED); drawLineCircle(x_center,y_center,radius,ILI9341_YELLOW); if (encoder_prev != 10000) { ILI9341_DrawArrow(x_center, y_center, x_center+radius*cos((encoder_prev/180.0*M_PI)-(90/180.0*M_PI)), y_center+radius*sin((encoder_prev/180.0*M_PI)-(90/180.0 * M_PI)), 0.23, ILI9341_BLACK); ILI9341_DrawArrow(x_center, y_center, x_center+radius*cos((encoder/180.0*M_PI)-(90/180.0*M_PI)), y_center+radius*sin((encoder/180.0*M_PI)-(90/180.0 * M_PI)), 0.23, ILI9341_RED); } osDelay(1); } /* USER CODE END StartTask02 */ } /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/