51单片机定时器总结

1.定时器TMOD寄存器

C/T这一位用来控制定时器工作方式。本来T上面有一横表示低电平有效。c为计数,也即是及外部脉冲的个数,也会是定时器溢出及中断。GATE这一位用来设定外部中断脉冲是否可启动定时器。 意思就是当GATE=1时,定时器的启动有二个位控制,即TR0和int0(这是对定时器0来说的,T1的话上二位就是1)。定时器只有在上二位都是一的情况下才会启动。我们就可以利用这个功能来测量脉冲的宽度。

我们知道在其他单片机中我们测脉冲宽度可以利用外部中断在上升沿河下降沿各读取一次定时器值来测定。但51单片机没有上升沿中断,也就没有办法测出高电平宽度。现在我们可以这样做,令TR0=1,GATE=1,这时定时器的启动只有INT0控制。当INT0为高电平时定时器启动,为低电平时定时器关闭。我们设置下降沿中断,在中断中就可以读取高电平所占的时间了。但是这样做只能得到高电平时间按。要想得到脉冲周期,可以再开一个定时器,另外一个就正常工作,这样就可以得到脉冲周期。也就可以求出脉冲宽度了。 

T0的工作方式3相信很少人记得,我还没有用过,但是我感觉做起码在我们需要用到的时候,还知道有这个功能。方式3可以把T0当作二个独立的计数器使用。在高级应用中肯定会有用吧。

定时器会存在误差,原因是在执行定时器中断的时候,会占用3到8个机器周期不等。这段时间我们并没有算到计数器初值里面。要想消除误差:1.可以把定时器低八位设为0,中断中只要给TH0赋值,因为此时定时器已经开始启动了,低八位其实已经不是0了。2.将低四位设为0.赋初值时,利用ORL TL1,#        ;加上你设定的初值。还有其他方法。

还有一点T0和T1的工作方式2看似工作方式是一样的,其实T1在方式2的时候不能中断,而T0是可以中断的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在ClassWizard中响应ID为~Dlg中的WM_TIMER消息。 使用SetTimer(nIDEvent,time,NULL)来建立一个定时器,关闭定时器用KillTimer(nIDEvent)函数。 然后可以响应ON_WM_TIMER消息来响应一个定时器完成一次记时后的程序。 响应方式如下: void CTimeDlg::OnTimer(UINT nIDEvent) { if(nIDEvent==1000)//间隔为5秒 { //处理事件 } elseif(nIDEvent==1001)//间隔为10秒 { //处理事件 } CDialog::OnTimer(nIDEvent); } 以下是给出一个串口通信定时检查接收数据的部分代码 void CMyDlg::OnOpenCom() { // TODO: Add your control notification handler code here if( f_open_com==true ) { f_open_com = false; GetDlgItem(IDC_OPEN_COM)->SetWindowText("打开通信端口"); CloseHandle(hComm); KillTimer(1000); /// 关闭定时器 return ; } SetTimer(1000, 1000, NULL); ///nIDEvent==1000,time=5000ms const char *ComNo; DCB dcb; string temp("COM1"); ComNo = temp.c_str(); hComm = CreateFile( ComNo , GENERIC_READ|GENERIC_WRITE , 0 , NULL , OPEN_EXISTING , 0 , 0); if( hComm==INVALID_HANDLE_VALUE ) /// 如果端口未打开 { MessageBox("打开通信端口出错!" , "Comm Error" , MB_OK); return ; } /// 将dcb地址传入,以取得通信参数 GetCommState(hComm,&dcb); /// 得知目前通信状态 dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; /// 字节为8 dcb.Parity = NOPARITY; /// Parity为None dcb.StopBits = ONESTOPBIT; /// 1个停止位 if( !SetCommState( hComm , &dcb)){ MessageBox("通信端口设置出错!" , "Set Error" , MB_OK ); CloseHandle(hComm); return; } GetDlgItem(IDC_OPEN_COM)->SetWindowText("关闭通信端口"); f_open_com = true; } void CMyDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default char inbuff[1024]; DWORD nBytesRead , dwError; COMSTAT cs; /// 取得状态 ClearCommError( hComm , &dwError , &cs); /// 数据是否大于所准备的缓冲区 if( cs.cbInQue > sizeof(inbuff) ) { PurgeComm(hComm , PURGE_RXCLEAR ); /// 清除通信端口数据 return ; } ReadFile(hComm , inbuff , cs.cbInQue , &nBytesRead , NULL ); //接收通信端口的数据 inbuff[cs.cbInQue] = '\0'; MessageBox("打开通信端口出错!" , "Comm Error" , MB_OK); m_Receive.Format("%s",inbuff); UpdateData(false); CDialog::OnTimer(nIDEvent); } 李杨: for(int i=0; ;i++ ) { ... Sleep(5); if(i>...) {AfxMessageBox("错误XXX"); return;} }//跳出后记得停止一些机器动作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值