我是靠谱客的博主 凶狠茉莉,最近开发中收集的这篇文章主要介绍单片机定时任务的写法(单定时器多定时用法)(蓝桥杯单片机)原理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

原理

我们都知道单片机有定时器,但我们使用到多个需要定时的任务的时候,往往是在定时器中断中,加入定时时间以及标志,至少需要三个部分

  1. :用来计时的cnt
  2. :表示计时上限的定时时间
  3. :定时完成标志

传统写法如下:

void Timer1Handle() interrupt 3
{
	if(timecnt < time)
		timecnt++
	else
	{
		timecnt = 0;
		timecntOK = 1;
	}
}
 
void process()
{
	if(timecntOK)
	{
		timecntOK = 0;
		//you process code
	}
}

这种写法,运用到了定时器的特性,但是每创建一个定时器就需要3个变量,并且在写程序的时候,创建变量不是很方便。

于是经过一番思考,我想到了另外一个方法,使用一个timecnt,然后需要创建的定时器都和这个timecnt来进行对比从而进行定时。

首先贴上代码和效果(这个是在蓝桥杯板子上实验的,因此有些部分是板子上的,不用理会),我再解释

#include "STC15F2K60S2.h"
#include "stdio.h"
typedef unsigned char uchar;
typedef unsigned int uint;
#define OFF 1
#define ON 	0

sbit BP = P0^6; sbit RL = P0^4;
#define BP(x) 	 BP = x; P2 = P2 & 0x1f | 5 << 5; P2 = P2 & 0x1f
#define RL(x) 	 RL = x; P2 = P2 & 0x1f | 5 << 5; P2 = P2 & 0x1f

//define
enum{LED = 4, EXT, SEL, CODE};


//time
#define ntime sizeof(Inc_time)/sizeof(Inc_time[0])
enum{T1, T2, T3, T4};
uint code Inc_time[] = {500, 1000, 1500, 2000};
uint time[ntime];
uint timecnt = 0;



//display
uchar digSel = 0;
uchar code CA[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 
	                 0x92, 0x82, 0xf8, 0x80, 0x90};
uchar Buffer[] = {1, 2, 3, 4, 5, 6, 7, 8};

sbit t1 = P1^0; sbit t2 = P1^7; sbit t3 = P1^2; sbit t4 = P1^3;

//key

sbit K1=P3^0;	sbit K2=P3^1; sbit K3=P4^2; sbit K4=P3^3;
enum{KS_GT, KS_AS, KS_WD}keyState = KS_GT;
uchar keyCnt = 0, tempKey = 0, key = 0;



void Timer1Init(void)		//2毫秒@11.0592MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x9A;		//设置定时初值
	TH1 = 0xA9;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	ET1 = 1;
	EA = 1;
}

void UartInit(void)		//9600bps@11.0592MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x01;		//串口1选择定时器2为波特率发生器
	AUXR |= 0x04;		//定时器2时钟为Fosc,即1T
	T2L = 0xE0;		//设定定时初值
	T2H = 0xFE;		//设定定时初值
	AUXR |= 0x10;		//启动定时器2
	ES = 0;
}


void SL(char da, char num)
{
	P0 = da;
	P2 = P2 & 0x1f | num << 5; P2 = P2 & 0x1f;
}

uchar GetKey()
{
	if(K1 == 0) return 1;
	else if (K2 == 0) return 2;
	else if (K3 == 0) return 3;
	else if (K4 == 0) return 4;
	else return 0;
}


void Init(void)
{
	uchar i = 0;
	BP(ON);RL(ON);
	SL(0xff, LED);
	for(;i < ntime; i++)
	{
		time[i] = Inc_time[i];	
	}
}

void Timer1Handle() interrupt 3
{
	SL(0xff, CODE);
	SL(1 << digSel, SEL);
	SL(CA[Buffer[digSel]], CODE);
	digSel = (digSel +1)%8;

	switch(keyState)
	{
	 case KS_GT:
	 	keyState = KS_AS;
		keyCnt = 10;
		tempKey = GetKey();
	 break;

	 case KS_AS:
	  if(keyCnt-- != 0);
		else if(tempKey == GetKey())
		{
		 if(tempKey != key)
		 {
		  key = tempKey;
			keyState = KS_WD;
		 }
		 else
		 {
		  keyState = KS_GT;
		 }
		}
		else
		 keyState = KS_GT;
	 break;
	}
	{
		uchar i;
		for(i = 0;i < ntime; i++)
		{
			if((timecnt == 65535) || (timecnt == time[i]))
			time[i] += Inc_time[i];
		}
		timecnt++;
	}
}


void test1()
{
	static uint Stime = 500;
	if(Stime != time[T1])
	{
		Stime = time[T1];
		TI = 1;
		printf("t1rn");
		t1 = ~t1;
	}
}
void test2()
{
	static uint Stime = 1000;
	if(Stime != time[T2])
	{
		Stime = time[T2];
		TI = 1;
		printf("t2rn");
		t2 = ~t2;
	}
}
void test3()
{
	static uint Stime = 1500;
	if(Stime != time[T3])
	{
		Stime = time[T3];
		TI = 1;
		printf("t3rn");
		t3 = ~t3;
	}
}
void test4()
{
	static uint Stime = 2000;
	if(Stime != time[T4])
	{
		Stime = time[T4];
		TI = 1;
		printf("t4rn");
		t4 = ~t4;
	}
}


void main()
{
 	Init();
	UartInit();
	Timer1Init();
	while(1)
	{
	 test1();
	 test2();
	 test3();
	 test4();					
	}

}

效果

在这里插入图片描述

初始化部分

//time
#define ntime sizeof(Inc_time)/sizeof(Inc_time[0])
enum{T1, T2, T3, T4};
uint code Inc_time[] = {500, 1000, 1500, 2000};
uint time[ntime];
uint timecnt = 0;


//为了方便创建定时任务所增加改动的步骤减少,因此这里写一个赋值初始化函数
void Init(void)
{
	uchar i = 0;
	for(;i < ntime; i++)
	{
		time[i] = Inc_time[i];	
	}
}

定时器部分

void Timer1Handle() interrupt 3
{
	uchar i;
	for(i = 0;i < ntime; i++)
	{
		if((timecnt == 65535) || (timecnt == time[i]))
		time[i] += Inc_time[i];
	}
	timecnt++;
}

流程图

Created with Raphaël 2.2.0 定时器开始 是否到达最后一个需要判断的定时? 定时器结束 timecnt是否为65535 或者当前timecnt等于当前的定时时间? 将当前定时时间+需要定时时间 yes no yes no

也就是说有一个定时器在走,而且不会停,但是它有一个特点就是到了65535就会归0
这个时候有一个数组,里面装的都是定时的时间,然后每次定时器计数+1的时候,都会和这个数组里面的一一判断,当相同的时候,说明它定时的时间到达。并且当前数组元素的值要+它定时的值,以下次到达定时的时间。

因为65535归0的特性。如果当一个定时到达65535的时候,所有在数组中的元素都应该+它定时的值,这样才能保证每个定时任务的定时是完整的!
如果不理解,可以在纸上画一遍流程就知道为什么到达65535要将所有的数据都+它定时的值了

最后

以上就是凶狠茉莉为你收集整理的单片机定时任务的写法(单定时器多定时用法)(蓝桥杯单片机)原理的全部内容,希望文章能够帮你解决单片机定时任务的写法(单定时器多定时用法)(蓝桥杯单片机)原理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(64)

评论列表共有 0 条评论

立即
投稿
返回
顶部