[51单片机] 定时器跑时间状态机采集18B20数据已成功,STC15W204S。

[复制链接]
 楼主| oufuqiang 发表于 2015-5-6 01:42 | 显示全部楼层 |阅读模式
  1. 没有使用软件延时的18B20驱动程序  (STC15W204S 1T 8051) 使用标准8051单片机需要将_nop_();的个数减少到2个。

  2. 很简单,只要把定时器设置为模式1,并开启总中断,定时器中断,再把这个中断程序贴进去就可以了。
  3. 在需要使用温度数据的地方,查询convfinsh标志状态,如果这个标志变成1,那么说明一个温度数据已经采集到了。拿去用即可
  4.                 if(convfinsh==1)
  5.                 {
  6.                         dispval=TempRes*625L;
  7.                         sendbuff[5]='0'+(dispval%10000000)/1000000;
  8.                         sendbuff[6]='0'+(dispval%1000000)/100000;
  9.                         sendbuff[7]='0'+(dispval%100000)/10000;
  10.                         sendbuff[9]='0'+(dispval%10000)/1000;
  11.                         sendbuff[10]='0'+(dispval%1000)/100;
  12.                         sendbuff[11]='0'+(dispval%100)/10;
  13.                         sendbuff[12]='0'+(dispval%10);
  14.                         send(sendbuff,17);
  15.                         while(sending);
  16.                         convfinsh=0;
  17.                 }

  18. 以下是中断服务程序:
  19. void timer0(void) interrupt 1
  20. {
  21.         static unsigned char step=1,cmd,bitcount;
  22.         DQ=1;
  23.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  24.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  25.         switch(step)
  26.         {
  27.         case 1:DQ=0;TH0=(65536-480)/256;TL0=(65536-480)%256;step=2;break;
  28.         case 2:DQ=1;TH0=(65536-70)/256;TL0=(65536-70)%256;step=3;break;
  29.         case 3:if(DQ==1){step=1;}else{TH0=(65536-300)/256;TL0=(65536-300)%256;step=4;}break;
  30.         case 4:cmd=0xcc;step=5;bitcount=0;break;
  31.         case 5:
  32.         DQ=0;
  33.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  34.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  35.         DQ=cmd&0x01;cmd=cmd>>1;TH0=(65536-80)/256;TL0=(65536-80)%256;
  36.   bitcount++;if(bitcount==8){cmd=0x44;step=6;bitcount=0;}break;
  37.         case 6:
  38.         DQ=0;
  39.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  40.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  41.         DQ=cmd&0x01;cmd=cmd>>1;TH0=(65536-80)/256;TL0=(65536-80)%256;
  42.   bitcount++;if(bitcount==8){step=7;}break;
  43.         case 7:
  44.         DQ=0;
  45.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  46.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  47.         DQ=1;
  48.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  49.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  50.         if(DQ==1){step=8;}TH0=(65536-6000)/256;TL0=(65536-6000)%256;break;
  51.         case 8:DQ=0;TH0=(65536-480)/256;TL0=(65536-480)%256;step=9;break;
  52.         case 9:DQ=1;TH0=(65536-70)/256;TL0=(65536-70)%256;step=10;break;
  53.         case 10:if(DQ==1){step=1;}else{TH0=(65536-300)/256;TL0=(65536-300)%256;step=11;}break;
  54.         case 11:cmd=0xcc;step=12;bitcount=0;break;
  55.         case 12:
  56.         DQ=0;
  57.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  58.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  59.         DQ=cmd&0x01;cmd=cmd>>1;TH0=(65536-80)/256;TL0=(65536-80)%256;
  60.   bitcount++;if(bitcount==8){cmd=0xbe;step=13;bitcount=0;}break;
  61.         case 13:
  62.         DQ=0;
  63.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  64.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  65.         DQ=cmd&0x01;cmd=cmd>>1;TH0=(65536-80)/256;TL0=(65536-80)%256;
  66.   bitcount++;if(bitcount==8){step=14;bitcount=0;}break;
  67.         case 14:
  68.         DQ=0;
  69.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  70.         _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  71.         DQ=1;
  72.         tempbindata=tempbindata>>1;if(DQ==1){tempbindata=tempbindata|0x8000;}
  73.         bitcount++;if(bitcount==16){TempRes=tempbindata;convfinsh=1;step=1;}
  74.         TH0=(65536-80)/256;TL0=(65536-80)%256;break;
  75.   }
  76. }
ayb_ice 发表于 2015-5-6 08:04 | 显示全部楼层
在主循环里搞个状态机,根本不需要什么长延时,关键时刻关中断即可

你这一样受高级中断的影响
 楼主| oufuqiang 发表于 2015-5-6 09:35 | 显示全部楼层
ayb_ice 发表于 2015-5-6 08:04
在主循环里搞个状态机,根本不需要什么长延时,关键时刻关中断即可

你这一样受高级中断的影响 ...

在主循环里面搞状态机,在写位数据的时候关闭中断,这个我已经写过了,在等待转换结束的逻辑里面看着不是很舒服,虽然用状态机等这750mS并不会阻塞程序的运行。现在写成定时器的,就当做后台服务一样,不用管它,要取温度的时候去拿数据就可以了。

其实我写之前为了避免无畏的重复已经搜索过别人写的状态机,包括主循环里面的,定时器的,VHDL硬件的等等。看着都不是很爽,所以就自己写了个。
ayb_ice 发表于 2015-5-6 11:04 | 显示全部楼层
oufuqiang 发表于 2015-5-6 09:35
在主循环里面搞状态机,在写位数据的时候关闭中断,这个我已经写过了,在等待转换结束的逻辑里面看着不是 ...

写成这种形式

bit ds18b20_call(U8* p)
{
        ....
}

主循环一直调用这个函数,判断返回值成功后,从P中获取结果,

内部完成细节,每10MS循环一次,这个函数不会大于10MS的阻塞,

我一般都是这样做的,内部其实也就是个状态机,把一个长的过程转换成了多个步骤
wangpeng59 发表于 2015-12-2 22:53 | 显示全部楼层
在时间上,我也是一直很困扰,写这个程序很容易把自己绕进去
您需要登录后才可以回帖 登录 | 注册

本版积分规则

107

主题

1454

帖子

21

粉丝
快速回复 在线客服 返回列表 返回顶部