Обучение STM32. Подключаем к микроконтроллеру STM32 семисегментный индикатор

В этом уроке по микроконтроллеру STM32 вы научитесь:

  • подключать семисегментный индикатор
  • конфигурировать порты на выход в CubeMX
  • использовать HAL функции для управления сегментами индикатора

Семисегментный индикатор с общим анодом SA56-11SRWA 

Рис.1. Семисегментный индикатор с общим анодом SA56-11SRWA Семисегментные индикаторы состоят из светодиодов, подключенных катодами или анодами к общей шине. Для индикаторов с общим катодом на общей шине должен быть 0, для индикаторов с общим анодом на общую шину необходимо подавать плюс. Рассмотрим индикатор с общим анодом модели SA56-11SRWA: семь сегментов и один символ точки. Это очень дешевый вариант взаимодействия с пользователем.

 

 

 

 

 

 

Подключение семисегментного индикатора

Рис.2. Семисегментный индикатор с общим анодом SA56-11SRWA   Каждый светодиод-сегмент , необходимо подключать через токоограничительный резистор, чтобы не спалить светодиод или порт микроконтроллера при длительной работе. Можно было бы поставить один резистор на общую шину, но тогда яркость сегментов была бы непостоянной из-за разных комбинаций включения сегментов. Короче, на кривой козе не объедешь. Поэтому сама-собой рождается такая схема подключения.

 

 

Рис.3. Схема подключения семисегментного индикатора к микроконтроллеру STM32 Согласно этой схеме на порт STM32 будет подаваться логическая единица 3.3 В за вычетом падения напряжения на светодиоде и резисторе. Поэтому для включения светодиода необходимо подавать в порт логический 0 с помощью нашей программы, для получения разности потенциалов на светодиоде. номинал резистора необходимо выбирать в пределах 500 - 1000 Ом. Светодиоды-сегменты имеют имена a, b, c, d, e, f, g. Исходя из этого будем формировать определенные символы на индикаторе. Отвлечемся теперь на железную часть нашей схемы. Подключение индикатора к микроконтроллеру кажется хаотичным, но это получается в основном из-за использования плоского кабеля.

 

 

 

 

Рис.4. Микроконтроллер STM32 На отладочной плате STM32VLDISCOVERY с микроконтроллером STM32F100RBT6B выберем такое расположение выводов, которое позволило бы подключить плоский кабель с разъемом типа HU. Ради эксперимента и запары ради возъмем следующий последовательный ряд выводов: PA14, PA15, PC10, PC11, PC12, PD2, PB3, PB4. По документации на эту отладочную плату выводы PA14, PA15, PB3, PB4 используются по умолчанию для JTAG-интерфейса. Поэтому эти порты не удастся использовать для управления просто так. Для его отключения JTAG-интерфейса придется воспользоваться специальной HAL-овской функцией __HAL_AFIO_REMAP_SWJ_DISABLE() после инициализации портов в программе.

 

Настройка портов в CubeMX

Рис.5. Настройка выходов микроконтроллера STM32 в CubeMX Перейдем теперь в CubeMX, где сначала выбираем тип нашего микроконтроллера - STM32F100RBT6B. Перейдем теперь на вкладку Pinout и включим порты PA14, PA15, PC10, PC11, PC12, PD2, PB3, PB4 на выход. Порт PB4 можно было в принципе не выбирать - на нем "висит" функция NJTRST (железный инверсный JTAG, который видимо является особенностью отладочной платы - его не изменить). Но ради изучения надо об  этом знать.

 

Рис.6. Конфигурирование выводов микроконтроллера  Перейдем на вкладку Configuration и проверим конфигурацию модуля GPIO. Все порты должны быть сконфигурированы по умолчанию на низкий выходной уровень (GPIO output level - Low), не притянутые ни в земле ни к питанию (Output Push Pull) и на низкой выходной частоте функционирования (Maximum output level - Low). Все рабочие уровни на портах будем делать программно.

 

Остальные настройки оставим без изменений и сгенерируем код, например для KEIL. В папке Src появился основной файл main.c, вспомогательный файл конфигурирования периферии stm32f1xx_hal_msp.c и файл прерываний stm32f1xx_it.c. Нас будет интересовать только файл main.c.

 

Программирование семисегментного индикатора

Откроем файл main.c. В нем для начала не забудем в функции main() выключить JTAG с помощью функции __HAL_AFIO_REMAP_SWJ_DISABLE(). Правда, эта функция подлая - при ее включении прошить микроконтроллер удастся только при нажатой на 2-3 секунды кнопки RESET на отладочной плате. Это соответствует режиму Connect Under Reset для ST-LINK v.2. Но наша отладочная плата STM32VLDISCOVERY имеет первую версию ST-LINK, в ней нет софтового режима Connect Under Reset и поэтому RESET нужно делать ручками...

Полный код программы приводится ниже.


/* main.c */
/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  *
  * COPYRIGHT(c) 2016 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
 
/* USER CODE BEGIN Includes */
 
/* USER CODE END Includes */
 
/* Private variables ---------------------------------------------------------*/
 
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
 
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
void setnumber (uint8_t number)
{
	switch (number)
	{
		case 0x30:
			{
				//HAL_GPIO_WritePin(GPIOA, GPIO_PIN_14, GPIO_PIN_RESET); //dot
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);  //G
				break;
			}
 
		case 0x31:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_SET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);  //G
				break;
			}
 
		case 0x32:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x33:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x34:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_SET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x35:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x36:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x37:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_SET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);  //G
				break;
			}
 
		case 0x38:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x39:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
	}
}
/* USER CODE END PFP */
 
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
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();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
 
  /* USER CODE BEGIN 2 */
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	__HAL_AFIO_REMAP_SWJ_DISABLE();
 
  while (1)
  {	
		setnumber(0x30);
		HAL_Delay(500);
 
		setnumber(0x31);
		HAL_Delay(500);
 
		setnumber(0x32);
		HAL_Delay(500);
 
		setnumber(0x33);
		HAL_Delay(500);
 
		setnumber(0x34);
		HAL_Delay(500);
 
		setnumber(0x35);
		HAL_Delay(500);
 
		setnumber(0x36);
		HAL_Delay(500);
 
		setnumber(0x37);
		HAL_Delay(500);
 
		setnumber(0x38);
		HAL_Delay(500);
 
		setnumber(0x39);
		HAL_Delay(500);
 
  /* USER CODE END WHILE */
 
  /* USER CODE BEGIN 3 */
 
  }
  /* USER CODE END 3 */
 
}
 
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
 
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
 
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 16;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
 
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
 
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
 
  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
 
/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_RESET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3|GPIO_PIN_4, GPIO_PIN_RESET);
 
  /*Configure GPIO pins : PA14 PA15 */
  GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
  /*Configure GPIO pins : PC10 PC11 PC12 */
  GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
  /*Configure GPIO pin : PD2 */
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
  /*Configure GPIO pins : PB3 PB4 */
  GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
}
 
/* USER CODE BEGIN 4 */
 
/* USER CODE END 4 */
 
#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,
    ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
 
}
 
#endif
 
/**
  * @}
  */ 
 
/**
  * @}
*/ 
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
 
    

В раздел пользовательских функций /* USER CODE BEGIN PFP */ ... /* USER CODE END PFP */ добавим функцию setnumber (uint8_t number) включения нужных сегментов индикатора в зависимости от входного аргумента - числа. Запись в этот раздел позволит сохранить наш код при последующей регенарации кода из CUBE MX.


/* main.c */

void setnumber (uint8_t number)
{
	switch (number)
	{
		case 0x30:
			{
				//HAL_GPIO_WritePin(GPIOA, GPIO_PIN_14, GPIO_PIN_RESET); //dot
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);  //G
				break;
			}
 
		case 0x31:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_SET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);  //G
				break;
			}
 
		case 0x32:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x33:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x34:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_SET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x35:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x36:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x37:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_SET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_SET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);  //G
				break;
			}
 
		case 0x38:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
 
		case 0x39:
			{
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); //A
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET); //B
				HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //C
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_11, GPIO_PIN_RESET); //D
				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); //E
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, GPIO_PIN_RESET);	//F
				HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);  //G
				break;
			}
	}
}


Рис.7. Переключение цифр на семисегментном индикаторе от 0 до 9  Для наглядности, в качестве аргумента функции setnumber используются ASCII коды символов. Например, ASCII код 0x30 означает 0, код 0x31 означает 1. Таким образом, можно сформировать символы алфавита (например, код 0x41 означал бы символ A) для прямого взаимодействия с UART. Но все-таки семисегментный индикатор очень грубое устройство. Результатом работы будет переключение цифр с 0 до 9 с интервалом 500 мс.

Код проекта доступен по кнопке Скачать пример вверху урока.


Поделиться ссылкой на статью

CADLife - лучший инженерный опыт, бесплатные уроки и обучение Solidworks, Creo, Pro/Engineer, STM32

Комментарии к статье

1 год назад

116359321479032058601

1 год назад
Спасибо! Хотелось бы статью по использованию мануала по HAL.

Администратор

1 год назад
1 год назад отредактировал Администратор Цитата
Первый раз слышу про мануал по HAL. Все функции HAL (а их очень много) доступны (например, в KEIL) по нажатию CTRL+Пробел и далее вводим слово HAL или __HAL - и начинаем выбирать нужные нам функции. Если функция выбрана, нажимаем правую кнопку мыши на этой функции и в меню выбираем Go To Definition или Go To Reference. При этом переходим или в саму функцию или в ее описание. С помощью таких переходов легко проследить, откуда что берется и как все работает. Вот и весь мануал.
11 месяцев назад
1.Мануалы лежат на сайте ST.

2.Вместо case было бы красивее загнать вариации для цифр семисегментного индикатора в массив и далее выбирать их по индексу. Итоговый код получился бы на порядок короче и читабельнее.

Администратор

11 месяцев назад
1. Мануалы и вправду есть!
http://www.st.com/content/ccc/resource/technical/document/user_manual/72/52/cc/53/05/e3/4c/98/DM00154093.pdf/files/DM00154093.pdf/jcr:content/translations/en.DM00154093.pdf
Но они не очень информативны.

2. Для начинающих это самый простой способ понять. Массив возможен при использовании одного порта - чтобы непосредственно загонять туда число, а при использовании разных портов как в этой статье массив не подойдет.
10 месяцев назад
1. Недостающую информацию ищем в исходниках.
2. Не вижу проблем и с использованием различных портов в одном массиве, да хоть ста портов одновременно. Массив будет чуточку сложнее не более того, но результирующий код всё же значительно короче.

Написать ответ...