MyTetra Share
Делитесь знаниями!
FreeRTOS. Обработка нажатия кнопки
Время создания: 04.05.2018 11:18
Раздел: Electronics - Microcontrollers - STM32 - CMSIS

Кнопка на плате подключена к пину PA0. Включаем тактирование порты и переводим его во входной режим. Подтяжка не нужна, т.к. кнопка уже подтянута аппаратно на плате.


//Port A

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //enable RCC for PortA

GPIOA->MODER &= ~(1 << 0); //Set output mode for PA0 (User Button)


Ниже реализован таск, отслеживающий и обрабатывающий нажатие кнопки. CheckButton имеет следующую струкуту:


if(GPIOA->IDR & GPIO_IDR_ID0) {

// код, который будет обработан сразу после нажатия кнопки

while(GPIOA->IDR & GPIO_IDR_ID0) {

vTaskDelay(100); } //проверяем, отпущена ли кнопка.

// код, который будет обработан после размыкания контактов кнопки

}

vTaskDelay(300); //задержка между опросами


Опрос кнпоки проходит каждые 300 мс, задержка для устранения дребезка контактов - 100 мс (с избытком).

В качесте полезного выхлопа по нажатию (точней по отжатию кнопки) меняется режим таска LedBlink - либо уходит в suspend, либо возобновляет работу.


void vTaskCheckButton(void *argument)

{

uint8_t taskState = 1;

while(1)

{

if(GPIOA->IDR & GPIO_IDR_ID0)

{

while(GPIOA->IDR & GPIO_IDR_ID0)

{ vTaskDelay(100); }

//if((GPIOA->IDR & GPIO_IDR_ID0))

//{

if(taskState)

{

GPIOD->BSRR |= GPIO_BSRR_BR12;

GPIOD->BSRR |= GPIO_BSRR_BR14;

vTaskSuspend(xLedBlinkHandle);

taskState = 0;

}

else

{

vTaskResume(xLedBlinkHandle);

taskState = 1;

}

//}

}

vTaskDelay(300);

}

}


Чтобы функции vTaskSuspend и vTaskResume работали, необходимо в FreeRTOSConfig.h дефайн INCLUDE_vTaskSuspend выставить в 1.

Для реализации этого функционала также пришлось в качестве глобальной переменной объявить указатель на хэндл задачи:


xTaskHandle xLedBlinkHandle = NULL;


И использовать его при создании таска:


xTaskCreate(vTaskLedArrow, "Arrow", 32, NULL, 1, NULL);

xTaskCreate(vTaskLedBlink, "Blink", 32, NULL, 1, &xLedBlinkHandle);

xTaskCreate(vTaskCheckButton, "UsrBttn", 32, NULL, 1, NULL);

vTaskStartScheduler();


В остальном код остался без изменений:


#include "stm32f4xx.h"

#include "FreeRTOS.h"

#include "task.h"

#include "queue.h"


void RCC_init(void);

void GPIO_init(void);

void vTaskLedArrow(void *argument);

void vTaskLedBlink(void *argument);

void vTaskCheckButton(void *argument);


xTaskHandle xLedBlinkHandle = NULL;


int main(void)

{

RCC_init();

GPIO_init();


xTaskCreate(vTaskLedArrow, "Arrow", 32, NULL, 1, NULL);

xTaskCreate(vTaskLedBlink, "Blink", 32, NULL, 1, &xLedBlinkHandle);

xTaskCreate(vTaskCheckButton, "UsrBttn", 32, NULL, 1, NULL);

vTaskStartScheduler();

while(1)

{

/*Code Section for Error Indication*/

GPIOD->BSRR |= GPIO_BSRR_BS12;

GPIOD->BSRR |= GPIO_BSRR_BS13;

GPIOD->BSRR |= GPIO_BSRR_BS14;

GPIOD->BSRR |= GPIO_BSRR_BS15;

}

}


void RCC_init(void)

{

RCC->CR |= (RCC_CR_HSEON); //Enable HSE

while( !(RCC->CR & RCC_CR_HSERDY) ) {}; //ready to start HSE


//FLASH

FLASH->ACR |= FLASH_ACR_LATENCY //latency for flash memory

| FLASH_ACR_PRFTEN

| FLASH_ACR_ICEN

| FLASH_ACR_DCEN;

//PLL - HSE

RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE; //set HSE as PLL source

RCC->CR &= ~(RCC_CR_PLLON); //disable PLL before changes

//PLL M

RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLM); //clear all PLLM bits

RCC->PLLCFGR |= RCC_PLLCFGR_PLLM_2; //set PLLM = 4 (100)


//PLL P

RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLP); //main PLL division PLLP = 2: 00

//PLL N

RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLN); //clear all PLLN bits with mask

RCC->PLLCFGR |= (RCC_PLLCFGR_PLLN_3 //set PLLN = 168 (1010 1000)

| RCC_PLLCFGR_PLLN_5 //for 8 or 16 MHz HSE

| RCC_PLLCFGR_PLLN_7); //

//PLL Q 7 (0111)

RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLQ);

RCC->PLLCFGR |= (RCC_PLLCFGR_PLLQ_0

| RCC_PLLCFGR_PLLQ_2

| RCC_PLLCFGR_PLLQ_2);

//AHB Prescaler

RCC->CFGR &= ~(RCC_CFGR_HPRE); //Prescaler = 1

RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //AHB = SYSCLK/1

//APB1 Prescaler 8

RCC->CFGR &= ~(RCC_CFGR_PPRE1);

RCC->CFGR |= RCC_CFGR_PPRE1_DIV8;

//APB2 Prescaler 2

RCC->CFGR &= ~(RCC_CFGR_PPRE2);

RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

//PLL enable

RCC->CR |= RCC_CR_PLLON; //enalbe PLL

while((RCC->CR & RCC_CR_PLLRDY) == 0) {} //wait for PLL is ready

//PLL System

//RCC->CFGR &= ~RCC_CFGR_SW;

RCC->CFGR |= RCC_CFGR_SW_PLL; //PLL selected as system clock

while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} //wait for PLL is used

}


void GPIO_init(void)

{

//RCC

RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; //enable RCC for PortD

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //enable RCC for PortA

//Port A

GPIOA->MODER &= ~(1 << 0); //Set output mode for PA0 (User Button)

//Port D

GPIOD->MODER = 0x55000000; //0b0101.0101 0000.0000 0000.0000 0000.0000

GPIOD->OTYPER = 0; //push-pull enable

GPIOD->OSPEEDR = 0; //low speed

GPIOD->BSRR = 0xF0000000; //turn off all LED

}


void vTaskLedArrow(void *argument)

{

while(1)

{

GPIOD->BSRR |= GPIO_BSRR_BR13;

GPIOD->BSRR |= GPIO_BSRR_BR15;

vTaskDelay(3000); //300 ms

GPIOD->BSRR |= GPIO_BSRR_BS13;

vTaskDelay(3000);

GPIOD->BSRR |= GPIO_BSRR_BS15;

vTaskDelay(3000);

GPIOD->BSRR |= GPIO_BSRR_BR13;

vTaskDelay(3000);

}

}


void vTaskLedBlink(void *argument)

{

while(1)

{

GPIOD->BSRR |= GPIO_BSRR_BS12;

GPIOD->BSRR |= GPIO_BSRR_BS14;

vTaskDelay(2000); //300 ms

GPIOD->BSRR |= GPIO_BSRR_BR12;

GPIOD->BSRR |= GPIO_BSRR_BR14;

vTaskDelay(2000);

}

}


void vTaskCheckButton(void *argument)

{

uint8_t taskState = 1;

while(1)

{

if(GPIOA->IDR & GPIO_IDR_ID0)

{

while(GPIOA->IDR & GPIO_IDR_ID0)

{ vTaskDelay(100); }


if(taskState)

{

GPIOD->BSRR |= GPIO_BSRR_BR12;

GPIOD->BSRR |= GPIO_BSRR_BR14;

vTaskSuspend(xLedBlinkHandle);

taskState = 0;

}

else

{

vTaskResume(xLedBlinkHandle);

taskState = 1;

}

}

vTaskDelay(300);

}

}












 
MyTetra Share v.0.53
Яндекс индекс цитирования