lugl4313820 发表于 2023-12-30 23:29

【ACM32G103RCT6开发板测评】freertos实现多任务按键控制LED灯

<p>【目的】</p>

<p>实现GPIO的输入与输出的体验</p>

<p>【开发环境】</p>

<p>1、MDK5.38</p>

<p>2、freertos</p>

<p>【实现步骤】</p>

<p>在freertos的工程中,创建两个任务,分别为:</p>

<p>1、按键检测任务。开发板板载了1个按键,为PC13,官方的BSP的acm32g103_coreboard.c中已经实现了对他的初始化,代码如下:</p>

<pre>
<code>/******************************************************************************
*@brief : PB init
*@param : none
*@return: none
******************************************************************************/
void BSP_PB_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    BSP_PB_CLK_ENABLE();

    GPIO_InitStruct.Pin       = BSP_PB_PIN;
    GPIO_InitStruct.Mode      = BSP_PB_MODE;
    GPIO_InitStruct.Pull      = BSP_PB_PULL;
    GPIO_InitStruct.Drive   = BSP_PB_DRIVE;
    GPIO_InitStruct.Alternate = BSP_PB_ALTERNATE;

    HAL_GPIO_Init(BSP_PB_GPIO, &amp;GPIO_InitStruct);

//                HAL_EXTI_ClearPending(BSP_PB_PIN);
//    NVIC_ClearPendingIRQ(BSP_PB_IRQ);
//    NVIC_SetPriority(BSP_PB_IRQ, 0x00);
//    NVIC_EnableIRQ(BSP_PB_IRQ);
}</code></pre>

<p>我这里不需要中断,所以注释掉了中断的配置。</p>

<p>2、LED灯的初始化,在acm32g103_coreboard.h也已有初始化的代码,所以我们直接调用就行了。库中也有翻转的函数BSP_LED_Toggle();</p>

<p>【任务的创建】</p>

<p>1、检测按键代码如下,主要的编程思想为检测是否按下,如果按下,则延时、消抖,再检测是否抬起,如果符合则翻转按键。</p>

<pre>
<code>void task_1(void *msg)
{
                printfS("task_1 run.... \r\n");
    while (1)
    {
      if(BSP_PB_GetState() == GPIO_PIN_RESET)
                                {
                                        vTaskDelay(100);
                                        if(BSP_PB_GetState() == GPIO_PIN_SET)
                                        {
                                                BSP_LED_Toggle();
                                        }
                                }
                                vTaskDelay(20);
    }
}</code></pre>

<p>烧写代码后,按下按建便可以实现LED灯的翻转。</p>

<p>【任务间的通信】</p>

<p>为体验事件标志组,所以我建立了任务事件组,为以后的编做准备:</p>

<pre>
<code>#define LEDTOGGLE_0        ( 1 &lt;&lt; 0 ) //0001 为按LED灯翻转事件标志

#define ALLBITS 0xFFFFFF      //24bits都为1</code></pre>

<p>我们在按键任务,如果检测到了按键按下后抬起,我们将事件标志置1,代码如下:</p>

<pre>
<code>void task_1(void *msg)
{
                printfS("task_1 run.... \r\n");
    while (1)
    {
      if(BSP_PB_GetState() == GPIO_PIN_RESET)
                                {
                                        vTaskDelay(100);
                                        if(BSP_PB_GetState() == GPIO_PIN_SET)
                                        {                               
                                                xEventGroupSetBits(xEventPurchase, LEDTOGGLE_0); //将事件置1
                                        }
                                }
                                vTaskDelay(20);
    }
}</code></pre>

<p>然后在led的任务中,我们判断示志位是否为1,如果为1,测翻反LED灯,代码如下:</p>

<pre>
<code>void task_2(void *msg)
{
                EventBits_t uxBits;// Event Group 24Bits 的 值
                printfS("task_2 run.... \r\n");
    while (1)
    {
                        uxBits = xEventGroupWaitBits (xEventPurchase,//Event Group Handler
                                  LEDTOGGLE_0,   //等待Event Group中的那个Bit(s)
                                  pdTRUE,         //执行后,对应的Bits是否重置为 0
                                  pdTRUE,          //等待的Bits判断关系 True为 AND, False为 OR
                                  xTimeOut);
                        if(uxBits &amp; LEDTOGGLE_0)
                        {
                                BSP_LED_Toggle();
                        }
    }
}</code></pre>

<p>在主程序中,我们创建标组标志组:</p>

<pre>
<code>void task_1(void *msg);
void task_2(void *msg);
int main(void)
{
    uint32_t count=0;
       
                HAL_Init();
               
    SystemClock_Config();
                TIM6_Init();
    BSP_UART_Init();       
                BSP_LED_Init();       
                BSP_PB_Init();
                xTaskCreate(task_1,"task1",100,NULL,0,NULL);
                xTaskCreate(task_2,"task2",100,NULL,0,NULL);
        xEventPurchase = xEventGroupCreate(); //创建 event group
                vTaskStartScheduler();
                while (1)
    {
               
    }
}</code></pre>

<p>下载到开发板后,我们就可以实现用按键实现对LED灯的翻转控制了。</p>

<p>【小结】</p>

<p>本次实验主要体验freertos的多任务操作,利用事件标志组来实现任务间的通信,为以后的实验打基础。</p>

<p>整体的工程代码附上。</p>

<div></div>

Gen_X 发表于 2023-12-31 11:28

<p>简单明了,详细!</p>

lugl4313820 发表于 2023-12-31 19:46

Gen_X 发表于 2023-12-31 11:28
简单明了,详细!

<p>多谢大佬的关注,这freertos也得多用用,才能熟悉。还在继续努力学习中!</p>

wangerxian 发表于 2023-12-31 20:48

<p>可以在任务里面实现按键短按和长按的检测~</p>

lugl4313820 发表于 2024-1-1 07:42

wangerxian 发表于 2023-12-31 20:48
可以在任务里面实现按键短按和长按的检测~

<p>有一个成品的单按、长按等的开源库,有空我去找找放到这里来。</p>

chejm 发表于 2024-1-2 04:34

<p>楼主提供的技术内容详实,通俗易懂,参考价值很大,感谢楼主的无私分享</p>

lugl4313820 发表于 2024-1-2 07:51

chejm 发表于 2024-1-2 04:34
楼主提供的技术内容详实,通俗易懂,参考价值很大,感谢楼主的无私分享

<p>感谢大佬的关注,大家都分享知识,这样对于基础的理解与掌握会越来越容易!</p>

矿泉水a 发表于 2024-10-1 18:06

chejm 发表于 2024-1-2 04:34
楼主提供的技术内容详实,通俗易懂,参考价值很大,感谢楼主的无私分享

<p>老哥,我加了个按键扫描直接不动了,现在直接整个程序不跑了,注释掉if可以正常运行</p>
页: [1]
查看完整版本: 【ACM32G103RCT6开发板测评】freertos实现多任务按键控制LED灯