单片机FreeRtos实验3

单片机 :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*    )&notify_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*    )&notify_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);
    }
}

测试结果