我基本上试图在按下按钮后将LED点亮。下面是应该处理此操作的代码的片段:
void task_player1(void *pvParameters)
{
while (1)
{
if (xSemaphoreTake(player1_signal, portMAX_DELAY))
{
printf(">>>Semaphore takenn<<<");
ioport_set_pin_level(L1, HIGH);
xSemaphoreGive(player1_signal);
}
else
{
ioport_set_pin_level(L1, LOW);
}
}
}
void task_ctrl(void *pvParameters)
{
bool button1 = 0;
while (1)
{
button1 = ioport_get_pin_level(B1);
if (button1)
{
xSemaphoreGive(player1_signal);
printf("Semaphore givenn");
}
}
}
我要设想的方式是task_ctrl
在按钮上给出信号量。 Task_player1
被阻止,直到需要信号量,之后应打开LED。
问题是它似乎从来没有使用过信号量。我正在运行printf
语句,向我展示该程序到达多远,它永远不会进入LED点亮的部分。但是,当我在没有按钮的情况下按下task_ctrl
中的xSemaphoreGive
时,请采用信号量。
奇怪的部分是"Semaphore givenn"
语句在按钮点击上打印出来,这应该意味着也给出了信号量,但永远不会被拿走。
任务独自工作,我什至设法在没有按钮的情况下使用按钮,如我上面所述。
。我猜想这是按钮按代码的东西,该按钮也可以在任务之外使用。那我做错了什么?我不是正确使用Freertos吗?
编辑:包括任务创建代码
#define TASK_STACK_SIZE (2048/ sizeof(portSTACK_TYPE))
xTaskCreate(task_ctrl, (const signed char * const) "Control", TASK_STACK_SIZE, NULL, 1, NULL);
xTaskCreate(task_player1, (const signed char * const) "Player1", TASK_STACK_SIZE, NULL, 1, NULL);
编辑2:我应该提到的可能是我使用的是Freertos 7.3,因为Atmel Studio没有任何更新版本。因此,据我所知,没有收益功能可用。
task_ctrl
永远不会阻止 - 这将防止运行 ever 的任何相等或较低优先级的任务。因此,如果task_player
相等或较低的优先级,即使给出了信号量,任务也永远不会安排。
它似乎没有按钮轮询工作很难解释,但是您尚未显示该代码,因此我无法发表评论。
您应该做两件事:
- 确保
task_ctrl
的优先级较低,至少比task_player1
(如果不阻止任何任务,则比任何任务都低 - 在这种情况下,闲置任务永远不会运行)。 - 确保
task_ctrl
阻止 - 即使只是轮询延迟,以免吞噬所有可用的CPU周期。
while (1)
{
button1 = ioport_get_pin_level(B1);
if (button1)
{
xSemaphoreGive(player1_signal);
printf("Semaphore givenn");
vtaskDelay( 1 ) ; // at least 1 tick
}
}
task_ctrl
的一个可能的问题是,它将在保留按钮时连续且反复地给出信号量。某种状态变化检测和切换脱回反弹而不是级别的轮询。
投票任务的替代解决方案是使用硬件中断TEH按钮,并在ISR上使用事件的投票任务块,或者将ISR直接提供给信号量 - 在任何一种情况下,您都必须交易审问。