1、利用STM32CubeMX配置FreeRTOS
假设我们之前的配置引脚、配置定时器、配置时钟的步骤均已完成,现在开始导入FreeRTOS。
接下来为我们的程序配置四个任务,注意这里我们的三个任务的优先级是一样的。如果你设置了某一个任务的优先级高,那么程序运行时会一直运行那个任务而无法进入其他任务。
数码管的优先级设高,不然数码管的扫描如果受键码的解析的拖延会产生闪烁!(可以试着把优先级改为low,然后你就会发现按键按下的时候数码管会闪烁。)这个道理和中断优先级是一样的。具体可以看这篇文章:
关于优先级的一点问题思考
这里的function名字最好也修改成和task名字相对应,我这边是当时上课没注意。。。
最后导出文件即可。
2、完成流水灯、按键、蜂鸣器数码管工作
1、在gpio.c和.h文件里面书写并声明按键扫描和led、数码管子程序
void SetLeds(uint8_t sta)
{
HAL_GPIO_WritePin(L1_GPIO_Port,L1_Pin,(sta & 0x01) ? GPIO_PIN_RESET:GPIO_PIN_SET);
HAL_GPIO_WritePin(L2_GPIO_Port,L2_Pin,(sta & 0x02) ? GPIO_PIN_RESET:GPIO_PIN_SET);
HAL_GPIO_WritePin(L3_GPIO_Port,L3_Pin,(sta & 0x04) ? GPIO_PIN_RESET:GPIO_PIN_SET);
HAL_GPIO_WritePin(L4_GPIO_Port,L4_Pin,(sta & 0x08) ? GPIO_PIN_RESET:GPIO_PIN_SET);
HAL_GPIO_WritePin(L5_GPIO_Port,L5_Pin,(sta & 0x10) ? GPIO_PIN_RESET:GPIO_PIN_SET);
HAL_GPIO_WritePin(L6_GPIO_Port,L6_Pin,(sta & 0x20) ? GPIO_PIN_RESET:GPIO_PIN_SET);
HAL_GPIO_WritePin(L7_GPIO_Port,L7_Pin,(sta & 0x40) ? GPIO_PIN_RESET:GPIO_PIN_SET);
HAL_GPIO_WritePin(L8_GPIO_Port,L8_Pin,(sta & 0x80) ? GPIO_PIN_RESET:GPIO_PIN_SET);
}
uint8_t KeyScan()
{
uint8_t key = 0;
if(HAL_GPIO_ReadPin(SW5_GPIO_Port,SW5_Pin) == GPIO_PIN_SET)
{
key = 5;
HAL_Delay(50);
if(HAL_GPIO_ReadPin(SW5_GPIO_Port,SW5_Pin) == GPIO_PIN_SET)
return key;
else
return 0;
}
if(HAL_GPIO_ReadPin(SW6_GPIO_Port,SW6_Pin) == GPIO_PIN_SET)
{
key = 6;
HAL_Delay(50);
if(HAL_GPIO_ReadPin(SW6_GPIO_Port,SW6_Pin) == GPIO_PIN_SET)
return key;
else
return 0;
}
if(HAL_GPIO_ReadPin(SW1_GPIO_Port,SW1_Pin) == GPIO_PIN_RESET)
{
key = 1;
HAL_Delay(50);
if(HAL_GPIO_ReadPin(SW1_GPIO_Port,SW1_Pin) == GPIO_PIN_RESET)
return key;
else
return 0;
}
if(HAL_GPIO_ReadPin(SW2_GPIO_Port,SW2_Pin) == GPIO_PIN_RESET)
{
key = 2;
HAL_Delay(50);
if(HAL_GPIO_ReadPin(SW2_GPIO_Port,SW2_Pin) == GPIO_PIN_RESET)
return key;
else
return 0;
}
if(HAL_GPIO_ReadPin(SW3_GPIO_Port,SW3_Pin) == GPIO_PIN_RESET)
{
key = 3;
HAL_Delay(50);
if(HAL_GPIO_ReadPin(SW3_GPIO_Port,SW3_Pin) == GPIO_PIN_RESET)
return key;
else
return 0;
}
if(HAL_GPIO_ReadPin(SW4_GPIO_Port,SW4_Pin) == GPIO_PIN_RESET)
{
key = 4;
HAL_Delay(50);
if(HAL_GPIO_ReadPin(SW4_GPIO_Port,SW4_Pin) == GPIO_PIN_RESET)
return key;
else
return 0;
}
return 0;
}
void Write595(uint8_t sel,uint8_t num,uint8_t bdot) //共阴数码管 '0'~'7' , '8'~'F'
{
static const uint8_t TAB[16] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
//71HC138输出高电平,关掉数码管显示
HAL_GPIO_WritePin(A3_GPIO_Port,A3_Pin,GPIO_PIN_RESET);
uint8_t dat = TAB[num & 0x0F] |(bdot?0x80:0x00);
//74HC595锁存8段数据
for(uint8_t i=0;i<8;++i)
{
HAL_GPIO_WritePin(SCK_GPIO_Port,SCK_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(SER_GPIO_Port,SER_Pin,(dat & 0x80)? GPIO_PIN_SET:GPIO_PIN_RESET);
dat<<=1;
HAL_GPIO_WritePin(SCK_GPIO_Port,SCK_Pin,GPIO_PIN_SET);
}
HAL_GPIO_WritePin(DISLK_GPIO_Port,DISLK_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(DISLK_GPIO_Port,DISLK_Pin,GPIO_PIN_SET);
//74HC138译码,sel(0~3)对应4位片选信号输出
HAL_GPIO_WritePin(A0_GPIO_Port,A0_Pin,(sel & 0x01) ? GPIO_PIN_SET:GPIO_PIN_RESET);
HAL_GPIO_WritePin(A1_GPIO_Port,A1_Pin,(sel & 0x02) ? GPIO_PIN_SET:GPIO_PIN_RESET);
HAL_GPIO_WritePin(A2_GPIO_Port,A2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(A3_GPIO_Port,A3_Pin,GPIO_PIN_SET);
}
2、在freertos.c文件里面设置全局变量并且在各自任务中载入程序
1、定义全局变量
2、四个任务依次对应着我们当初配置
1、流水灯任务
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
SetLeds(sta);
osDelay(interval);
if(run)
{
if(sta < 0x80) sta<<=1;
else sta = 0x01;
}
osDelay(100);
}
/* USER CODE END StartDefaultTask */
}
2、按键任务
void StartTask02(void *argument)
{
/* USER CODE BEGIN StartTask02 */
/* Infinite loop */
for(;;)
{
key=KeyScan();
if(key!=0) seg[0]=key;
if(key == 1) //start
{
run = 1;
}
if(key == 2)
{
run = 0;
}
if(key == 3) //speed up
{
interval/=2;
if(interval <= 100) interval=100;
}
if(key == 4) //speed down
{
interval*=2;
if(interval >= 2000) interval=2000;
}
osDelay(100);
}
/* USER CODE END StartTask02 */
}
3、蜂鸣器任务
void StartTask03(void *argument)
{
/* USER CODE BEGIN StartTask03 */
/* Infinite loop */
for(;;)
{
beep_duty = key*100;
TIM3->CCR1 = beep_duty;
osDelay(100);
}
/* USER CODE END StartTask03 */
}
4、数码管任务
void StartTaskSEG(void *argument)
{
/* USER CODE BEGIN StartTaskSEG */
/* Infinite loop */
for(;;)
{
for(uint8_t i =0;i<4;i++)
{
Write595(i,seg[i],0);
osDelay(5);
}
osDelay(1);
}
/* USER CODE END StartTaskSEG */
}
3、关于FreeRTOS的注意事项
注意点:
1、每个任务函数中都要有延时delay
2、osdelay使当前任务挂起,当延时结束,又唤醒当前任务,相当于释放了cpu。
而HALdelay在延时中还是会占用cpu资源的。
3、时间戳可以在不使用delay的情况下得到当前时间
4、os函数都需要在任务函数中调用
评论(1)
您还未登录,请登录后发表或查看评论