【单片机】定时器2捕获模式测试脉冲周期(实例)

/**在串口助手,以十六进制向实验板发送01命令,表示启动定时器2的捕获模式,并返回“Captch On!”,以十
***六进制向实验板发送02命令,使P1.1产生一次负跳变,第一次负跳变时,串口助手显示”Fisrt 
***Drump!020s 50272us“,第二次负跳变时,显示”Second Drump! 023s 22296us“并返回两次负跳变之间
***的脉冲周期“Result is:002s 37560us”,当以十六进制向实验板发送02命令时,表示停止定时器2的捕获
***模式,并返回“Captch Off!”。发送其他命令时,返回“Error!”
**/
#include 
typedef unsigned char uchar;		//重命名,方便写
typedef unsigned int  uint;

uint 	countVal;					//存放两次跳变之间的计数值
uchar 	exT2flag, command, sec, tempflag;
bit 	busy;						//串口发送完成标志
sbit 	drump = P1^1;				//声明P1^1外部引脚

void init(void);					//参数初始化
void SendData(uchar);				//串口发送字符
void SendString(uchar*);			//串口发送字符串
void SendNum(uchar);				//串口发送8位无符号整型数值
void SendValue(uint);				//串口发送16位无符号整型数值

void init()
{
	TMOD  = 0x20;					//定时器1 工作方式1
	TH1   = 0xfd;			 		//定时器1作为串口波特率发生器,8位计数器,波特率9600,SMOD=0不加倍,
	TL1   = 0xfd;					//根据公式算的初始值为253即0xfd
	TH2   = (65536-45872)/256;		//定时器2初始值,16位,一次溢出需计数(2^16=65536)个,这里延时50ms,计数一个的时间为12个机器周期的时间
	TL2   = (65536-45872)%256;		//即(12/11.0592约等于1.09),即延时50ms需要计数(50000/1.09约等于45872)个
	T2CON = 0x09;					//EXEN2=1, CP/RL2=1;
	SM0   = 1;						//串行工作方式1
	SM1   = 1;						//同上
	TR1   = 1;						//启动定时器1
	REN	  = 1;						//允许串行口接收数据
	EA    = 1;						//开总中断
	ET2   = 1;						//开定时器2中断
	ES    = 1;						//开串行口中断
}

void main()
{
	uint s1, us1, s2, us2, s, us;	//存放计数的时间
	init();
	SendString("Hello Manager!\n");	//测试串口
	while(1)
	{
		drump = 1;					//为负跳变做准备
		if(exT2flag == 1)			//表示第一次产生负跳变
		{
			s1  = sec;				//第一次产生负跳变时,已发生中断的次数(或时间)
			us1 = countVal;			//第一次产生负跳变时,陷阱寄存器的值
			SendString("Fisrt Drump! ");
			SendNum(s1);
			SendString("s ");
			SendValue(us1);
			SendString("\n");
			exT2flag = 0;
		}
		if(exT2flag == 2)			//表示第二次产生负跳变
		{
			s2  = sec;				//同上
			us2 = countVal;
			exT2flag = 0;
			SendString("Second Drump! ");
			SendNum(s2);
			SendString("s ");
			SendValue(us2);
			SendString("\n\n");
			exT2flag = 0;
			
			if(us2>=us1)			//比较两次产生负跳变时,陷阱寄存器的值
			{
				s  = s2 - s1;		//计算两次负跳变之间产生的中断次数(或时间)
				us = us2 - us1;
			}else					//如果第二次的陷阱寄存器比第一次小,则需要向上一次中断借1位
			{
				if(s2<=s1+1) s = 0;
				else		s  = s2 - s1 - 1;
				us = (65536-us1)-(65536-us2);//进行us2-us1时是负数,避免发生错误则需借一位
			}
			SendString("Result is:");
			SendNum(s);
			SendString("s ");
			SendValue(us);
			SendString("\n\n");			
		}
		switch(command)
		{
			case 1:	SendString("Captch On!\n");	
					TR2 = 1;		//启动定时器2
					command = 0;	
					break;
			case 2: drump = 0;		//产生一次负跳变
					command = 0;	
					break;		
			case 3: SendString("Captch Off!\n");
					TR2 = 0;		//关闭定时器2
					command = 0;
					break;
			case 4:	SendString("Error!\n");
					command = 0;
					break;
		}
	}
}

void T2_time() interrupt 5
{
	static uint a, b;
	if(EXF2)						//外部中断产生负跳变
	{
		EXF2 = 0;
		countVal = ((RCAP2H|0x00)<<8)|(RCAP2L|0x00);
		a++;
		if(a>2) a = 1;	
		if(a==1) exT2flag = 1;
		if(a==2) exT2flag = 2;
		RCAP2L=0x00;    			//陷阱寄存器清零
    	RCAP2H=0x00;	
	}
	if(TF2)							//溢出中断
	{
		TF2 = 0;
		b++;
		if(b==20)					//20个50ms即1秒
		{
			b = 0;
			sec++;					//秒累加
		}
	}
}

void Ser_uart() interrupt 4
{
	uchar temp;
	if(RI)							//接收中断标志位
	{
		RI = 0;						//清除接收中断标志位
		temp = SBUF;				//获取串口缓冲寄存器的值
		if(temp==0x01) 		command = 1;
		else if(temp==0x02) command = 2;
		else if(temp==0x03) command = 3;
		else				command = 4;
	}
	
	if(TI)							//发送中断标志位
	{
		TI = 0;
		busy = 0;					//发送完成标志
	}
}

void SendData(uchar dat)
{
	while(busy);					//等待上一次数据发送完成
	busy = 1;
	SBUF = dat;						//发送当前数据
}

void SendString(uchar *str)			
{
	while(*str)
	{
		SendData(*str++);
	}
}

void SendNum(uchar dat)
{
	SendData(dat/100+48);
	SendData(dat%100/10+48);
	SendData(dat%100%10+48);
}

void SendValue(uint value)
{
	SendData(value/10000+48);		
	SendData(value%10000/1000+48);
	SendData(value%10000%1000/100+48);
	SendData(value%10000%1000%100/10+48);
	SendData(value%10000%1000%100%10+48);
}

你可能感兴趣的:(单片机,单片机)