找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2056|回复: 10
收起左侧

这段单片机程序具体什么意思?为什么先要给TMR0两个计数

[复制链接]
ID:216579 发表于 2021-12-4 11:51 | 显示全部楼层 |阅读模式
for(i =y;i>0;i--)
     {
     TMR0 = 0xD9; //延时10ms
     CountOld  = TMR0;
     CountNew = TMR0;
     while (CountNew  >= CountOld)   
     {
         CountOld = CountNew;
         CountNew = TMR0;
     }
     }
为什么先要给TMR0两个计数

回复

使用道具 举报

ID:624769 发表于 2021-12-4 23:44 | 显示全部楼层
代码不全,没办法给你解释清楚。
只能告诉你,有另外一个中断程序,会改写 TMR0

     while (CountNew  >= CountOld)   
     {
         CountOld = CountNew;
         CountNew = TMR0;
     }
当 TMR0 在另外一个中断的作用下,减小的时候,会跳出 这个 while, 反之,会死在这个循环里 至于具体如何跳出这个外面这个for, 要看y的定义了。
回复

使用道具 举报

ID:216579 发表于 2021-12-6 08:49 | 显示全部楼层
int mydelay_ms(int y)  //延时 y*10 ms
{
    uchar i;
   

     for(i =y;i>0;i--)
     {
     TMR0 = 0xD9; //延时10ms
     CountOld  = TMR0;
     CountNew = TMR0;
     while (CountNew  >= CountOld)   
     {
         CountOld = CountNew;
         CountNew = TMR0;
     }
     }
}
回复

使用道具 举报

ID:216579 发表于 2021-12-6 08:49 | 显示全部楼层
int mydelay_ms(int y)  //延时 y*10 ms
{
    uchar i;
   

     for(i =y;i>0;i--)
     {
     TMR0 = 0xD9; //延时10ms
     CountOld  = TMR0;
     CountNew = TMR0;
     while (CountNew  >= CountOld)   
     {
         CountOld = CountNew;
         CountNew = TMR0;
     }
     }
}
回复

使用道具 举报

ID:155507 发表于 2021-12-6 10:55 | 显示全部楼层
PIC16f877a 具有三个独立的定时器,可用作定时器、计数器或用于 PWM 生成。

Timer 0
TMR0 模块是一个 8 位定时器/计数器,具有以下特性:

  • 8位定时器/计数器
  • 可读可写
  • 8 位软件可编程预分频器
  • 内部或外部时钟选择
  • 从 FFh 溢出到 00h 时中断
  • 外部时钟的边沿选择

Timer0_Block_Diagram.png


这段单片机程序具体的意思是用定时器实现准确的延时程序




回复

使用道具 举报

ID:216579 发表于 2021-12-6 11:02 | 显示全部楼层
angmall 发表于 2021-12-6 10:55
PIC16f877a 具有三个独立的定时器,可用作定时器、计数器或用于 PWM 生成。

Timer 0

单片机用的PIC10F200, 没有中断
回复

使用道具 举报

ID:624769 发表于 2021-12-6 16:51 | 显示全部楼层
guhuawei19 发表于 2021-12-6 11:02
单片机用的PIC10F200, 没有中断

不管有没有中断, TMR0 是定时器吧? 理论上 TMR0 向上计数吧? 当TMR0 溢出之后,

while (CountNew  >= CountOld)   
     {
         CountOld = CountNew;
         CountNew = TMR0;
     }
这段代码里面的, CountNew 就 小于 CountOld 了吧? 这个时候 就会跳出这个 while, for 里面的 i 就会减1, 减到0 延时结束,子函数返回。不过,没明白为啥搞这么复杂……, 感觉这么写就可以了吧……

int mydelay_ms(int y)  //延时 y*10 ms
{
    while(y--)
     {
     TMR0 = 0xD9; //延时10ms
     while(TMR0>=0xD9);
     }
}

回复

使用道具 举报

ID:401564 发表于 2021-12-6 22:53 | 显示全部楼层
guhuawei19 发表于 2021-12-6 08:49
int mydelay_ms(int y)  //延时 y*10 ms
{
    uchar i;

XC8编译器自带延时函数  __delay_ms()
PICC编译器好像功能更多,延时函数肯定是有的
已经有现成的,就不需要去折腾那么多
为什么要两个计数,有可能就是单纯的增加指令来消耗时间而已
CountOld CountNew 是全局变量吗?说不定在其它地方还有用得着的
回复

使用道具 举报

ID:216579 发表于 2021-12-11 12:59 | 显示全部楼层
Y_G_G 发表于 2021-12-6 22:53
XC8编译器自带延时函数  __delay_ms()
PICC编译器好像功能更多,延时函数肯定是有的
已经有现成的,就不 ...

全局变量
回复

使用道具 举报

ID:990881 发表于 2021-12-11 14:54 | 显示全部楼层
一个是保存的0XD9一个保存实时的TMR0值,当溢出时退出while循环即延时10ms
回复

使用道具 举报

ID:962286 发表于 2021-12-29 10:50 | 显示全部楼层
188610329 发表于 2021-12-6 16:51
不管有没有中断, TMR0 是定时器吧? 理论上 TMR0 向上计数吧? 当TMR0 溢出之后,

while (CountNew  > ...

你的理解是对的,不过这种阻塞延时直接用编译器的延时宏即可,用定时器反而麻烦且浪费资源。以PIC10F200为例:
  1. #define _XTAL_FREQ                4000000

  2. void DelayXmS(unsigned int _Delay)
  3. {
  4.         unsigned int i;

  5.         for(i = 0; i < _Delay; i++)
  6.         {
  7.                 __delay_ms(1);
  8.                 CLRWDT();
  9.         }
  10. }
复制代码
__delay_ms(x) 是一个延时宏,并非函数,x只能是立即数,所以得封装一下。

当然对于大部分应用,很多阻塞延时是可以用状态机轮询来实现的,这样CPU资源不会被阻塞占用,整个系统的实时性会很好控制。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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