Программа билдится в CoIDE, но не работает переключение задач. При удерживании кнопки должна переключаться задача, то есть сначала горели 3 светодиода ( при нажатие выключались и обратно включались, а после удерживании кнопки должна переключиться задача, должна запуститься другая задачу ( например, бегущий огонёк по часовой стрелке.
Желательно написать рабочий новый код.
#include "stm32f30x.h"
#include "stm32f30x_gpio.h"
#include "stm32f30x_rcc.h"
#include "portmacro.h"
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* LED Configuration */
#define LED_RED_PE9 GPIO_Pin_9
#define LED_BLUE_PE8 GPIO_Pin_8
#define LED_ORANGE_PE10 GPIO_Pin_10
#define LED_GREEN_PE15 GPIO_Pin_15
#define LED_GREEN_PE11 GPIO_Pin_11
#define LED_ORANGE_PE14 GPIO_Pin_14
#define LED_BLUE_PE12 GPIO_Pin_12
#define LED_RED_PE13 GPIO_Pin_13
/* Define ALL_LEDS constant */
#define ALL_LEDS (LED_RED_PE9 | LED_BLUE_PE8 | LED_ORANGE_PE10 | \
LED_GREEN_PE15 | LED_GREEN_PE11 | LED_ORANGE_PE14 | \
LED_BLUE_PE12 | LED_RED_PE13)
/* Traffic Light Configuration */
#define RED1 GPIO_Pin_9 // PE9 (LD3)
#define YELLOW1 GPIO_Pin_8 // PE8 (LD4)
#define GREEN1 GPIO_Pin_10 // PE10 (LD5)
#define RED2 GPIO_Pin_13 // PE13 (LD10)
#define YELLOW2 GPIO_Pin_12 // PE12 (LD9)
#define GREEN2 GPIO_Pin_11 // PE11 (LD7)
#define USER_BUTTON GPIO_Pin_0 // PA0
#define BUTTON_PORT GPIOA
/* Timing Parameters */
#define DEBOUNCE_DELAY_MS 100
#define INITIAL_DELAY 250
#define DELAY_INCREMENT 50
#define MAX_DELAY 1000
#define MIN_DELAY 50
#define NORMAL_DELAY_MS 2000
#define BLINK_DELAY_MS 500
/* Message Types */
typedef enum {
BUTTON_PRESSED,
BUTTON_LONG_PRESS,
MODE_SWITCH,
SPEED_CHANGE,
DIRECTION_CHANGE,
TRAFFIC_MODE_CHANGE
} MessageType_t;
typedef struct {
MessageType_t type;
uint32_t value;
} ButtonMessage_t;
/* Global Variables */
xQueueHandle xMessageQueue = NULL;
xTaskHandle xCurrentModeTaskHandle = NULL;
xTaskHandle xStaticModeTaskHandle = NULL;
xTaskHandle xRunningModeTaskHandle = NULL;
xTaskHandle xDirectionChangeTaskHandle = NULL;
xTaskHandle xSpeedControlTaskHandle = NULL;
xTaskHandle xTrafficLightTaskHandle = NULL;
volatile uint8_t direction = 1;
volatile uint16_t current_delay = INITIAL_DELAY;
volatile uint8_t emergency_mode = 0;
/* Function Prototypes */
void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void vHardwareInit(void);
void vSwitchMode(xTaskHandle newModeTask);
/* Helper Functions */
void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
if(GPIO_ReadOutputDataBit(GPIOx, GPIO_Pin) == Bit_SET) {
GPIO_ResetBits(GPIOx, GPIO_Pin);
} else {
GPIO_SetBits(GPIOx, GPIO_Pin);
}
}
void vHardwareInit(void) {
GPIO_InitTypeDef gpio;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
gpio.GPIO_Mode = GPIO_Mode_OUT;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
gpio.GPIO_Pin = ALL_LEDS | RED1 | YELLOW1 | GREEN1 | RED2 | YELLOW2 | GREEN2;
GPIO_Init(GPIOE, &gpio);
gpio.GPIO_Mode = GPIO_Mode_IN;
gpio.GPIO_PuPd = GPIO_PuPd_UP;
gpio.GPIO_Pin = USER_BUTTON;
GPIO_Init(GPIOA, &gpio);
GPIO_ResetBits(GPIOE, ALL_LEDS | RED1 | YELLOW1 | GREEN1 | RED2 | YELLOW2 | GREEN2);
}
void vSwitchMode(xTaskHandle newModeTask) {
if(xCurrentModeTaskHandle != NULL) {
vTaskSuspend(xCurrentModeTaskHandle);
}
xCurrentModeTaskHandle = newModeTask;
vTaskResume(newModeTask);
}
/* Task Implementations */
void vButtonTask(void *pvParameters) {
portTickType xPressTime;
uint8_t last_button_state = 1;
ButtonMessage_t message;
while(1) {
uint8_t button_state = GPIO_ReadInputDataBit(BUTTON_PORT, USER_BUTTON);
if(last_button_state && !button_state) {
xPressTime = xTaskGetTickCount();
}
else if(!last_button_state && button_state) {
portTickType duration = (xTaskGetTickCount() - xPressTime) * portTICK_RATE_MS;
if(duration < 1000) {
message.type = BUTTON_PRESSED;
message.value = 0;
xQueueSend(xMessageQueue, &message, 0);
} else {
message.type = MODE_SWITCH;
message.value = 0;
xQueueSend(xMessageQueue, &message, 0);
}
}
last_button_state = button_state;
vTaskDelay(DEBOUNCE_DELAY_MS / portTICK_RATE_MS);
}
}
void vStaticModeTask(void *pvParameters) {
ButtonMessage_t message;
while(1) {
if(xQueueReceive(xMessageQueue, &message, portMAX_DELAY) == pdPASS) {
if(message.type == BUTTON_PRESSED) {
GPIO_ToggleBits(GPIOE, LED_RED_PE9 | LED_BLUE_PE8 | LED_ORANGE_PE10);
}
else if(message.type == MODE_SWITCH) {
GPIO_ResetBits(GPIOE, LED_RED_PE9 | LED_BLUE_PE8 | LED_ORANGE_PE10);
vSwitchMode(xRunningModeTaskHandle);
}
}
}
}
void vRunningModeTask(void *pvParameters) {
const uint16_t leds[] = {LED_RED_PE9, LED_BLUE_PE8, LED_ORANGE_PE10,
LED_GREEN_PE15, LED_GREEN_PE11, LED_ORANGE_PE14,
LED_BLUE_PE12, LED_RED_PE13};
uint8_t current_led = 0;
ButtonMessage_t message;
while(1) {
if(xQueueReceive(xMessageQueue, &message, 0) == pdPASS) {
if(message.type == MODE_SWITCH) {
GPIO_ResetBits(GPIOE, ALL_LEDS);
vSwitchMode(xDirectionChangeTaskHandle);
}
}
GPIO_ResetBits(GPIOE, leds[current_led]);
current_led = (current_led + 1) % 8;
GPIO_SetBits(GPIOE, leds[current_led]);
vTaskDelay(current_delay / portTICK_RATE_MS);
}
}
void vDirectionChangeTask(void *pvParameters) {
const uint16_t leds[] = {LED_RED_PE9, LED_BLUE_PE8, LED_ORANGE_PE10,
LED_GREEN_PE15, LED_GREEN_PE11, LED_ORANGE_PE14,
LED_BLUE_PE12, LED_RED_PE13};
uint8_t current_led = 0;
ButtonMessage_t message;
while(1) {
if(xQueueReceive(xMessageQueue, &message, 0) == pdPASS) {
if(message.type == BUTTON_PRESSED) {
direction = !direction; // Изменение направления по нажатию кнопки
}
else if(message.type == MODE_SWITCH) {
GPIO_ResetBits(GPIOE, ALL_LEDS);
vSwitchMode(xSpeedControlTaskHandle);
}
}
GPIO_ResetBits(GPIOE, leds[current_led]);
current_led = direction ? ((current_led + 1) % 8) : ((current_led == 0) ? 7 : (current_led - 1));
GPIO_SetBits(GPIOE, leds[current_led]);
vTaskDelay(current_delay / portTICK_RATE_MS);
}
}
void vSpeedControlTask(void *pvParameters) {
ButtonMessage_t message;
while(1) {
if(xQueueReceive(xMessageQueue, &message, portMAX_DELAY) == pdPASS) {
if(message.type == BUTTON_PRESSED) {
current_delay = (current_delay + DELAY_INCREMENT > MAX_DELAY) ? MIN_DELAY : (current_delay + DELAY_INCREMENT);
}
else if(message.type == MODE_SWITCH) {
GPIO_ResetBits(GPIOE, ALL_LEDS);
vSwitchMode(xTrafficLightTaskHandle);
}
}
}
}
void vTrafficLightTask(void *pvParameters) {
ButtonMessage_t message;
const portTickType xNormalDelay = NORMAL_DELAY_MS / portTICK_RATE_MS;
const portTickType xBlinkDelay = BLINK_DELAY_MS / portTICK_RATE_MS;
while(1) {
if(xQueueReceive(xMessageQueue, &message, 0) == pdPASS) {
if(message.type == BUTTON_PRESSED) {
emergency_mode = !emergency_mode;
GPIO_ResetBits(GPIOE, RED1 | YELLOW1 | GREEN1 | RED2 | YELLOW2 | GREEN2);
}
else if(message.type == MODE_SWITCH) {
GPIO_ResetBits(GPIOE, RED1 | YELLOW1 | GREEN1 | RED2 | YELLOW2 | GREEN2);
vSwitchMode(xStaticModeTaskHandle);
}
}
if(!emergency_mode) {
/* Normal traffic light sequence */
GPIO_SetBits(GPIOE, RED1 | GREEN2);
vTaskDelay(xNormalDelay);
GPIO_ResetBits(GPIOE, RED1 | GREEN2);
GPIO_SetBits(GPIOE, YELLOW1 | YELLOW2);
vTaskDelay(xNormalDelay/4);
GPIO_ResetBits(GPIOE, YELLOW1 | YELLOW2);
GPIO_SetBits(GPIOE, GREEN1 | RED2);
vTaskDelay(xNormalDelay);
GPIO_ResetBits(GPIOE, GREEN1 | RED2);
GPIO_SetBits(GPIOE, YELLOW1 | YELLOW2);
vTaskDelay(xNormalDelay/4);
} else {
/* Emergency blinking mode */
GPIO_ToggleBits(GPIOE, YELLOW1 | YELLOW2);
vTaskDelay(xBlinkDelay);
}
}
}
int main(void) {
vHardwareInit();
xMessageQueue = xQueueCreate(10, sizeof(ButtonMessage_t));
/* Create all tasks */
xTaskCreate(vButtonTask, (signed char*)"Button", configMINIMAL_STACK_SIZE, NULL, 6, NULL);
xTaskCreate(vStaticModeTask, (signed char*)"Static", configMINIMAL_STACK_SIZE, NULL, 5, &xStaticModeTaskHandle);
xTaskCreate(vRunningModeTask, (signed char*)"Running", configMINIMAL_STACK_SIZE, NULL, 4, &xRunningModeTaskHandle);
xTaskCreate(vDirectionChangeTask, (signed char*)"Direction", configMINIMAL_STACK_SIZE, NULL, 3, &xDirectionChangeTaskHandle);
xTaskCreate(vSpeedControlTask, (signed char*)"SpeedCtrl", configMINIMAL_STACK_SIZE, NULL, 2, &xSpeedControlTaskHandle);
xTaskCreate(vTrafficLightTask, (signed char*)"Traffic", configMINIMAL_STACK_SIZE, NULL, 1, &xTrafficLightTaskHandle);
/* Start with static mode */
xCurrentModeTaskHandle = xStaticModeTaskHandle;
vTaskSuspend(xRunningModeTaskHandle);
vTaskSuspend(xDirectionChangeTaskHandle);
vTaskSuspend(xSpeedControlTaskHandle);
vTaskSuspend(xTrafficLightTaskHandle);
vTaskStartScheduler();
while(1);
}