找回密码
 注册会员
更新自动建库工具PCB Footprint Expert 2024.04 Pro / Library Expert 破解版

关于多任务和资源复用举例学习笔记

[复制链接]
admin 发表于 2012-9-2 10:41:12 | 显示全部楼层 |阅读模式

本文包含原理图、PCB、源代码、封装库、中英文PDF等资源

您需要 登录 才可以下载或查看,没有账号?注册会员

×
/*************************************************************************************

单片机程序的多任务和资源复用举例


以前思考过有关多按键同时按下的编程思想,如当有两个按键,控制设备的两个不同部分。

要求实现:

 每个按键按下,相应控制程序运行。但两个按键可以同时按下,就是说两个控制程序可能

需要同时运行。如何编写程序?

注:此程序不使用RTOS等操作系统。

说明:

 1.产生波形可以使用中断中计数来产生精确的波形。本方案能体现出程序的多任务和资源复

用问题。

 2.题意是两个程序在并发运行,也就是扩展到多个不同任务同时运行,在此就不讨论。


*************************************************************************************/
#include <reg52.h>

//------------------- Timer ------------------------
bit fTimer0_2ms; //T0中断产生的标志,准备传递给主循环
bit fSYS_2ms; //系统T0中断产生的标志,12M,主循环使用
bit fSYS_20ms; //每20MS产生一次的消息

#define INT2MSCOUNT 10 //产生2MS所需要的时间次数
unsigned char data mTimer_2msReg=INT2MSCOUNT; //产生2MS所需要的寄存器
#define INT20MSCOUNT 10 //产生20MS所需要的时间次数,在20MS基础上
unsigned char data mTimer_20msReg=INT20MSCOUNT; //产生20MS所需要的寄存器,在20MS基础上

//-------------------- KEY --------------------------
unsigned char data mKey1SwapTask; //按键任务寄存器
unsigned char data mKey2SwapTask; //按键任务寄存器
sbit iKey1=P1^0; //按键的输入口

sbit iKey2=P1^1;

bit fKey1; //为简单化,没使用队列保存键值,使用标志
bit fKey2; //为简单化,没使用队列保存键值,使用标志


//------------------- Task1 --------------------------
unsigned char data mTask1Id; //任务一的任务号
unsigned char data mTask1_1HzReg; //1hz时间寄存器
unsigned int data mTask1_2SReg; //2S时间寄存器
sbit oTask1=P1^2; //输出方波口

//------------------ Task2 ---------------------------
unsigned char data mTask2Id; //任务二的任务号
unsigned char data mTask2_1p2HzReg; //1.2hz时间寄存器
sbit oTask2=P1^3; //输出方波口

//---------- 产生以1MS为基础的系统定时信号,T0作为基准定时器 ----
void Timer0_Init() // 定时器T0初始化0.2MS,12M
{
TMOD|=0x2; //8位定时器
TL0=TH0=~(200)+1; //12M
TR0=1;
ET0=1;
}

//------------- 定时器0的中断服务,产生fTimer0_2ms ---------------
void timer0(void) interrupt 1 //T0中断
{
mTimer_2msReg--;
if(mTimer_2msReg==0)
{
mTimer_2msReg=INT2MSCOUNT; //产生1MS所需要的寄存器
fTimer0_2ms=1;
}
}

//---------------------- 控制消息fSYS_2ms ------------------------
void Timer0_MainLoop()
{
fSYS_2ms=0;
fSYS_20ms=0;

if(fTimer0_2ms)
{
fTimer0_2ms=0; //接收中断过来的时间标志,转换为消息
fSYS_2ms=1; //此消息在一周内有效,被外部程序复用
mTimer_20msReg--; // 产生20MS的消息
if(mTimer_20msReg==0)
{
mTimer_20msReg=INT20MSCOUNT; //产生20MS所需要的寄存器,在20MS基础上
fSYS_20ms=1;
}
}
}

//---------------- 按键扫描,包含两个扫描任务 ------------------
void Key_MainLoop( )
{
if(fSYS_20ms==0)return;
switch(mKey1SwapTask)
{
case 0: //有按键按下吗?
if(iKey1==0)
{
mKey1SwapTask=1;
}
break;
case 1: //键按下去抖延时
mKey1SwapTask=2;//延时一个系统时间
break;
case 2: //键值判断
if(iKey1==0)
{
fKey1=1; //按键有效
mKey1SwapTask=3; //去按键去抖
}
else
mKey1SwapTask=0; //抖动
break;
case 3: //有松开吗?
if(iKey1==1)
{
mKey1SwapTask=4;
}
break;
case 4: //键松开去抖延时
mKey1SwapTask=5;//延时一个系统时间
break;
case 5: //键值判断
if(iKey1==1)
{
mKey1SwapTask=0;//去按键检测开始
}
else
mKey1SwapTask=3; //抖动
break;
}
switch(mKey2SwapTask)
{
case 0: //有按键按下吗?
if(iKey2==0)
{
mKey2SwapTask=1;
}
break

case 1: //键按下去抖延时
mKey2SwapTask=2;//延时一个系统时间
break;
case 2: //键值判断
if(iKey2==0)
{
fKey2=1;//按键有效
mKey2SwapTask=3;//去按键去抖
}
else
mKey2SwapTask=0; //抖动
break;
case 3: //有松开吗?
if(iKey2==1)
{
mKey2SwapTask=4;
}
break;
case 4: //键松开去抖延时
mKey2SwapTask=5;//延时一个系统时间
break;
case 5: //键值判断
if(iKey2==1)
{
mKey2SwapTask=0;//去按键检测开始
}
else
mKey2SwapTask=3; //抖动
break;
}
}

//--------- 任务一 输出1HZ的方波,2S后停止 ----------------
/**********************************************
一个部分。
**********************************************/
void Task1_MainLoop()
{
switch(mTask1Id)
{
case 0: if(fKey1)
{
fKey1=0; //接收该键值
mTask1_1HzReg=500/2; //1hz时间寄存器,500ms,以2MS为单位
mTask1_2SReg=2000/2; //2S时间寄存器,500ms,以2MS为单位
oTask1=0;
mTask1Id=1;
}
break;
case 1: if(fSYS_2ms)
{
mTask1_1HzReg--;
if(mTask1_1HzReg==0)
{
oTask1=~oTask1;
mTask1_1HzReg=500/2;//1hz时间寄存器,500ms,以2MS为单位
}
mTask1_2SReg--;
if(mTask1_2SReg==0)
{
oTask1=1;//2S时间到
mTask1Id=0;
}
}
break;
}
}

//------------ 任务二 输出1.2hz的方波,直到按键再次按 --------------------
void Task2_MainLoop()
{
switch(mTask2Id)
{
case 0: if(fKey2)
{
fKey2=0; //接收该键值
mTask2_1p2HzReg=416/2; //1hz时间寄存器,832/2ms,以2MS为单位
oTask2=0;
mTask2Id=1;
}
break;
case 1: if(fKey2)
{
fKey2=0;
oTask2=1;
mTask2Id=0;
}
else
{
if(fSYS_2ms)
{
mTask2_1p2HzReg--;
if(mTask2_1p2HzReg==0)
{
oTask2=~oTask1;
mTask2_1p2HzReg=416/2; //1hz时间寄存器,832/2ms,以2MS为单位
}
}
}
break;
}
}
//--------------- 主程序 ---------------
void main()
{
Timer0_Init();
EA=1;

while(1)
{
Timer0_MainLoop();
Key_MainLoop();
Task1_MainLoop();
Task2_MainLoop();
}
}
*滑块验证:
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

QQ|手机版|MCU资讯论坛 ( 京ICP备18035221号-2 )|网站地图

GMT+8, 2024-11-24 17:55 , Processed in 0.054657 second(s), 11 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表