【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, &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 << 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 & 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>
<p>简单明了,详细!</p>
Gen_X 发表于 2023-12-31 11:28
简单明了,详细!
<p>多谢大佬的关注,这freertos也得多用用,才能熟悉。还在继续努力学习中!</p>
<p>可以在任务里面实现按键短按和长按的检测~</p>
wangerxian 发表于 2023-12-31 20:48
可以在任务里面实现按键短按和长按的检测~
<p>有一个成品的单按、长按等的开源库,有空我去找找放到这里来。</p>
<p>楼主提供的技术内容详实,通俗易懂,参考价值很大,感谢楼主的无私分享</p>
chejm 发表于 2024-1-2 04:34
楼主提供的技术内容详实,通俗易懂,参考价值很大,感谢楼主的无私分享
<p>感谢大佬的关注,大家都分享知识,这样对于基础的理解与掌握会越来越容易!</p>
chejm 发表于 2024-1-2 04:34
楼主提供的技术内容详实,通俗易懂,参考价值很大,感谢楼主的无私分享
<p>老哥,我加了个按键扫描直接不动了,现在直接整个程序不跑了,注释掉if可以正常运行</p>
页:
[1]