今天接着再学习《定时器周期性调度任务》
昨天在周期性任务介绍中已经知道如何通过数组用一个定时器实现多个任务和流水灯。
今天学习:
一,任务3按键1按一下,LED通过数组移动一下重点:按键不能在通过while判断是否按下松开了。因为,如果是多任务就可能会在while中出现死循环。怎么办?用定时器,当检测到按键连续按下后,按键计数变量+1,只要松开一下,计数清0,计数累积到50ms的时候判定为按下,实现LED通过数组移动一下的任务。而其他任务比如计时、打印等都可以照常执行基本不受影响。
二,文件的创建(.c和.h) 创建程序文件三步,1新建文件并保存,2添加到工程 ,3添加引用路径。一般一个.c和一个.h文件一起执行一个外设或者一个任务或功能。这样可以让代码看起来简洁明了注意函数定义添加文件一定要记得把引用路径添加到工程里。
三,结构体数组的周期性任务调度 在前面的任务:LED1 0.3秒闪一次,LED2 0.6秒闪一次,LED3 0.9秒闪一次之中他们1都有定时器1ms加的变量,2都有一个设定的计数目标,3都有需要执行的功能,4.定时时间到了才能执行。那么就可以采用结构体数组实现。
首先创建Task.h文件
#ifndef __TASK_H
#define __TASK_H
#include "config.h" //调用头文件
typedef struct
{
u8 Run; //任务状态:Run/Stop
u16 TIMCount; //定时计数器
u16 TRITime; //重载计数器
void (*TaskHook) (void); //任务函数
} TASK_COMPONENTS;
void Task_Marks_Handler_Callback(void);
void Task_Pro_Handler_Callback(void);
#endif
然后创建Task.c文件。
u8 Tasks_Max = sizeof(Task_Comps)/sizeof(Task_Comps);
void Task_Marks_Handler_Callback(void)
{
u8 i;
for(i=0; i<Tasks_Max; i++)
{
if(Task_Comps.TIMCount) /* If the time is not 0 */
{
Task_Comps.TIMCount--; /* Time counter decrement */
if(Task_Comps.TIMCount == 0) /* If time arrives */
{ /*Resume the timer value and try again */
Task_Comps.TIMCount = Task_Comps.TRITime;
Task_Comps.Run = 1; /* The task can be run */
}
}
}
}
void Task_Pro_Handler_Callback(void)
{
u8 i;
for(i=0; i<Tasks_Max; i++)
{
if(Task_Comps.Run) /* If task can be run */
{
Task_Comps.Run = 0; /* Flag clear 0 */
Task_Comps.TaskHook(); /* Run task */
}
}
}
在io.c文件创建执行函数
#include "io.h"
u8 State1 = 0; //LED1初始状态
u8 State2 = 0; //LED2初始状态
u8 State3 = 0; //LED3初始状态
u16 Key_Vol = 0; //按键按下持续时间
void LED0_Blink(void)
{
State1 = !State1;
P00 = State1;
}
void LED1_Blink(void)
{
State2 = !State2;
P01 = State2;
}
void LED2_Blink(void)
{
State3 = !State3;
P02 = State3;
}
void KEY_Task(void)
{
if( P32 == 0 )
{
Key_Vol++;
if( Key_Vol==5 )
{
//按键按下的任务
printf( "按键单击\r\n" );
}
}
else
{
Key_Vol = 0;
}
}
在io.h文件中声明有关函数
#ifndef __IO_H
#define __IO_H
#include "config.h" //调用头文件
void LED0_Blink(void);
void LED1_Blink(void);
void LED2_Blink(void);
void KEY_Task(void);
#endif
我觉得这个是今天学习的重点的重点照抄了一遍,以便加深理解。
今天学习新的一集《复位系统》
如果我们的设备的软硬件没有问题,但在运行中可能会受某些不确定因素的影响,出现某种未知的错误的时候,复位系统可以帮助我们通过复位操作来,使其能够恢复正确运行。
复位操作可以确保单片机在开始工作时处于已知的状态,使其能够正确初始化各个寄存器和外设。避免不确定行为:没有进行复位时,内部控制寄存器的内容可能是随机的,这可能导致定时器溢出、中断异常、外设误操作等不确定行为。初始化系统:复位操作可以进行系统的初始化,包括清除寄
存器、设置默认值、配置时钟等,为系统正常运行做好准备。保证程序正常开始执行:复位确保程序从正确的地址开始执行,避免跳转到未知的地址或执行错误的指令。
复位系统有1.硬件复位 2.软件复位
硬件复位有
1.上电复位(复位电压为1.7-1.9V)
2.低压复位:
3.复位脚复位:
以上复位功能需要在AIapp-ISP下载时 勾选有关选项。复位时间的长短,复位电压的检测等。例如,勾选允许低压复位选项后,当VCC电压低于设置的低压检测电压时,MCU会产生低压复位。如果不勾选允许低压复位选项,当VCC电压低于设置的低压检测电压时,MCU会产生低压中断标志。如果使能了低压中断的话,就会产生低压中断。
4.看门狗复位:
原来以为看门狗复位是软件复位,现在才知道在系统运行以后也就启动了看门狗的计数器,看门狗就开始自动计数,如果到了一定的时间还不去清理看门狗(也叫喂狗),那么看门狗计数器就会溢出从而引起看门狗中断,造成系统复位,属于硬件复位。所以,在使用有看门狗的芯片时要注意清理看门狗。但实际使用中也是需要在程序中编写有关代码设置看门狗复位溢出时间等。
软件复位只有一种。
只要在程序代码中写入IAP_CONTR=0x60或 IAP_CONTR=0x20就可以方便的进入下载模式或从头开始运行用户程序。
谢谢!冲哥辛苦了。{:4_213:}
宝贝收到了,谢谢STC提供的软硬件学习资源。{:4_250:}迫不及待的开始实际操作。
{:4_180:}新年好,几天放假,没想到课程就更新到16集了!冲哥辛苦了,谢谢!{:4_213:}
《定时器周期性调度任务》
这课内容多,知识点基础性强,非常重要。反复学习多次了。在最近的学习中遇到一个问题,就是按键没反应。
#ifndef __IO_H
#define __IO_H
#include "config.h" //调用头文件
#define KEY1 P34 //定义一个按键 引脚选择P32
#define KEY2 P35 //定义一个按键 引脚选择P33
void LED0_Blink(void);
void LED1_Blink(void);
void LED2_Blink(void);
void KEY_Task(void);
#endif
#include "io.h"
u8 State1 = 0; //LED1初始状态
u8 State2 = 0; //LED2初始状态
u8 State3 = 0; //LED3初始状态
u16 Key_Vol = 0; //按键按下持续时间
void LED0_Blink(void)
{
State1 = !State1;
P00 = State1;
}
void LED1_Blink(void)
{
State2 = !State2;
P01 = State2;
}
void LED2_Blink(void)
{
State3 = !State3;
P02 = State3;
}
void KEY_Task(void)
{
if( KEY1 == 0) //判断按键有没有按下
{
Key_Vol++;
if( Key_Vol==5 )
{
P04 = ~P04;
}
}
else if( KEY2 == 0) //判断按键有没有按下
{
Key_Vol++;
if( Key_Vol==5 )
{
P07 = ~P07;
}
}
Key_Vol = 0;
}
编译后LED显示正常,但按键按下没有反应。请问老师和高手问题出在那里?谢谢!{:4_196:}
把这段代码改了一下。好像问题解决了。{:4_165:}
void KEY_Task(void)
{
if( KEY1 == 0) //判断按键有没有按下
{
Key_Vol++;
if( Key_Vol==5 )
{
P04 = ~P04;
}
}
//------------------------------------------------按下熄灭,松开点亮 ------------------------------------------------
else if( KEY2 == 0) //判断按键有没有按下
{
Key_Vol++;
if( Key_Vol==5 )
{
P07 = ~P07;
}
}
else
{
Key_Vol = 0;
}
}
今天除了更新了串口的高级应用,还重新发布了DS18B20测温教学视频。继续打卡学习。看完了串口的高级应用的视频,期待学习MODBUS-RTU的通讯。