Загрузка данных


/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * 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"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "task.h"
#include "PCB_Uni_mp3.h"
#include "DFPlayer_Mini.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
DFPLayerMini DFPlayer1;
uint8_t DFPlayer1_Rx[10];
uint8_t MainBoard_Rx[4];

uint8_t ch_vol = 0;


/* 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 ---------------------------------------------------------*/
TIM_HandleTypeDef htim3;

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart3_rx;

/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .priority = (osPriority_t) osPriorityNormal,
  .stack_size = 128 * 4
};
/* Definitions for myTask02 */
osThreadId_t myTask02Handle;
const osThreadAttr_t myTask02_attributes = {
  .name = "myTask02",
  .priority = (osPriority_t) osPriorityLow,
  .stack_size = 128 * 4
};
/* Definitions for myTask03 */
osThreadId_t myTask03Handle;
const osThreadAttr_t myTask03_attributes = {
  .name = "myTask03",
  .priority = (osPriority_t) osPriorityLow,
  .stack_size = 128 * 4
};
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_TIM3_Init(void);
static void MX_USART3_UART_Init(void);
void StartDefaultTask(void *argument);
void StartTask02(void *argument);
void StartTask03(void *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_DMA_Init();
  MX_USART1_UART_Init();
  MX_TIM3_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Init scheduler */
  osKernelInitialize();

  /* 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) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* creation of myTask02 */
  myTask02Handle = osThreadNew(StartTask02, NULL, &myTask02_attributes);

  /* creation of myTask03 */
  myTask03Handle = osThreadNew(StartTask03, NULL, &myTask03_attributes);

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

  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_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();
  }
}

/**
  * @brief TIM3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */

  /* USER CODE END TIM3_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 0;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 0;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */

  /* USER CODE END TIM3_Init 2 */
  HAL_TIM_MspPostInit(&htim3);

}

/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 9600;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{

  /* USER CODE BEGIN USART3_Init 0 */

  /* USER CODE END USART3_Init 0 */

  /* USER CODE BEGIN USART3_Init 1 */

  /* USER CODE END USART3_Init 1 */
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 9600;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART3_Init 2 */

  /* USER CODE END USART3_Init 2 */

}

/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Channel3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
  /* DMA1_Channel5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);

}

/**
  * @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(oLED_GPIO_Port, oLED_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(oBUSY_GPIO_Port, oBUSY_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : oLED_Pin */
  GPIO_InitStruct.Pin = oLED_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(oLED_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : iPlayStop_Pin iVolDown_Pin iVol_Up_Pin iVolDownA15_Pin */
  GPIO_InitStruct.Pin = iPlayStop_Pin|iVolDown_Pin|iVol_Up_Pin|iVolDownA15_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : iVolUp_Pin */
  GPIO_InitStruct.Pin = iVolUp_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(iVolUp_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : oBUSY_Pin */
  GPIO_InitStruct.Pin = oBUSY_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(oBUSY_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : PB8 PB9 */
  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

/* USER CODE BEGIN 4 */



/* 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 *argument)
{
  /* 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 *argument)
{
  /* USER CODE BEGIN StartTask02 */
  /* Infinite loop */
	
	osDelay(1500); // Задержка при включении
	
	HAL_UART_Receive_DMA(&huart1, DFPlayer1_Rx, 10); // Включение DMA по приему 10 байт от плеера
	
	//DFPlayerMini_Ini(); // Инициализация плеера
		
	vTaskDelay(200); // Задержка между посылками в плеер
	
	HAL_UART_Receive_IT(&huart3, MainBoard_Rx, 1); // Разрашение прерываний по приему байта от платы MAIN
	
#if defined(PLAY_A4_PAUSE_A7_EN) || defined(ZD) || defined(A4_LOW_LEV_CONT)
	DFPlayer1.track_num_MP3 = 1;
#else
	ch_tr = DFPlayer1.track_num_MP3; // Инициализация переменной ch_tr для отслеживания изменений переключения трека
#endif

	LED_BUSY(1);

	DFPlayer1.vol = 10; // Установка громкости

#if defined(ZD) || defined(A4_LOW_LEV_CONT)
	DFPlayer1.vol = 30; // Установка громкости на максимум при автономном использовании
#endif
		
	ch_vol = DFPlayer1.vol; // Инициализация переменной ch_vol для отслеживания изменений громкости
	
	DFPlayer_setVolume(DFPlayer1.vol); // Установка громкости

	vTaskDelay(100); // Задержка между посылками в плеер
	
	
#ifdef ANATOMIA // Если используется для стенда М0004_Анатомическое_строение_OK, то перенциализироать пины A4, A7 на выход.
HAL_GPIO_DeInit (GPIOA, GPIO_PIN_4); // Деинициализация  пина A4 (сброс в исходное состояние)

HAL_GPIO_DeInit (GPIOA, GPIO_PIN_7); // Деинициализация  пина A7 (сброс в исходное состояние)

GPIO_InitTypeDef GPIO_InitStruct = {0};

GPIO_InitStruct.Pin = GPIO_PIN_4; // Вывод
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Режим - выход
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // Скорость - низкая
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Инициализировать

GPIO_InitStruct.Pin = GPIO_PIN_7; // Вывод
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Режим - выход
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // Скорость - низкая
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Инициализировать
#endif

#ifdef ZD // Если используется для  то переинциализироать пин A4
HAL_GPIO_DeInit (GPIOA, iPlayStop_Pin); // Деинициализация  пина A4 (сброс в исходное состояние)

GPIO_InitTypeDef GPIO_InitStruct = {0};

GPIO_InitStruct.Pin = iPlayStop_Pin; // Вывод
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // Режим - вход
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // Скорость - низкая
GPIO_InitStruct.Pull = GPIO_PULLDOWN; // Поддтяжка к земле
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Инициализировать
#endif

#ifdef A4_LOW_LEV_CONT
HAL_GPIO_DeInit (GPIOA, iPlayStop_Pin); // Деинициализация  пина A4 (сброс в исходное состояние)

GPIO_InitTypeDef GPIO_InitStruct = {0};

GPIO_InitStruct.Pin = iPlayStop_Pin; // Вывод
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // Режим - вход
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // Скорость - низкая
GPIO_InitStruct.Pull = GPIO_PULLUP; // Поддтяжка к +
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Инициализировать
#endif

#ifdef PLAY_A4_PAUSE_A7_EN

HAL_GPIO_DeInit (GPIOA, GPIO_PIN_4); // Деинициализация  пина A4 (сброс в исходное состояние)
HAL_GPIO_DeInit (GPIOA, GPIO_PIN_7); // Деинициализация  пина A7 (сброс в исходное состояние)

GPIO_InitTypeDef GPIO_InitStruct = {0};

GPIO_InitStruct.Pin = GPIO_PIN_4; // Вывод (пин)
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // Работа пина на вход
GPIO_InitStruct.Pull = GPIO_PULLUP; // Подтяжка к питанию
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Инициализировать

GPIO_InitStruct.Pin = GPIO_PIN_7; // Вывод (пин)
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // Работа пина на вход
GPIO_InitStruct.Pull = GPIO_PULLUP; // Подтяжка к питанию
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Инициализировать

#endif
	
	vTaskDelay(100);
	
	
  for(;;)
  {
		
#ifdef ASCII_PROTOCOL
		if (ch_tr == 1)
		{
			DFPlayer_Play_track_MP3(DFPlayer1.track_num_MP3);
			DFPlayer1.DF_LED = 1;
			ch_tr = 0;
		}
		
#ifdef ANATOMIA
if (DFPlayer1.DF_LED == 1)
{
	if (DFPlayer1.track_num_MP3 == 48)
	{
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
	}
	else
	{
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
	}
} else
{
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
}
#endif		

	  vTaskDelay(50);
		
		Read_Vol_Pins();
		
		if (ch_vol != DFPlayer1.vol)
		{
			DFPlayer_setVolume(DFPlayer1.vol);
			ch_vol = DFPlayer1.vol;
		}
		
		vTaskDelay(50);
		
#endif

#ifdef HEX_PROTOCOL
		if (ch_tr == 1)
		{
			DFPlayer_Play_track_UserFolder(DFPlayer1.Folder, DFPlayer1.track_num_MP3);
			DFPlayer1.DF_LED = 1;
			ch_tr = 0;
		}

	  vTaskDelay(50);
		
		Read_Vol_Pins();
		
		if (ch_vol != DFPlayer1.vol)
		{
			DFPlayer_setVolume(DFPlayer1.vol);
			ch_vol = DFPlayer1.vol;
		}
		
		vTaskDelay(50);
		
#endif
		
#ifdef PLAY_A4_PAUSE_A7_EN
		
		if (ch_tr == 1)
		{
			DFPlayer_Play_track_MP3(DFPlayer1.track_num_MP3);
			DFPlayer1.DF_LED = 1;
			ch_tr = 0;
		}
		
		vTaskDelay(50);
		
		Read_Vol_Pins();
		
		if (ch_vol != DFPlayer1.vol)
		{
			DFPlayer_setVolume(DFPlayer1.vol);
			ch_vol = DFPlayer1.vol;
		}
		
		Read_PinPlayStop();
		vTaskDelay(100);
#endif

#ifdef ZD
		
		Read_PinPlayStop();
		vTaskDelay(100);
#endif

#ifdef A4_LOW_LEV_CONT
		
		Read_PinPlayStop();
		vTaskDelay(100);
#endif

  }
  /* USER CODE END StartTask02 */
}

/* USER CODE BEGIN Header_StartTask03 */
/**
* @brief Function implementing the myTask03 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask03 */
void StartTask03(void *argument)
{
  /* USER CODE BEGIN StartTask03 */
  /* Infinite loop */
  for(;;)
  {

		LED_MCU_Blink();
    osDelay(500);
		
		if (DFPlayer1.DF_LED == 0)
		{
				LED_BUSY(0);
		}
		
			if (DFPlayer1.DF_LED == 1)
		{
				LED_BUSY(1);
		}
		//LED_BUSY_Blink();

  }
  /* USER CODE END StartTask03 */
}

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

/*********************************************************************************************************************************************************************************
*		Файл: DFPLayer_Mini.c
*		Версия: v1.00
*		Наименование проекта: Плата Uni_mp3
*		Разработал: Тимофеев Д.Г.
*		Организация:
*
*		Описание к файлу:
*
*
*		Примечания:
*
*
********************************************************************************************************************************************************************************/

#include "main.h"
#include "cmsis_os.h"
#include "DFPlayer_Mini.h"

uint8_t Player_Tx_Data[10];

void DFPlayer_DoSum(uint8_t *Str) // Расчет контрольной суммы
{
	uint16_t xorsum = 0;
	uint8_t _i;
	for(_i = 0; _i < 6; _i++)
	{
		xorsum = xorsum + Str[_i];
	}
	xorsum = 0 - xorsum;
	*(Str+_i) = (uint8_t)(xorsum >>8);
	*(Str+_i+1) = (uint8_t)(xorsum & 0x00ff);
}

void DFPlayerMini_Ini (void) // Инициализация плеера
{
	Player_Tx_Data[0] = 0x7E; // Старт байт
	Player_Tx_Data[1] = 0xFF; // Версия ПО
	Player_Tx_Data[2] = 0x06; // количество информационных байт
	Player_Tx_Data[3] = 0x09; // Команда
	Player_Tx_Data[4] = 0x00; // Обратная связь (ожидание подтверждения ответа от плеера)
	Player_Tx_Data[5] = 0x00; // Старший байт данных
	Player_Tx_Data[6] = 0x02; // Младший байт данных SD card
	
	DFPlayer_DoSum(&Player_Tx_Data[1]); // Расчет контрольной суммы

	Player_Tx_Data[9] = 0xEF; // Стоп байт
	                       
	HAL_UART_Transmit(&huart1, Player_Tx_Data, 10, 0xFFFF);	
}


void DFPlayer_setVolume(uint8_t vol) // Установка гормкости
{
	if (vol > 30)
	{
		vol = 30;
	}
	Player_Tx_Data[0] = 0x7E; // Старт байт
	Player_Tx_Data[1] = 0xFF; // Версия ПО
	Player_Tx_Data[2] = 0x06; // количество информационных байт
	Player_Tx_Data[3] = 0x06; // Команда (усановка горомксти)
	Player_Tx_Data[4] = 0x00; // Обратная связь (ожидание подтвер
	Player_Tx_Data[5] = 0x00; // Старший байт данных
	Player_Tx_Data[6] = vol; // Уровень громкости
	
	DFPlayer_DoSum(&Player_Tx_Data[1]); // Расчет контрольной суммы

	Player_Tx_Data[9] = 0xEF; // Стоп байт
	
	HAL_UART_Transmit(&huart1, Player_Tx_Data, 10, 0xFFFF);	
}

void DFPlayer_Play_track_MP3(uint16_t n_track) // Выбор трека в папке MP3
{
	Player_Tx_Data[0] = 0x7E; // Старт байт
	Player_Tx_Data[1] = 0xFF; // Версия ПО
	Player_Tx_Data[2] = 0x06; // количество информационных байт
	Player_Tx_Data[3] = 0x12; // Команда запустить трек в папке MP3
	Player_Tx_Data[4] = 0x00; // Обратная связь (ожидание подтвер
	
	Player_Tx_Data[5] = 0x00; 
	Player_Tx_Data[6] = 0x00; 
	
	Player_Tx_Data[5] |= (n_track >> 8); // Старший байт данных
	Player_Tx_Data[6] |= (0x00FF & n_track); // Номер файла для воспроизвдения
	
	DFPlayer_DoSum(&Player_Tx_Data[1]); // Расчет контрольной суммы
	
	Player_Tx_Data[9] = 0xEF; // Стоп байт
	
	HAL_UART_Transmit_IT(&huart1, Player_Tx_Data, 10);	
}

void DFPlayer_pause (void)
{
	Player_Tx_Data[0] = 0x7E; // Старт байт
	Player_Tx_Data[1] = 0xFF; // Версия ПО
	Player_Tx_Data[2] = 0x06; // количество информационных байт
	Player_Tx_Data[3] = 0x0E; // Пауза
	Player_Tx_Data[4] = 0x00; // Обратная связь (ожидание подтверждения ответа от плеера)
	Player_Tx_Data[5] = 0x00; // Старший байт данных
	Player_Tx_Data[6] = 0x02; // Младший байт данных SD card
	
	DFPlayer_DoSum(&Player_Tx_Data[1]); // Расчет контрольной суммы

	Player_Tx_Data[9] = 0xEF; // Стоп байт
	                       
	HAL_UART_Transmit_IT(&huart1, Player_Tx_Data, 10);	
}



void DFPlayer_Play(void) // Воспроизвести (после паузы)
{
	Player_Tx_Data[0] = 0x7E; // Старт байт
	Player_Tx_Data[1] = 0xFF; // Версия ПО
	Player_Tx_Data[2] = 0x06; // количество информационных байт
	Player_Tx_Data[3] = 0x0D; // Play
	Player_Tx_Data[4] = 0x00; // Обратная связь (ожидание подтвер
	
	Player_Tx_Data[5] = 0x00; 
	Player_Tx_Data[6] = 0x00; 
	
	Player_Tx_Data[5] = 0x00; // Старший байт данных
	Player_Tx_Data[6] = 0x00; // Младший байт данных
	
	DFPlayer_DoSum(&Player_Tx_Data[1]); // Расчет контрольной суммы
	
	Player_Tx_Data[9] = 0xEF; // Стоп байт
	
	HAL_UART_Transmit_IT(&huart1, Player_Tx_Data, 10);	
}


void DFPlayer_stop (void)
{
	Player_Tx_Data[0] = 0x7E; // Старт байт
	Player_Tx_Data[1] = 0xFF; // Версия ПО
	Player_Tx_Data[2] = 0x06; // количество информационных байт
	Player_Tx_Data[3] = 0x16; // Пауза
	Player_Tx_Data[4] = 0x00; // Обратная связь (ожидание подтверждения ответа от плеера)
	Player_Tx_Data[5] = 0x00; // Старший байт данных
	Player_Tx_Data[6] = 0x02; // Младший байт данных SD card
	
	DFPlayer_DoSum(&Player_Tx_Data[1]); // Расчет контрольной суммы

	Player_Tx_Data[9] = 0xEF; // Стоп байт
	                       
	HAL_UART_Transmit_IT(&huart1, Player_Tx_Data, 10);
}

void DFPlayer_Play_track_UserFolder(uint8_t n_folder , uint8_t n_track) // Выбор трека в папке папке пользователя
{
	Player_Tx_Data[0] = 0x7E; // Старт байт
	Player_Tx_Data[1] = 0xFF; // Версия ПО
	Player_Tx_Data[2] = 0x06; // количество информационных байт
	Player_Tx_Data[3] = 0x0F; // Команда запустить трек в папке пользователя
	Player_Tx_Data[4] = 0x00; // Обратная связь (ожидание подтвер
	
	Player_Tx_Data[5] = n_folder; // Старший байт данных - пользовательская папка
	Player_Tx_Data[6] = n_track; // Номер файла в пользовательской для воспроизвдения 
	
	DFPlayer_DoSum(&Player_Tx_Data[1]); // Расчет контрольной суммы
	
	Player_Tx_Data[9] = 0xEF; // Стоп байт
	
	HAL_UART_Transmit_IT(&huart1, Player_Tx_Data, 10);	
}

/*********************************************************************************************************************************************************************************
*		Файл: PCB_Uni_mp3.c
*		Версия: v1.00
*		Наименование проекта: Плата Uni_mp3
*		Разработал: Тимофеев Д.Г.
*		Организация:
*
*		Описание к файлу: 
*
*
*		Примечания: Проект для работы с платой Uni2-main_v1.0. Получение данных в формате ASCII (три символа).
*
*
********************************************************************************************************************************************************************************/

#include "main.h"
#include "cmsis_os.h"
#include "DFPlayer_Mini.h"
#include "PCB_Uni_mp3.h"

uint8_t MainBoard_Rx_Data[8]; // Массив для принятых данных с ПК (скопированных в функции обратного вызова DMA)

uint16_t count = 0; // Переменная для посчета пришдших пакетов от плеера. Пакет воспроизведение закончено (0x3D) почемуто приходит дважды.

uint8_t num_IRQ = 0; // Переменная для посчета количества вхождений в функцию обратного вызова UART

uint8_t start_st = 0; // Переменная (флаг) для определения  был ли получен старт пакет при вызовах фукции обратного вызова UART

uint8_t ch_tr; // // Переменная для отслеживания изменения номера трека

void LED_MCU_Blink (void) // Функция мигнаия индикаторного светодиода МК (MCU LED)
{
	HAL_GPIO_TogglePin(GPIOC, oLED_Pin);
}

void LED_BUSY_Blink (void)
{
	HAL_GPIO_TogglePin(GPIOB, oBUSY_Pin);
}

void LED_BUSY(uint8_t f) // Функция вкл/откл индкаторного светодиода BUSY
{
	
	if (f == 1)
	{
		HAL_GPIO_WritePin(GPIOB, oBUSY_Pin, GPIO_PIN_SET);
	}
	
		if (f == 0)
	{
		HAL_GPIO_WritePin(GPIOB, oBUSY_Pin, GPIO_PIN_RESET);
	}
		
	
}

void Read_Vol_Pins (void) // Функция чтения состояния пинов для изменения горомкости
{
	
	if (HAL_GPIO_ReadPin(GPIOB, iVolUp_Pin) == 0) //Проверка PORTB 3
		{
			if(DFPlayer1.vol < 31)
			{
				DFPlayer1.vol = DFPlayer1.vol + 1;
			}
		}
		
			if (HAL_GPIO_ReadPin(GPIOA, iVolDownA15_Pin) == 0) //Проверка PORTA 15
		{
			if(DFPlayer1.vol >= 1)
			{
				DFPlayer1.vol = DFPlayer1.vol - 1;
			}
		}
		
			if (HAL_GPIO_ReadPin(GPIOA, iVol_Up_Pin) == 0) //Проверка PORTA 12
		{
			if(DFPlayer1.vol < 31)
			{
				DFPlayer1.vol = DFPlayer1.vol + 1;
			}
		}
		
			if (HAL_GPIO_ReadPin(GPIOA, iVolDown_Pin) == 0) //Проверка PORTA 11
		{
			if(DFPlayer1.vol >= 1)
			{
				DFPlayer1.vol = DFPlayer1.vol - 1;
			}
		}
			
}
#ifdef ASCII_PROTOCOL

uint16_t get_track_MainBoard(void) // Получение номера трека из полученной посылки
{
	uint16_t track = 0;
	
	track = ((MainBoard_Rx_Data[1] - 0x30) * 100) + ((MainBoard_Rx_Data[2] - 0x30) * 10) + (MainBoard_Rx_Data[3] - 0x30);
		
	return track;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // Функция обратного вызова 
{

	if(huart == &huart3) // Посылка с главной платы
	{

		if(MainBoard_Rx[0] == 0xFF) // Если первый [0] байт 0xFF, то начала посылки с номером трека
			{
				start_st = 1;
			}
			
			if (start_st == 1) // Получение посылки с номером трека
			{
			 MainBoard_Rx_Data[num_IRQ] = MainBoard_Rx[0];
				
			 if(num_IRQ < 3)
			{
				num_IRQ = num_IRQ + 1;
			}
			else
			{
				ch_tr = 1;
				DFPlayer1.track_num_MP3 = get_track_MainBoard();
				num_IRQ = 0;
				start_st = 0;
				MainBoard_Rx[0] = 0;
								
			}
			
			}
			
			
			 if (MainBoard_Rx[0] == 'p') // Пауза
			{
				DFPlayer_pause();
				DFPlayer1.DF_LED = 0x00;
				MainBoard_Rx[0] = 0;
				//num_IRQ = 0;
			}
			
			if (MainBoard_Rx[0] == 'r') 
			{
				DFPlayer_Play(); // Продолжить воспроизвдение
				DFPlayer1.DF_LED = 0x01;
				LED_BUSY(1);
				MainBoard_Rx[0] = 0;
				//num_IRQ = 0;
			}
			
			if(MainBoard_Rx[0] == 's')
			{
				DFPlayer_stop(); // Стоп
				DFPlayer1.DF_LED = 0x00;
				MainBoard_Rx[0] = 0;
				//num_IRQ = 0;
			}
			
			HAL_UART_Receive_IT (&huart3, MainBoard_Rx, 1);		
	}
	
	if(huart == &huart1) //Посылка от плеера
	{
		//HAL_UART_DMAPause(&huart1);
		
		HAL_UART_Receive_DMA(&huart1, (uint8_t*) &DFPlayer1_Rx, 10); // Режим normal (не circular)
		
		// устаревший код, был написан исходно при разработке, DFPlayer почему-то посылал два раза посылку об окончании трека
		//if (DFPlayer1_Rx[0] == 0x7E) 
		//{
		//	count = count + 1;
		//	
		//	if (count == 2)
		//	{
		//		char c = '@';
		//		HAL_UART_Transmit_IT(&huart3, (uint8_t*)&c, 1);
		//		
		//		count = 0;
		//		
		//		for (uint8_t i = 0; i < 10; i++)
		//		{
		//			DFPlayer1_Rx[i] = 0x00;
		//		}	
		//	}
		//}
		
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3B)) // Если карта вынута
		{
			DFPlayer1.DF_LED = 0x01;
		}
		// какие-то модули посылают 3A (Pull in) при вставлении карты
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3A)) // Если карта вставлена
		{
			DFPlayer1.DF_LED = 0x00;
		}
		// какие-то посылают 3F (card on-line) при вставлении карты
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3F)) // Если карта вставлена
		{
			DFPlayer1.DF_LED = 0x00;
		}
		
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3D)) // Если трек закончился
		{
			if (DFPlayer1.DF_LED == 1)		// если шло воспроизведение - для отсеивания двойных посылок по окончании трека в некоторых версиях DFPlayer
			{
				char c = '@';
				HAL_UART_Transmit_IT(&huart3, (uint8_t*)&c, 1);
			}
			DFPlayer1.DF_LED = 0x00;
		}
		
	}
}
#endif

#ifdef HEX_PROTOCOL

uint16_t get_track_MainBoard(void) // Получение номера трека из полученной посылки
{
	uint16_t track = 0;
	
	return track;
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // Функция обрабтного вызова 
{

	if(huart == &huart3) // Посылка с главной платы
	{

		if(MainBoard_Rx[0] == 0xFF) // Если первый [0] байт 0xFF, то начала посылки с номером трека
			{
				start_st = 1;
			}
			
			if (start_st == 1) // Получение посылки с номером трека
			{
			 MainBoard_Rx_Data[num_IRQ] = MainBoard_Rx[0];
				
			 if(num_IRQ < 2)
			{
				num_IRQ = num_IRQ + 1;
			}
			else
			{
				ch_tr = 1;
				
				DFPlayer1.Folder = MainBoard_Rx_Data[1];
				DFPlayer1.track_num_MP3 = MainBoard_Rx_Data[2]; // Получение номера папки 
				
#ifdef MENDELEEV_RUN_STRING
				if(MainBoard_Rx_Data[1] <= 99)
				{
					DFPlayer1.track_num_MP3 = (MainBoard_Rx_Data[2] + 1);
				} else
				if(MainBoard_Rx_Data[1] > 99)
				{
					DFPlayer1.Folder = (MainBoard_Rx_Data[1] - 99);
					DFPlayer1.track_num_MP3 = (MainBoard_Rx_Data[2] + 101);
				}
#endif
	      
				
				num_IRQ = 0;
				start_st = 0;
				MainBoard_Rx[0] = 0;
								
			}
			
			}
						
			 if (MainBoard_Rx[0] == 'p') // Пауза
			{
				DFPlayer_pause();
				DFPlayer1.DF_LED = 0x00;
				MainBoard_Rx[0] = 0;
				//num_IRQ = 0;
			}
			
			if (MainBoard_Rx[0] == 'r') 
			{
				DFPlayer_Play(); // Продолжить воспроизвдение
				DFPlayer1.DF_LED = 0x01;
				LED_BUSY(1);
				MainBoard_Rx[0] = 0;
				//num_IRQ = 0;
			}
			
			if(MainBoard_Rx[0] == 's')
			{
				DFPlayer_stop(); // Стоп
				DFPlayer1.DF_LED = 0x00;
				MainBoard_Rx[0] = 0;
				//num_IRQ = 0;
			}
			
			HAL_UART_Receive_IT (&huart3, MainBoard_Rx, 1);		
	}
	
	if(huart == &huart1) //Посылка от плеера
	{
		//HAL_UART_DMAPause(&huart1);
		
		HAL_UART_Receive_DMA(&huart1, (uint8_t*) &DFPlayer1_Rx, 10); // Режим normal (не circular)
		
		// устаревший код, был написан исходно при разработке, DFPlayer почему-то посылал два раза посылку об окончании трека
		//if (DFPlayer1_Rx[0] == 0x7E) 
		//{
		//	count = count + 1;
		//	
		//	if (count == 2)
		//	{
		//		char c = '@';
		//		HAL_UART_Transmit_IT(&huart3, (uint8_t*)&c, 1);
		//		
		//		count = 0;
		//		
		//		for (uint8_t i = 0; i < 10; i++)
		//		{
		//			DFPlayer1_Rx[i] = 0x00;
		//		}	
		//	}
		//}
		
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3B)) // Если карта вынута
		{
			DFPlayer1.DF_LED = 0x01;
		}
		// какие-то модули посылают 3A (Pull in) при вставлении карты
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3A)) // Если карта вставлена
		{
			DFPlayer1.DF_LED = 0x00;
		}
		// какие-то посылают 3F (card on-line) при вставлении карты
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3F)) // Если карта вставлена
		{
			DFPlayer1.DF_LED = 0x00;
		}
		
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3D)) // Если трек закончился
		{
			if (DFPlayer1.DF_LED == 1)		// если шло воспроизведение - для отсеивания двойных посылок по окончании трека в некоторых версиях DFPlayer
			{
				char c = '@';
				HAL_UART_Transmit_IT(&huart3, (uint8_t*)&c, 1);
			}
			DFPlayer1.DF_LED = 0x00;
		}
		
	}
}
#endif



#if defined (PLAY_A4_PAUSE_A7_EN)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // Функция обратного вызова 
{
	if(huart == &huart1) //Посылка от плеера
	{
		//HAL_UART_DMAPause(&huart1);
		
		HAL_UART_Receive_DMA(&huart1, (uint8_t*) &DFPlayer1_Rx, 10); // Режим normal (не circular)
		
		// устаревший код, был написан исходно при разработке, DFPlayer почему-то посылал два раза посылку об окончании трека
		//if (DFPlayer1_Rx[0] == 0x7E) 
		//{
		//	count = count + 1;
		//	
		//	if (count == 2)
		//	{
		//		char c = '@';
		//		HAL_UART_Transmit_IT(&huart3, (uint8_t*)&c, 1);
		//		
		//		count = 0;
		//		
		//		for (uint8_t i = 0; i < 10; i++)
		//		{
		//			DFPlayer1_Rx[i] = 0x00;
		//		}	
		//	}
		//}
		
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3B)) // Если карта вынута
		{
			DFPlayer1.DF_LED = 0x01;
		}
		// какие-то модули посылают 3A (Pull in) при вставлении карты
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3A)) // Если карта вставлена
		{
			DFPlayer1.DF_LED = 0x00;
		}
		// какие-то посылают 3F (card on-line) при вставлении карты
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3F)) // Если карта вставлена
		{
			DFPlayer1.DF_LED = 0x00;
		}
		
		if ((DFPlayer1_Rx[0] == 0x7E) && (DFPlayer1_Rx[3] == 0x3D)) // Если трек закончился
		{
			if (DFPlayer1.DF_LED == 1)		// если шло воспроизведение - для отсеивания двойных посылок по окончании трека в некоторых версиях DFPlayer
			{
				//char c = '@';
				//HAL_UART_Transmit_IT(&huart3, (uint8_t*)&c, 1);
#if defined (REPEAT)
				ch_tr = 1;	// для повторного запуска трека
#endif
			}
			DFPlayer1.DF_LED = 0x00;
		}
		
	}
}
#endif

void Read_PinPlayStop (void) // Чтение пин
{
#if defined(ZD) || defined(A4_LOW_LEV_CONT)
	static uint8_t s_push = 0;
#endif
#ifdef ZD

if (HAL_GPIO_ReadPin(GPIOA, iPlayStop_Pin) == 1)
{
	if (s_push == 0)
	{
		s_push = 1;
		DFPlayer_Play_track_MP3(1);
	}
	if (s_push == 1)
	{
		DFPlayer_Play();
	}

}

if (HAL_GPIO_ReadPin(GPIOA, iPlayStop_Pin) == 0)
{
	DFPlayer_stop();	
}

#endif

#ifdef PLAY_A4_PAUSE_A7_EN

static uint8_t StartStop = 0, StartPause = 0;
static uint8_t s_push4 = 0, s_push7 = 0;

if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == 0)
{
	s_push4++;
	
	if (s_push4 == 1)
	{
		if (StartStop == 0) // Нечетное по счету нажатие
		{
			//DFPlayer_Play_track_MP3(1);
			ch_tr = 1;//DFPlayer_Play();
			StartStop = 1;
		}
		else // Четное по счету нажатие
		{
			DFPlayer_stop(); // Остановить воспроизведение
			StartStop = 0;
			DFPlayer1.DF_LED = 0;
		}
	}
} else
{
	s_push4 = 0;
}

if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7) == 0)
{
	s_push7++;
	
	if (s_push7 == 1)
	{
		if (StartPause == 0) // Нечетное по счету нажатие
		{
			//DFPlayer_Play_track_MP3(1); // Воспроивести первый трек
			DFPlayer_Play();
			StartPause = 1;
			DFPlayer1.DF_LED = 1;
		}
		else // Четное по счету нажатие
		{
			//DFPlayer_stop(); // Остановить воспроизведение
			DFPlayer_pause(); // Пауза
			StartPause = 0;
			DFPlayer1.DF_LED = 0;
		}
	}
} else
{
	s_push7 = 0;
}

#endif

#ifdef A4_LOW_LEV_CONT

	if (HAL_GPIO_ReadPin(GPIOA, iPlayStop_Pin) == 0)
	{
		if (s_push == 0)
		{
			s_push = 1;
			DFPlayer_Play_track_MP3(1);
		}
		if (s_push == 1)
		{
			DFPlayer_Play();
		}
	
	}

	if (HAL_GPIO_ReadPin(GPIOA, iPlayStop_Pin) == 1)
	{
		DFPlayer_stop();
	}

#endif

}

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * 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 "FreeRTOS.h"
#include "task.h"
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */     

/* 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 ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

/* USER CODE END Variables */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
   
/* USER CODE END FunctionPrototypes */

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
     
/* USER CODE END Application */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : stm32f1xx_hal_msp.c
  * Description        : This file provides code for the MSP Initialization 
  *                      and de-Initialization codes.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * 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"
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */
extern DMA_HandleTypeDef hdma_usart1_rx;

extern DMA_HandleTypeDef hdma_usart3_rx;

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */

/* USER CODE END TD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
 
/* USER CODE END Define */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */

/* USER CODE END Macro */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */

/* USER CODE END ExternalFunctions */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */
                        
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
                    /**
  * Initializes the Global MSP.
  */
void HAL_MspInit(void)
{
  /* USER CODE BEGIN MspInit 0 */

  /* USER CODE END MspInit 0 */

  __HAL_RCC_AFIO_CLK_ENABLE();
  __HAL_RCC_PWR_CLK_ENABLE();

  /* System interrupt init*/
  /* PendSV_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0);

  /** NOJTAG: JTAG-DP Disabled and SW-DP Enabled 
  */
  __HAL_AFIO_REMAP_SWJ_NOJTAG();

  /* USER CODE BEGIN MspInit 1 */

  /* USER CODE END MspInit 1 */
}

/**
* @brief TIM_PWM MSP Initialization
* This function configures the hardware resources used in this example
* @param htim_pwm: TIM_PWM handle pointer
* @retval None
*/
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
{
  if(htim_pwm->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspInit 0 */

  /* USER CODE END TIM3_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_TIM3_CLK_ENABLE();
  /* USER CODE BEGIN TIM3_MspInit 1 */

  /* USER CODE END TIM3_MspInit 1 */
  }

}

void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(htim->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspPostInit 0 */

  /* USER CODE END TIM3_MspPostInit 0 */
  
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**TIM3 GPIO Configuration    
    PA6     ------> TIM3_CH1 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN TIM3_MspPostInit 1 */

  /* USER CODE END TIM3_MspPostInit 1 */
  }

}
/**
* @brief TIM_PWM MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param htim_pwm: TIM_PWM handle pointer
* @retval None
*/
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm)
{
  if(htim_pwm->Instance==TIM3)
  {
  /* USER CODE BEGIN TIM3_MspDeInit 0 */

  /* USER CODE END TIM3_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM3_CLK_DISABLE();
  /* USER CODE BEGIN TIM3_MspDeInit 1 */

  /* USER CODE END TIM3_MspDeInit 1 */
  }

}

/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(huart->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();
  
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration    
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 DMA Init */
    /* USART1_RX Init */
    hdma_usart1_rx.Instance = DMA1_Channel5;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_NORMAL;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspInit 1 */

  /* USER CODE END USART1_MspInit 1 */
  }
  else if(huart->Instance==USART3)
  {
  /* USER CODE BEGIN USART3_MspInit 0 */

  /* USER CODE END USART3_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART3_CLK_ENABLE();
  
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**USART3 GPIO Configuration    
    PB10     ------> USART3_TX
    PB11     ------> USART3_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* USART3 DMA Init */
    /* USART3_RX Init */
    hdma_usart3_rx.Instance = DMA1_Channel3;
    hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart3_rx.Init.Mode = DMA_NORMAL;
    hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(huart,hdmarx,hdma_usart3_rx);

    /* USART3 interrupt Init */
    HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USART3_IRQn);
  /* USER CODE BEGIN USART3_MspInit 1 */

  /* USER CODE END USART3_MspInit 1 */
  }

}

/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
  if(huart->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspDeInit 0 */

  /* USER CODE END USART1_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART1_CLK_DISABLE();
  
    /**USART1 GPIO Configuration    
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX 
    */
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);

    /* USART1 DMA DeInit */
    HAL_DMA_DeInit(huart->hdmarx);

    /* USART1 interrupt DeInit */
    HAL_NVIC_DisableIRQ(USART1_IRQn);
  /* USER CODE BEGIN USART1_MspDeInit 1 */

  /* USER CODE END USART1_MspDeInit 1 */
  }
  else if(huart->Instance==USART3)
  {
  /* USER CODE BEGIN USART3_MspDeInit 0 */

  /* USER CODE END USART3_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_USART3_CLK_DISABLE();
  
    /**USART3 GPIO Configuration    
    PB10     ------> USART3_TX
    PB11     ------> USART3_RX 
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11);

    /* USART3 DMA DeInit */
    HAL_DMA_DeInit(huart->hdmarx);

    /* USART3 interrupt DeInit */
    HAL_NVIC_DisableIRQ(USART3_IRQn);
  /* USER CODE BEGIN USART3_MspDeInit 1 */

  /* USER CODE END USART3_MspDeInit 1 */
  }

}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    stm32f1xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * 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 "stm32f1xx_it.h"
#include "FreeRTOS.h"
#include "task.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */

/* USER CODE END TD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
 
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* External variables --------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart3_rx;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN EV */

/* USER CODE END EV */

/******************************************************************************/
/*           Cortex-M3 Processor Interruption and Exception Handlers          */ 
/******************************************************************************/
/**
  * @brief This function handles Non maskable interrupt.
  */
void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */

  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */

  /* USER CODE END NonMaskableInt_IRQn 1 */
}

/**
  * @brief This function handles Hard fault interrupt.
  */
void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Memory management fault.
  */
void MemManage_Handler(void)
{
  /* USER CODE BEGIN MemoryManagement_IRQn 0 */

  /* USER CODE END MemoryManagement_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
    /* USER CODE END W1_MemoryManagement_IRQn 0 */
  }
}

/**
  * @brief This function handles Prefetch fault, memory access fault.
  */
void BusFault_Handler(void)
{
  /* USER CODE BEGIN BusFault_IRQn 0 */

  /* USER CODE END BusFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
    /* USER CODE END W1_BusFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Undefined instruction or illegal state.
  */
void UsageFault_Handler(void)
{
  /* USER CODE BEGIN UsageFault_IRQn 0 */

  /* USER CODE END UsageFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
    /* USER CODE END W1_UsageFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Debug monitor.
  */
void DebugMon_Handler(void)
{
  /* USER CODE BEGIN DebugMonitor_IRQn 0 */

  /* USER CODE END DebugMonitor_IRQn 0 */
  /* USER CODE BEGIN DebugMonitor_IRQn 1 */

  /* USER CODE END DebugMonitor_IRQn 1 */
}

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
#if (INCLUDE_xTaskGetSchedulerState == 1 )
  if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
  {
#endif /* INCLUDE_xTaskGetSchedulerState */
  xPortSysTickHandler();
#if (INCLUDE_xTaskGetSchedulerState == 1 )
  }
#endif /* INCLUDE_xTaskGetSchedulerState */
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

/******************************************************************************/
/* STM32F1xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f1xx.s).                    */
/******************************************************************************/

/**
  * @brief This function handles DMA1 channel3 global interrupt.
  */
void DMA1_Channel3_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel3_IRQn 0 */

  /* USER CODE END DMA1_Channel3_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart3_rx);
  /* USER CODE BEGIN DMA1_Channel3_IRQn 1 */

  /* USER CODE END DMA1_Channel3_IRQn 1 */
}

/**
  * @brief This function handles DMA1 channel5 global interrupt.
  */
void DMA1_Channel5_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel5_IRQn 0 */

  /* USER CODE END DMA1_Channel5_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart1_rx);
  /* USER CODE BEGIN DMA1_Channel5_IRQn 1 */

  /* USER CODE END DMA1_Channel5_IRQn 1 */
}

/**
  * @brief This function handles USART1 global interrupt.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

/**
  * @brief This function handles USART3 global interrupt.
  */
void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */

  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */

  /* USER CODE END USART3_IRQn 1 */
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/**
  ******************************************************************************
  * @file    system_stm32f1xx.c
  * @author  MCD Application Team
  * @brief   CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.
  * 
  * 1.  This file provides two functions and one global variable to be called from 
  *     user application:
  *      - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
  *                      factors, AHB/APBx prescalers and Flash settings). 
  *                      This function is called at startup just after reset and 
  *                      before branch to main program. This call is made inside
  *                      the "startup_stm32f1xx_xx.s" file.
  *
  *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
  *                                  by the user application to setup the SysTick 
  *                                  timer or configure other parameters.
  *                                     
  *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
  *                                 be called whenever the core clock is changed
  *                                 during program execution.
  *
  * 2. After each device reset the HSI (8 MHz) is used as system clock source.
  *    Then SystemInit() function is called, in "startup_stm32f1xx_xx.s" file, to
  *    configure the system clock before to branch to main program.
  *
  * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depending on
  *    the product used), refer to "HSE_VALUE". 
  *    When HSE is used as system clock source, directly or through PLL, and you
  *    are using different crystal you have to adapt the HSE value to your own
  *    configuration.
  *        
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/** @addtogroup CMSIS
  * @{
  */

/** @addtogroup stm32f1xx_system
  * @{
  */  
  
/** @addtogroup STM32F1xx_System_Private_Includes
  * @{
  */

#include "stm32f1xx.h"

/**
  * @}
  */

/** @addtogroup STM32F1xx_System_Private_TypesDefinitions
  * @{
  */

/**
  * @}
  */

/** @addtogroup STM32F1xx_System_Private_Defines
  * @{
  */

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE               8000000U /*!< Default value of the External oscillator in Hz.
                                                This value can be provided and adapted by the user application. */
#endif /* HSE_VALUE */

#if !defined  (HSI_VALUE)
  #define HSI_VALUE               8000000U /*!< Default value of the Internal oscillator in Hz.
                                                This value can be provided and adapted by the user application. */
#endif /* HSI_VALUE */

/*!< Uncomment the following line if you need to use external SRAM  */ 
#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
/* #define DATA_IN_ExtSRAM */
#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */

/* Note: Following vector table addresses must be defined in line with linker
         configuration. */
/*!< Uncomment the following line if you need to relocate the vector table
     anywhere in Flash or Sram, else the vector table is kept at the automatic
     remap of boot address selected */
/* #define USER_VECT_TAB_ADDRESS */

#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line if you need to relocate your vector Table
     in Sram else user remap will be done in Flash. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS   SRAM_BASE       /*!< Vector Table base address field.
                                                     This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET         0x00000000U     /*!< Vector Table base offset field.
                                                     This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS   FLASH_BASE      /*!< Vector Table base address field.
                                                     This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET         0x00000000U     /*!< Vector Table base offset field.
                                                     This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */

/******************************************************************************/

/**
  * @}
  */

/** @addtogroup STM32F1xx_System_Private_Macros
  * @{
  */

/**
  * @}
  */

/** @addtogroup STM32F1xx_System_Private_Variables
  * @{
  */

  /* This variable is updated in three ways:
      1) by calling CMSIS function SystemCoreClockUpdate()
      2) by calling HAL API function HAL_RCC_GetHCLKFreq()
      3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency 
         Note: If you use this function to configure the system clock; then there
               is no need to call the 2 first functions listed above, since SystemCoreClock
               variable is updated automatically.
  */
uint32_t SystemCoreClock = 16000000;
const uint8_t AHBPrescTable[16U] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8U] =  {0, 0, 0, 0, 1, 2, 3, 4};

/**
  * @}
  */

/** @addtogroup STM32F1xx_System_Private_FunctionPrototypes
  * @{
  */

#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
#ifdef DATA_IN_ExtSRAM
  static void SystemInit_ExtMemCtl(void); 
#endif /* DATA_IN_ExtSRAM */
#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */

/**
  * @}
  */

/** @addtogroup STM32F1xx_System_Private_Functions
  * @{
  */

/**
  * @brief  Setup the microcontroller system
  *         Initialize the Embedded Flash Interface, the PLL and update the 
  *         SystemCoreClock variable.
  * @note   This function should be used only after reset.
  * @param  None
  * @retval None
  */
void SystemInit (void)
{
#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl(); 
  #endif /* DATA_IN_ExtSRAM */
#endif 

  /* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
  SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#endif /* USER_VECT_TAB_ADDRESS */
}

/**
  * @brief  Update SystemCoreClock variable according to Clock Register Values.
  *         The SystemCoreClock variable contains the core clock (HCLK), it can
  *         be used by the user application to setup the SysTick timer or configure
  *         other parameters.
  *           
  * @note   Each time the core clock (HCLK) changes, this function must be called
  *         to update SystemCoreClock variable value. Otherwise, any configuration
  *         based on this variable will be incorrect.         
  *     
  * @note   - The system frequency computed by this function is not the real 
  *           frequency in the chip. It is calculated based on the predefined 
  *           constant and the selected clock source:
  *             
  *           - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
  *                                              
  *           - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
  *                          
  *           - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) 
  *             or HSI_VALUE(*) multiplied by the PLL factors.
  *         
  *         (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value
  *             8 MHz) but the real value may vary depending on the variations
  *             in voltage and temperature.   
  *    
  *         (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value
  *              8 MHz or 25 MHz, depending on the product used), user has to ensure
  *              that HSE_VALUE is same as the real frequency of the crystal used.
  *              Otherwise, this function may have wrong result.
  *                
  *         - The result of this function could be not correct when using fractional
  *           value for HSE crystal.
  * @param  None
  * @retval None
  */
void SystemCoreClockUpdate (void)
{
  uint32_t tmp = 0U, pllmull = 0U, pllsource = 0U;

#if defined(STM32F105xC) || defined(STM32F107xC)
  uint32_t prediv1source = 0U, prediv1factor = 0U, prediv2factor = 0U, pll2mull = 0U;
#endif /* STM32F105xC */

#if defined(STM32F100xB) || defined(STM32F100xE)
  uint32_t prediv1factor = 0U;
#endif /* STM32F100xB or STM32F100xE */
    
  /* Get SYSCLK source -------------------------------------------------------*/
  tmp = RCC->CFGR & RCC_CFGR_SWS;
  
  switch (tmp)
  {
    case 0x00U:  /* HSI used as system clock */
      SystemCoreClock = HSI_VALUE;
      break;
    case 0x04U:  /* HSE used as system clock */
      SystemCoreClock = HSE_VALUE;
      break;
    case 0x08U:  /* PLL used as system clock */

      /* Get PLL clock source and multiplication factor ----------------------*/
      pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;
      pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
      
#if !defined(STM32F105xC) && !defined(STM32F107xC)      
      pllmull = ( pllmull >> 18U) + 2U;
      
      if (pllsource == 0x00U)
      {
        /* HSI oscillator clock divided by 2 selected as PLL clock entry */
        SystemCoreClock = (HSI_VALUE >> 1U) * pllmull;
      }
      else
      {
 #if defined(STM32F100xB) || defined(STM32F100xE)
       prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U;
       /* HSE oscillator clock selected as PREDIV1 clock entry */
       SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; 
 #else
        /* HSE selected as PLL clock entry */
        if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET)
        {/* HSE oscillator clock divided by 2 */
          SystemCoreClock = (HSE_VALUE >> 1U) * pllmull;
        }
        else
        {
          SystemCoreClock = HSE_VALUE * pllmull;
        }
 #endif
      }
#else
      pllmull = pllmull >> 18U;
      
      if (pllmull != 0x0DU)
      {
         pllmull += 2U;
      }
      else
      { /* PLL multiplication factor = PLL input clock * 6.5 */
        pllmull = 13U / 2U; 
      }
            
      if (pllsource == 0x00U)
      {
        /* HSI oscillator clock divided by 2 selected as PLL clock entry */
        SystemCoreClock = (HSI_VALUE >> 1U) * pllmull;
      }
      else
      {/* PREDIV1 selected as PLL clock entry */
        
        /* Get PREDIV1 clock source and division factor */
        prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC;
        prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1U;
        
        if (prediv1source == 0U)
        { 
          /* HSE oscillator clock selected as PREDIV1 clock entry */
          SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;          
        }
        else
        {/* PLL2 clock selected as PREDIV1 clock entry */
          
          /* Get PREDIV2 division factor and PLL2 multiplication factor */
          prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4U) + 1U;
          pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8U) + 2U; 
          SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;                         
        }
      }
#endif /* STM32F105xC */ 
      break;

    default:
      SystemCoreClock = HSI_VALUE;
      break;
  }
  
  /* Compute HCLK clock frequency ----------------*/
  /* Get HCLK prescaler */
  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)];
  /* HCLK clock frequency */
  SystemCoreClock >>= tmp;  
}

#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)
/**
  * @brief  Setup the external memory controller. Called in startup_stm32f1xx.s 
  *          before jump to __main
  * @param  None
  * @retval None
  */ 
#ifdef DATA_IN_ExtSRAM
/**
  * @brief  Setup the external memory controller. 
  *         Called in startup_stm32f1xx_xx.s/.c before jump to main.
  *         This function configures the external SRAM mounted on STM3210E-EVAL
  *         board (STM32 High density devices). This SRAM will be used as program
  *         data memory (including heap and stack).
  * @param  None
  * @retval None
  */ 
void SystemInit_ExtMemCtl(void) 
{
  __IO uint32_t tmpreg;
  /*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is 
    required, then adjust the Register Addresses */

  /* Enable FSMC clock */
  RCC->AHBENR = 0x00000114U;

  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_FSMCEN);
  
  /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */
  RCC->APB2ENR = 0x000001E0U;
  
  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPDEN);

  (void)(tmpreg);
  
/* ---------------  SRAM Data lines, NOE and NWE configuration ---------------*/
/*----------------  SRAM Address lines configuration -------------------------*/
/*----------------  NOE and NWE configuration --------------------------------*/  
/*----------------  NE3 configuration ----------------------------------------*/
/*----------------  NBL0, NBL1 configuration ---------------------------------*/
  
  GPIOD->CRL = 0x44BB44BBU;  
  GPIOD->CRH = 0xBBBBBBBBU;

  GPIOE->CRL = 0xB44444BBU;  
  GPIOE->CRH = 0xBBBBBBBBU;

  GPIOF->CRL = 0x44BBBBBBU;  
  GPIOF->CRH = 0xBBBB4444U;

  GPIOG->CRL = 0x44BBBBBBU;  
  GPIOG->CRH = 0x444B4B44U;
   
/*----------------  FSMC Configuration ---------------------------------------*/  
/*----------------  Enable FSMC Bank1_SRAM Bank ------------------------------*/
  
  FSMC_Bank1->BTCR[4U] = 0x00001091U;
  FSMC_Bank1->BTCR[5U] = 0x00110212U;
}
#endif /* DATA_IN_ExtSRAM */
#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */

/**
  * @}
  */

/**
  * @}
  */
  
/**
  * @}
  */    
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/