单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
一、软件定时器实验
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
freertos_demo(); /* 运行FreeRTOS例程 */
}
Rtos
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "Timer", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
lcd_draw_rectangle(5, 110, 115, 314, BLACK);
lcd_draw_rectangle(125, 110, 234, 314, BLACK);
lcd_draw_line(5, 130, 115, 130, BLACK);
lcd_draw_line(125, 130, 234, 130, BLACK);
lcd_show_string(15, 111, 110, 16, 16, "Timer1: 000", BLUE);
lcd_show_string(135, 111, 110, 16, 16, "Timer2: 000", BLUE);
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
task
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 定时器1创建为周期定时器 */
Timer1Timer_Handler = xTimerCreate((const char* )"Timer1", /* 定时器名 */
(TickType_t )1000, /* 定时器超时时间 */
(UBaseType_t )pdTRUE, /* 周期定时器 */
(void* )1, /* 定时器ID */
(TimerCallbackFunction_t)Timer1Callback); /* 定时器回调函数 */
/* 定时器2创建为单次定时器 */
Timer2Timer_Handler = xTimerCreate((const char* )"Timer2", /* 定时器名 */
(TickType_t )1000, /* 定时器超时时间 */
(UBaseType_t )pdFALSE, /* 单次定时器 */
(void* )2, /* 定时器ID */
(TimerCallbackFunction_t)Timer2Callback); /* 定时器回调函数 */
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task1(void *pvParameters)
{
uint8_t key = 0;
while (1)
{
if ((Timer1Timer_Handler != NULL) && (Timer2Timer_Handler != NULL))
{
key = key_scan(0);
switch (key)
{
case KEY0_PRES:
{
xTimerStart((TimerHandle_t )Timer1Timer_Handler, /* 待启动的定时器句柄 */
(TickType_t )portMAX_DELAY); /* 等待系统启动定时器的最大时间 */
xTimerStart((TimerHandle_t )Timer2Timer_Handler, /* 待启动的定时器句柄 */
(TickType_t )portMAX_DELAY); /* 等待系统启动定时器的最大时间 */
break;
}
case KEY1_PRES:
{
xTimerStop((TimerHandle_t )Timer1Timer_Handler, /* 待停止的定时器句柄 */
(TickType_t )portMAX_DELAY); /* 等待系统停止定时器的最大时间 */
xTimerStop((TimerHandle_t )Timer2Timer_Handler, /* 待停止的定时器句柄 */
(TickType_t )portMAX_DELAY); /* 等待系统停止定时器的最大时间 */
break;
}
default:
{
break;
}
}
}
vTaskDelay(10);
}
}
void Timer1Callback(TimerHandle_t xTimer)
{
static uint32_t timer1_num = 0;
lcd_fill(6, 131, 114, 313, lcd_discolor[++timer1_num % 11]); /* LCD区域刷新 */
lcd_show_xnum(79, 111, timer1_num, 3, 16, 0x80, BLUE); /* 显示定时器1超时次数 */
}
void Timer2Callback(TimerHandle_t xTimer)
{
static uint32_t timer2_num = 0;
lcd_fill(126, 131, 233, 313, lcd_discolor[++timer2_num % 11]); /* LCD区域刷新 */
lcd_show_xnum(199, 111, timer2_num, 3, 16, 0x80, BLUE); /* 显示定时器2超时次数 */
}
测试结果

二、事件标志组实验
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
freertos_demo(); /* 运行FreeRTOS例程 */
}
Rtos
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "Event Group", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
lcd_draw_rectangle(5, 130, 234, 314, BLACK); /* 画矩形 */
lcd_show_string(30, 110, 220, 16, 16, "Event Group Value: 0", BLUE);
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
task
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建事件标志组 */
EventGroupHandler = xEventGroupCreate();
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
/* 创建任务3 */
xTaskCreate((TaskFunction_t )task3,
(const char* )"task3",
(uint16_t )TASK3_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK3_PRIO,
(TaskHandle_t* )&Task3Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task1(void *pvParameters)
{
uint8_t key = 0;
while (1)
{
key = key_scan(0);
switch (key)
{
case KEY0_PRES:
{
xEventGroupSetBits((EventGroupHandle_t )EventGroupHandler, /* 待操作的事件标志组句柄 */
(EventBits_t )EVENTBIT_0); /* 待设置的bit位 */
break;
}
case KEY1_PRES:
{
xEventGroupSetBits((EventGroupHandle_t )EventGroupHandler, /* 待操作的事件标志组句柄 */
(EventBits_t )EVENTBIT_1); /* 待设置的bit位 */
break;
}
default:
{
break;
}
}
vTaskDelay(10);
}
}
void task2(void *pvParameters)
{
uint32_t task2_num = 0;
while (1)
{
xEventGroupWaitBits((EventGroupHandle_t )EventGroupHandler, /* 等待的事件标志组句柄 */
(EventBits_t )EVENTBIT_ALL, /* 等待的事件 */
(BaseType_t )pdTRUE, /* 函数退出时清零等待的事件 */
(BaseType_t )pdTRUE, /* 等待等待的事件中的所有事件 */
(TickType_t )portMAX_DELAY); /* 等待时间 */
lcd_fill(6, 131, 233, 313, lcd_discolor[++task2_num % 11]); /* LCD区域刷新 */
vTaskDelay(10);
}
}
void task3(void *pvParameters)
{
EventBits_t event_val = 0;
while (1)
{
event_val = xEventGroupGetBits((EventGroupHandle_t)EventGroupHandler); /* 获取的事件标志组句柄 */
lcd_show_xnum(182, 110, event_val, 1, 16, 0, BLUE); /* 在LCD上显示事件值 */
vTaskDelay(10);
}
}
测试结果

三、任务通知模拟二值信号量实验
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
freertos_demo(); /* 运行FreeRTOS例程 */
}
Rtos
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "Notify Bina Sem", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
lcd_draw_rectangle(5, 130, 234, 314, BLACK); /* 画矩形 */
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
task
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task1(void *pvParameters)
{
uint8_t key = 0;
while (1)
{
if (Task2Task_Handler != NULL)
{
key = key_scan(0);
switch (key)
{
case KEY0_PRES: /* 发送任务通知 */
{
xTaskNotifyGive((TaskHandle_t)Task2Task_Handler); /* 接收任务通知的任务句柄 */
break;
}
default:
{
break;
}
}
}
vTaskDelay(10);
}
}
void task2(void *pvParameters)
{
uint32_t notify_val = 0;
uint32_t task2_num = 0;
while (1)
{
notify_val = ulTaskNotifyTake((BaseType_t )pdTRUE, /* 通知值在函数退出时清零,类似二值信号量 */
(TickType_t )portMAX_DELAY); /* 等待时间 */
if (notify_val != 0)
{
lcd_fill(6, 131, 233, 313, lcd_discolor[++task2_num % 11]); /* LCD区域刷新 */
}
}
}
测试结果

四、任务通知模拟计数型信号量实验
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
freertos_demo(); /* 运行FreeRTOS例程 */
}
Rtos
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "Notify Count Sem", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(54, 111, 200, 16, 16, "Notify Value: 0", BLUE);
lcd_draw_rectangle(5, 110, 234, 314, BLACK);
lcd_draw_line(5, 130, 234, 130, BLACK);
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
task
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task1(void *pvParameters)
{
uint8_t key = 0;
while (1)
{
key = key_scan(0);
if (Task2Task_Handler != NULL)
{
switch (key)
{
case KEY0_PRES: /* 发送任务通知 */
{
xTaskNotifyGive((TaskHandle_t)Task2Task_Handler); /* 接收任务通知的任务句柄 */
break;
}
default:
{
break;
}
}
}
vTaskDelay(10);
}
}
void task2(void *pvParameters)
{
uint32_t notify_val = 0;
uint32_t task2_num = 0;
while (1)
{
notify_val = ulTaskNotifyTake((BaseType_t )pdFALSE, /* 通知值在函数退出时递减,类似计数型信号量 */
(TickType_t )portMAX_DELAY); /* 等待时间 */
lcd_show_xnum(166, 111, notify_val - 1, 2, 16, 0, BLUE); /* 在LCD上显示任务通知值 */
lcd_fill(6, 131, 233, 313, lcd_discolor[++task2_num % 11]); /* LCD区域刷新 */
vTaskDelay(1000);
}
}
测试结果

五、任务通知模拟消息邮箱实验
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
freertos_demo(); /* 运行FreeRTOS例程 */
}
Rtos
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "Notify MailBox", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
lcd_draw_rectangle(5, 125, 234, 314, BLACK); /* 画矩形 */
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
task
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task1(void *pvParameters)
{
uint8_t key = 0;
while (1)
{
key = key_scan(0);
if ((Task2Task_Handler != NULL) && (key != 0))
{
xTaskNotify((TaskHandle_t )Task2Task_Handler, /* 接收任务通知的任务句柄 */
(uint32_t )key, /* 要更新的bit位 */
(eNotifyAction )eSetValueWithOverwrite); /* 更新方式为覆写 */
}
vTaskDelay(10);
}
}
void task2(void *pvParameters)
{
uint32_t notify_val = 0;
uint32_t task2_num = 0;
while (1)
{
xTaskNotifyWait((uint32_t )0x00000000, /* 进入函数时,不清除任务通知值 */
(uint32_t )0xFFFFFFFF, /* 函数退出时,清零任务通知值 */
(uint32_t* )¬ify_val, /* 接收到的通知值 */
(TickType_t )portMAX_DELAY); /* 等待时间 */
switch (notify_val)
{
case KEY0_PRES: /* LCD区域刷新 */
{
lcd_fill(6, 126, 233, 313, lcd_discolor[++task2_num % 11]);
break;
}
case KEY1_PRES: /* LED0闪烁 */
{
LED0_TOGGLE();
break;
}
default:
{
break;
}
}
}
}
测试结果

六、任务通知模拟事件标志组实验
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
freertos_demo(); /* 运行FreeRTOS例程 */
}
Rtos
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "Notify Event Group", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(30,110,220,16,16,"Event Group Value: 0",BLUE);
lcd_draw_rectangle(5,130,234,314,BLACK); /* 画矩形 */
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
task
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task1(void *pvParameters)
{
uint8_t key = 0;
while (1)
{
if (Task2Task_Handler != NULL)
{
key = key_scan(0);
switch (key)
{
case KEY0_PRES:
{
xTaskNotify((TaskHandle_t )Task2Task_Handler, /* 接收任务通知的任务句柄 */
(uint32_t )EVENTBIT_0, /* 要更新的bit位 */
(eNotifyAction )eSetBits); /* 更新方式为设置bit位 */
break;
}
case KEY1_PRES:
{
xTaskNotify((TaskHandle_t )Task2Task_Handler, /* 接收任务通知的任务句柄 */
(uint32_t )EVENTBIT_1, /* 要更新的bit位 */
(eNotifyAction )eSetBits); /* 更新方式为设置bit位 */
break;
}
default:
{
break;
}
}
}
vTaskDelay(10);
}
}
void task2(void *pvParameters)
{
uint32_t notify_val = 0;
uint32_t event_val = 0;
uint32_t task2_num = 0;
while (1)
{
xTaskNotifyWait((uint32_t )0x00000000, /* 进入函数时,不清除任务通知值 */
(uint32_t )0xFFFFFFFF, /* 函数退出时,清零任务通知值 */
(uint32_t* )¬ify_val, /* 接收到的通知值 */
(TickType_t )portMAX_DELAY); /* 等待时间 */
if (notify_val & EVENTBIT_0) /* 模拟事件0发生 */
{
event_val |= EVENTBIT_0;
}
else if (notify_val & EVENTBIT_1) /* 模拟事件1发生 */
{
event_val |= EVENTBIT_1;
}
lcd_show_xnum(182, 110, event_val, 1, 16, 0, BLUE); /* LCD上显示事件值 */
if (event_val == EVENTBIT_ALL)
{
event_val = 0; /* 模拟事件组清零 */
lcd_fill(6, 131, 233, 313, lcd_discolor[++task2_num % 11]);
}
}
}
测试结果

七、低功耗Tickless实验
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
freertos_demo(); /* 运行FreeRTOS例程 */
}
Rtos
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "FreeRTOS Tickless", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
task
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 关闭LCD */
lcd_display_off();
LCD_BL(0);
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
/**
* @brief task1
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task1(void *pvParameters)
{
while(1)
{
LED0(1); /* LED0灭,指示退出低功耗模式 */
delay_ms(3000); /* CPU忙延时,期间不会进入低功耗模式 */
LED0(0); /* LED0亮,指示进入低功耗模式 */
vTaskDelay(3000); /* 阻塞延时,期间会进入低功耗模式 */
}
}
#if (configUSE_TICKLESS_IDLE != 0)
/**
* @brief PRE_SLEEP_PROCESSING
* @param 无
* @retval 无
*/
void PRE_SLEEP_PROCESSING(void)
{
/* 关闭部分外设时钟,仅作演示 */
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOD_CLK_DISABLE();
__HAL_RCC_GPIOE_CLK_DISABLE();
__HAL_RCC_GPIOF_CLK_DISABLE();
__HAL_RCC_GPIOG_CLK_DISABLE();
}
/**
* @brief POST_SLEEP_PROCESSING
* @param 无
* @retval 无
*/
void POST_SLEEP_PROCESSING(void)
{
/* 重新打开部分外设时钟,仅作演示 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
}
#endif
测试结果
LED0亮起,指示进入低功耗模式;LED0熄灭,指示退出低功耗模式。
八、空闲任务钩子函数实验
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
freertos_demo(); /* 运行FreeRTOS例程 */
}
Rtos
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "FreeRTOS IDLE HOOK", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
task
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 关闭LCD */
lcd_display_off();
LCD_BL(0);
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task1(void *pvParameters)
{
while(1)
{
LED0(1); /* LED0灭,指示退出低功耗模式 */
delay_ms(3000); /* CPU忙延时,期间不会进入低功耗模式 */
LED0(0); /* LED0亮,指示进入低功耗模式 */
vTaskDelay(3000); /* 阻塞延时,期间会进入低功耗模式 */
}
}
void BeforeEnterSleep(void)
{
/* 关闭部分外设时钟,仅作演示 */
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOD_CLK_DISABLE();
__HAL_RCC_GPIOE_CLK_DISABLE();
__HAL_RCC_GPIOF_CLK_DISABLE();
__HAL_RCC_GPIOG_CLK_DISABLE();
}
void AfterExitSleep(void)
{
/* 重新打开部分外设时钟,仅作演示 */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
}
void vApplicationIdleHook(void)
{
__disable_irq();
__dsb(portSY_FULL_READ_WRITE);
__isb(portSY_FULL_READ_WRITE);
BeforeEnterSleep();
__wfi();
AfterExitSleep();
__dsb(portSY_FULL_READ_WRITE);
__isb(portSY_FULL_READ_WRITE);
__enable_irq();
}
测试结果
LED0亮起,指示进入低功耗模式;LED0熄灭,指示退出低功耗模式。
九、内存管理实验
主函数
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
freertos_demo(); /* 运行FreeRTOS例程 */
}
Rtos
void freertos_demo(void)
{
lcd_show_string(10, 10, 220, 32, 32, "STM32", RED);
lcd_show_string(10, 47, 220, 24, 24, "Mem Manage", RED);
lcd_show_string(10, 76, 220, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(30, 118, 200, 16, 16, "Total Mem: Bytes", RED);
lcd_show_string(30, 139, 200, 16, 16, "Free Mem: Bytes", RED);
lcd_show_string(30, 160, 200, 16, 16, "Malloc Addr:", RED);
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
task
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
void task1(void *pvParameters)
{
uint8_t key = 0;
uint8_t *buf = NULL;
size_t free_size = 0;
while (1)
{
key = key_scan(0);
switch (key)
{
case KEY0_PRES: /* 申请内存和使用内存 */
{
buf = pvPortMalloc(30);
sprintf((char *)buf, "0x%p", buf);
lcd_show_string(130, 160, 200, 16, 16, (char *)buf, BLUE);
break;
}
case KEY1_PRES: /* 释放内存 */
{
if (NULL != buf)
{
vPortFree(buf);
buf = NULL;
}
break;
}
default:
{
break;
}
}
lcd_show_xnum(114, 118, configTOTAL_HEAP_SIZE, 5, 16, 0, BLUE); /* 显示总内存大小 */
free_size = xPortGetFreeHeapSize(); /* 获取内存剩余大小 */
lcd_show_xnum(114, 139, free_size, 5, 16, 0, BLUE); /* 显示剩余内存大小 */
vTaskDelay(10);
}
}
测试结果
