/**在串口助手,以十六进制向实验板发送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 <reg52.h>
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);
}
【单片机】定时器2捕获模式测试脉冲周期(实例)
最新推荐文章于 2023-10-19 19:08:56 发布