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

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование микроконтроллеров » Narod Stream. CMSIS. » Урок 2. stm32407 Бегущие огни. STM32F4DISCOVERY.


Урок 2. stm32407 Бегущие огни. STM32F4DISCOVERY.

Сообщений 1 страница 4 из 4

1

Второй урок уже более сложный и вариантов реализации будет четыре.

Ссылка на оригинал: https://www.youtube.com/watch?v=zcoIPwW … mp;index=2

ВАРИАНТ №1.

Вариант реализации точно такой же как у автора видео.
Недостатки варианта:
- задержка блокирующая. Значение задержки нужно угадывать. 

Вполне рабочий вариант, но в нем не используються аппаратные возможности МК.

Код:
/* Includes */
#include "stm32f4xx.h"

/* Private macro */

// гасим все светодиоды
#define  LED_CLR_ALL           GPIOD->BSRR = GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15
// включаем соотв.светодиод
#define  LED1_SET                GPIOD->BSRR = GPIO_BSRR_BS_12
#define  LED2_SET                GPIOD->BSRR = GPIO_BSRR_BS_13
#define  LED3_SET                GPIOD->BSRR = GPIO_BSRR_BS_14
#define  LED4_SET                GPIOD->BSRR = GPIO_BSRR_BS_15
#define  DELAY_INIT_CNT          500000

/* Private variables */
/* Private function prototypes */
/* Private functions */
void RCC_Init(void);
void GPIO_Init(void);
void Delay(__IO uint32_t tDelay);



void RCC_Init(void)
{
  RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN;  // включаем тактирование GPIOD
}

void GPIO_Init(void)
{
  GPIOD->MODER = GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 | GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0;  // настраиваем PD12, PD13, PD14, PD15 как "двухтактный выход общего назначения"
}

// блокирующая задержка
void Delay(__IO uint32_t tDelay)
{
  while(tDelay--);
}

int main(void)
{
  RCC_Init();
  GPIO_Init();

  while(1)
  {
   LED_CLR_ALL;  
   LED1_SET;
   Delay(DELAY_INIT_CNT);

   LED_CLR_ALL;
   LED2_SET;
   Delay(DELAY_INIT_CNT);

   LED_CLR_ALL;
   LED3_SET;
   Delay(DELAY_INIT_CNT);

   LED_CLR_ALL;
   LED4_SET;
   Delay(DELAY_INIT_CNT);
  }
}

0

2

ВАРИАНТ №2.

Второй вариант отличаеться использованием точной задержки с использованием модуля ядра DWT, но задержка осталась блокирующая и использовать ее нужно по случаю.
Были написаны соответствующие модули для реализации функций задержки.

F4xx_Delay.h

Код:
/*
 * F4xx_Delay.h
 *
 *  Created on: 31 янв. 2018 г.
 *      Author: Home
 */

#ifndef F4XX_DELAY_H_
#define F4XX_DELAY_H_

#include <F4xx_DWT.h>

// задержка в микросекундах
void Delay_us(__IO uint32_t tDelay);

// задержка в милисекундах
void Delay_ms(__IO uint32_t tDelay);

#endif /* F4XX_DELAY_H_ */

F4xx_Delay.с

Код:
/*
 * F4xx_Delay.c
 *
 *  Created on: 31 янв. 2018 г.
 *      Author: Home
 */

#include <F4xx_Delay.h>


// задержка в микросекундах
void Delay_us(__IO uint32_t tDelay)
{
  DWT->CYCCNT = 0;
  tDelay = tDelay * (SYS_CLK /1000000);
  while (DWT->CYCCNT < tDelay);
}

// задержка в милисекундах
void Delay_ms(__IO uint32_t tDelay)
{
  DWT->CYCCNT = 0;
  tDelay = tDelay * (SYS_CLK /1000);
  while (DWT->CYCCNT < tDelay);
}

Также появился хедер main.h там будут общие определения

main.h

Код:
/*
 * main.h
 *
 *  Created on: 31 янв. 2018 г.
 *      Author: Home
 */

#ifndef MAIN_H_
#define MAIN_H_

#include "stm32f4xx.h"

// системная частота в герцах
#define  SYS_CLK           16000000

#endif /* MAIN_H_ */

также создал модуль для работы с DWT, создал его специально в отдельном файле для отделения и возможности наращиания функционала.

F4xx_DWT.h

Код:
/*
 * F4xx_DWT.h
 *
 *  Created on: 31 янв. 2018 г.
 *      Author: Home
 */

#ifndef F4XX_DWT_H_
#define F4XX_DWT_H_

#include <main.h>

void DWT_CYC_Counter_Enable(void);

#endif /* F4XX_DWT_H_ */

F4xx_DWT.с

Код:
/*
 * F4xx_DWT.c
 *
 *  Created on: 31 янв. 2018 г.
 *      Author: Home
 */

#include <F4xx_DWT.h>

void DWT_CYC_Counter_Enable(void)
{
  /* запускаем таймер DWT_CYC */
  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  DWT->CYCCNT = 0;
  DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}

ну и сам main.c:

Код:
/*
******************************************************************************
File:     main.c
Info:     Generated by Atollic TrueSTUDIO(R) 9.0.0   2018-01-31

The MIT License (MIT)
Copyright (c) 2018 STMicroelectronics

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

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

/* Includes */
#include "main.h"
#include <F4xx_DWT.h>
#include <F4xx_Delay.h>

/* Private macro */

// гасим все светодиоды
#define  LED_CLR_ALL             GPIOD->BSRR = GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15
// включаем соотв.светодиод
#define  LED1_SET                GPIOD->BSRR = GPIO_BSRR_BS_12
#define  LED2_SET                GPIOD->BSRR = GPIO_BSRR_BS_13
#define  LED3_SET                GPIOD->BSRR = GPIO_BSRR_BS_14
#define  LED4_SET                GPIOD->BSRR = GPIO_BSRR_BS_15
#define  DELAY_INIT_CNT          500000

// тестовая нога для анализатора
#define  TST_CLR                 GPIOD->BSRR = GPIO_BSRR_BR_0
#define  TST_SET                 GPIOD->BSRR = GPIO_BSRR_BS_0

/* Private variables */
/* Private function prototypes */
/* Private functions */
void RCC_Init(void);
void GPIO_Init(void);
void Delay(__IO uint32_t tDelay);



void RCC_Init(void)
{
  RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN;  // включаем тактирование GPIOD
}

void GPIO_Init(void)
{
  GPIOD->MODER = GPIO_MODER_MODER0_0 | GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 | GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0;  // настраиваем PD12, PD13, PD14, PD15 как "двухтактный выход общего назначения"
}

// блокирующая задержка
void Delay(__IO uint32_t tDelay)
{
  while(tDelay--);
}

int main(void)
{
uint32_t a;

  RCC_Init();
  GPIO_Init();
  DWT_CYC_Counter_Enable();

  while(1)
  {
   LED_CLR_ALL;
   LED1_SET;
   Delay_ms(500);

   LED_CLR_ALL;
   LED2_SET;
   Delay_us(500000);

   LED_CLR_ALL;
   LED3_SET;
   Delay_ms(500);

   LED_CLR_ALL;
   LED4_SET;
   Delay_us(500000);
  }
}

0

3

ВАРИАНТ №3.

Конечно же для периодических действий в программе нужно применять аппаратные таймеры. Таймер будет генерировать прерывание по переполнению счетчика, в нем мы будет изменять логические уровни на порту меняя порядок свечения диодов.

Код:
/*
******************************************************************************
File:     main.c
Info:     Generated by Atollic TrueSTUDIO(R) 9.0.0   2018-01-31

The MIT License (MIT)
Copyright (c) 2018 STMicroelectronics

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

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

/* Includes */
#include "main.h"

/* Private macro */

/* Private variables */
// массив значения которго мы будем записывать в порт
uint32_t LEDs_BuffCtrl[4] = {
  (GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15 | GPIO_BSRR_BS_12),
  (GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15 | GPIO_BSRR_BS_13),
  (GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15 | GPIO_BSRR_BS_14),
  (GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15 | GPIO_BSRR_BS_15)
};
uint32_t LEDs_BuffCtrl_Pos = 0;  // счетчик


/* Private function prototypes */
/* Private functions */
void RCC_Init(void);
void GPIO_Init(void);
void TIM5_Init(void);


void RCC_Init(void)
{
  RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN;  // включаем тактирование GPIOD
  RCC->APB1ENR = RCC_APB1ENR_TIM5EN;  // включаем тактирование TIM5
}

void GPIO_Init(void)
{
  GPIOD->MODER = GPIO_MODER_MODER0_0 | GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 | GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0;  // настраиваем PD12, PD13, PD14, PD15 как "двухтактный выход общего назначения"
}

void TIM5_Init(void)
{
  TIM5->PSC = 127;  // настраиваем предделитель
  TIM5->ARR = 49999;  // настраиваем максимальное значение счета
  TIM5->DIER = TIM_DIER_UIE;  // разрешаем генерировать запрос на прерывание по переполнению счетчика
  TIM5->EGR = TIM_EGR_UG;  // генерируем Update, для обновления теневых регистров
  TIM5->SR = 0;  // сбрасываем флаги
  TIM5->CR1 |= TIM_CR1_CEN;  // включаем таймер в работу
}

//
void TIM5_IRQHandler(void)
{
  if(TIM5->SR & TIM_SR_UIF)
  {
   GPIOD->BSRR = LEDs_BuffCtrl[LEDs_BuffCtrl_Pos];  // изменяем состояние светодиодов на новое
   if(++LEDs_BuffCtrl_Pos == 4) LEDs_BuffCtrl_Pos = 0;  // увеличиваем счетчик
   TIM5->SR &= ~TIM_SR_UIF;
  }
}

int main(void)
{
  RCC_Init();
  GPIO_Init();
  TIM5_Init();

  NVIC_EnableIRQ(TIM5_IRQn);  // разрешили прерывание

  while(1);
}

0

4

ВАРИАНТ №4.

В третьем варианте процесс переключения светодиодов выполняеться как фоновая задача отвлекая основную программу только в момент переключения. Теперь в четвертом и последнем варианте процесс будет полностью реализован без участия ЦП микроконтроллера. Тут мы задействуем модуль DMA.

Код:
/*
******************************************************************************
File:     main.c
Info:     Generated by Atollic TrueSTUDIO(R) 9.0.0   2018-01-31

The MIT License (MIT)
Copyright (c) 2018 STMicroelectronics

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

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

/* Includes */
#include "main.h"

/* Private macro */
#define _DMA_SxCR_CHSEL(xVal) ((uint32_t) (xVal << 25))

/* Private variables */
// массив значения которго мы будем записывать в порт
uint32_t LEDs_BuffCtrl[4] = {
  (GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15 | GPIO_BSRR_BS_12),
  (GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15 | GPIO_BSRR_BS_13),
  (GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15 | GPIO_BSRR_BS_14),
  (GPIO_BSRR_BR_12 | GPIO_BSRR_BR_13 | GPIO_BSRR_BR_14 | GPIO_BSRR_BR_15 | GPIO_BSRR_BS_15)
};

/* Private function prototypes */
/* Private functions */
void RCC_Init(void);
void GPIO_Init(void);
void TIM8_Init(void);
void DMA2_Stream1_Chnl7_Init(void);

void RCC_Init(void)
{
  RCC->AHB1ENR = RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_DMA2EN;  // включаем тактирование GPIOD и DMA1
  RCC->APB2ENR = RCC_APB2ENR_TIM8EN;
}

void GPIO_Init(void)
{
  GPIOD->MODER = GPIO_MODER_MODER0_0 | GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 | GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0;  // настраиваем PD12, PD13, PD14, PD15 как "двухтактный выход общего назначения"
}

void TIM8_Init(void)
{
  TIM8->PSC = 127;  // настраиваем предделитель
  TIM8->ARR = 49999;  // настраиваем максимальное значение счета
  TIM8->CCR1 = 500;
  TIM8->DIER = TIM_DIER_UDE;  // разрешаем генерировать запрос на прерывание по переполнению счетчика
  TIM8->EGR = TIM_EGR_UG;  // генерируем Update, для обновления теневых регистров
  TIM8->SR = 0;  // сбрасываем флаги
  TIM8->CR1 = TIM_CR1_CEN | TIM_CR1_URS;  // включаем таймер в работу
}

void DMA2_Stream1_Chnl7_Init(void)
{
  DMA2_Stream1->CR = 0;
  DMA2_Stream1->M0AR = (uint32_t) &LEDs_BuffCtrl[0];
  DMA2_Stream1->PAR = (uint32_t) &GPIOD->BSRR;
  DMA2_Stream1->NDTR = sizeof(LEDs_BuffCtrl)/sizeof(*LEDs_BuffCtrl);
  DMA2_Stream1->CR = DMA_SxCR_PL | _DMA_SxCR_CHSEL(7) | DMA_SxCR_MSIZE_1 | DMA_SxCR_PSIZE_1 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_CIRC;
  DMA2->LIFCR = DMA_LIFCR_CDMEIF1 | DMA_LIFCR_CFEIF1 | DMA_LIFCR_CHTIF1 | DMA_LIFCR_CTCIF1 | DMA_LIFCR_CTEIF1;
  DMA2_Stream1->CR |= DMA_SxCR_EN;
}


int main(void)
{
  RCC_Init();
  GPIO_Init();

  DMA2_Stream1_Chnl7_Init();
  TIM8_Init();

  while(1);
}

0


Вы здесь » Программирование микроконтроллеров » Narod Stream. CMSIS. » Урок 2. stm32407 Бегущие огни. STM32F4DISCOVERY.