打印

DS18B20关中断时,扫描LED段码闪烁处理

[复制链接]
2068|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sjg_mcu|  楼主 | 2009-10-16 22:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我使用DS18B20测温,因时序严格,中断要关,而8段LED使用中断动态扫描,关掉中断后LED有屏闪,不关中断DS18B20读数不准.
以下为源程序.
18B20部分:已调试通过
//=================================================================================================
//ds18b20专用延时子程序
//=================================================================================================
void delayll(uint x){ for(;x>0;x--);}
//=================================================================================================
//ds18b20复位函数
//=================================================================================================
void ow_reset(void)
{ uchar presence=1; uint temp;
GIE=0;                //在DS18B20读出温度数据时最好关闭中断               
while(presence==1)          //标志位为1一直循环,该位会在DS18B20复位成功后归0退出循环
  { TRISA2=0;asm("nop");asm("nop");  //接DS18B20信号线的IO设置为输出,并稳定一段小时间
   DQ=1;asm("nop");asm("nop");DQ=0; //开始产生低电平
   delayll(50);            //持续550us
   DQ=1;               //撤销低电平
   delayll(6);             //等待66us
   TRISA2=1;asm("nop");asm("nop");  //将IO设置为输入开始检测复位成功的低电平信号出现
   presence=DQ;           //读取信号,如果该信号为0说明复位成功,并退出循环
   //以下小部分是附加功能,非驱动部分,功能是探头拔下或损坏报警-----------------------------------
   temp++;if(temp>2000){GIE=1;disp_add=2;disp_menu();} //goto loop;探头异常 显示Err,并有报警声
  } temp=0;
  while(DQ==0)           //DS18B20复位成功后的低电平时间会持续几百us时间,等待低电平消失
  {//以下小部分是附加功能,非驱动部分,功能是探头拔下或损坏报警
   temp++;if(temp>2000){GIE=1;disp_add=2;disp_menu();}   //goto loop;探头异常,显示Err,并有报警声
  }
//   loop: ;
   GIE=1;              //打开中断,不然数码管会闪烁
}
//=================================================================================================
//DS18B20写命令函数 向总线上写一字节
//=================================================================================================
void write_byte(uchar val)      //参数:向总线上定一个字节
{ uchar i;
GIE=0;                   //在DS18B20读出温度数据时最好关闭中断
TRISA2=0;asm("nop");asm("nop");   //IO脚设置为输出,并稳定一会儿时间
for(i=8;i>0;i--)          //一个字节8个bit位
{ DQ=1;asm("nop");asm("nop");    //
  DQ=0;asm("nop");asm("nop");    //
  asm("nop");asm("nop");asm("nop"); //
  DQ=val&0x01;           //
  delayll(6);             //等待6us
  val=val/2;            //
}                  //
DQ=1;delayll(1);           //
GIE=1;               //打开中断,不然数码管会闪烁  
}
//=================================================================================================
//DS18B20从总线上读一字节函数
//=================================================================================================
uchar read_byte(void)
{ uchar i,value=0;
GIE=0;                   //在DS18B20读出温度数据时最好关闭中断
for(i=8;i>0;i--)               //一个字节共8个bit位,全部要读完整
{ TRISA2=0; asm("nop");asm("nop");      //数据口置输出状态,稍微延时一会儿等待稳定下来
  DQ=1;asm("nop");asm("nop");         //数据口置高,稍微延时一会儿
  value>>=1;                  //
  DQ=0;                    //
  asm("nop");asm("nop");asm("nop");asm("nop");//
  DQ=1;                    //
  asm("nop");asm("nop");asm("nop");asm("nop");//
  TRISA2=1;asm("nop");asm("nop");       //
  if(DQ)value|=0x80;             //
  delayll(6);
}
DQ=1;GIE=1;
return(value);           //打开中断,不然数码管会闪烁
                   //
}
//=================================================================================================
//读出温度函数
//=================================================================================================
void read_temp(void)
{ uchar x;
  ow_reset();           //ds18b20复位程序
  write_byte(0xcc);        //发skip ROM命令
  write_byte(0xbe);        //发读命令
  readdata[0]=read_byte();    //温度低8位
  readdata[1]=read_byte();    //温度高8位
  ow_reset();
  write_byte(0xcc);        //发skip ROM命令
  write_byte(0x44);        //发转换命令
//温度数据处理----------------------------------------------------------------------
  sflag=0;
  if((readdata[1] & 0xf8)!=0x00)   //负数处理,取补码
   {
    sflag=1;
    readdata[1]=~readdata[1];
    readdata[0]=~readdata[0];
    result=readdata[0]+1;
    readdata[0]=result;
    if(result>255)
    {readdata[1]++;}
   }
   //整数处理--------------------------------------------------------------
  readdata[1]=readdata[1]<<4;     //左移去掉高位数据
  readdata[1]=readdata[1] & 0x70;   //去掉最高位和低位数据
  x=readdata[0];
  x=x>>4;               //右移4位去掉小数部分的数据
  x=x & 0x0f;             //去掉高位数据
  readdata[1]=readdata[1] | x;    //完整的整数部分数据
  result=readdata[1];         //数据赋值给缓存
  //小数处理-----------------------------------------------------------------
  x=readdata[0] & 0x0f;
  x=x<<1;
  //displaybuf[0]=(dotcode[x])%10;  //小数低位
  result1=(dotcode[x])/10;      //小数高位
}
//***************************************************************************************************
//       DS18B20读出的温度数据,滤波算法(DS18B20偶尔会读出错误数据)
//***************************************************************************************************
void wd_pj(void)
{  uchar i,temm;uchar wdaa[6];
  //------------------连续读出6次DS18B20温度数据---------------------------------------------
  for(i=0;i<6;i++)      
   {  read_temp();                                  //读出温度数据,数据在display[4]里
     wdaa[i]=result;                //依次临时存放6次读出的温度数据
     //delayy(1);                                   //间隔一会儿再读
   }
//-------------------冒泡排列,从大到小排列,去掉最高的和最小的,取中间的平均数------------------
for(i=6;i>0;i--)   
  { if(wdaa[0]<wdaa[1]){temm=wdaa[0];wdaa[0]=wdaa[1];wdaa[1]=temm;}
    if(wdaa[1]<wdaa[2]){temm=wdaa[1];wdaa[1]=wdaa[2];wdaa[2]=temm;}
    if(wdaa[2]<wdaa[3]){temm=wdaa[2];wdaa[2]=wdaa[3];wdaa[3]=temm;}
    if(wdaa[3]<wdaa[4]){temm=wdaa[3];wdaa[3]=wdaa[4];wdaa[4]=temm;}
    if(wdaa[4]<wdaa[5]){temm=wdaa[4];wdaa[4]=wdaa[5];wdaa[5]=temm;}
  }
  result=(wdaa[2]+wdaa[3])/2;                                        //                                
}
//=================================================================================================
//温度显示处理数据处理函数
//=================================================================================================
void disp_wd(void)
{  
  uchar x=3;
  //显示数据循环------------------------------------------------------------
  while(result/10)          //数据不为0 带高位消隐
  {
   displaybuf[x]=result%10;     //数据按位直到为0
   result=result/10;
   x++;
  }
  displaybuf[x]=result;        //数据为0
  //负号显示----------------------------------------------------------------
  if(sflag==1)            //在最高位前加负号
   {displaybuf[x+1]=17;}
  else{displaybuf[x+1]=16;}      //否则消隐      
  
// displaybuf[0]=2;
  displaybuf[1]=18;          //符号c
  displaybuf[2]=result1;       //小数位
}
//================================================================================================= 
//定时器中断扫描部分
//=================================================================================================  
void interrupt time0()
{
uchar displaycount,tmp;
  
  //动态扫描子程序------------------------------------------------------------
  tmp=PORTC&0X07;                //保留低3位数据不受影响,高5位才是扫描字
  led_dm=0x00;                 //清余辉
  led_smz=tmp|displaybit[displaycount];     //根据计数器取出扫描字点亮数码管
  tmp=displaybuf[displaycount];         //根据当前计数值,取显示缓冲待显示值
  if((displaycount==3)&&(xiaoshud==1))     //第3位显示小数点
   { tmp=displaycode[displaybuf[displaycount]]|0x80; }  //显示小数点
  else{ tmp=displaycode[displaybuf[displaycount]];}    //不显示小数点
  led_dm=0x00; PORTD=tmp;                 //清余辉,送自行码
  displaycount++; if(displaycount>4){displaycount=0;}   //计数值等于5就归0
  //---------------------------------------------------------------------------------
  TMR0=150;       //定时器0每中断一次重新置初值
}
}

相关帖子

沙发
帝国炮灰| | 2018-11-21 08:22 | 只看该作者
请问楼主解决了吗?我也在纠结这个问题

使用特权

评论回复
板凳
dirtwillfly| | 2018-11-21 08:39 | 只看该作者
ds18b20读取一次数据要多久?数码管扫描周期是多少,扫描一次用多久?
只要合理安排任务,没问题的。

使用特权

评论回复
地板
dirtwillfly| | 2018-11-21 08:39 | 只看该作者
帝国**灰 发表于 2018-11-21 08:22
请问楼主解决了吗?我也在纠结这个问题

ds18b20读取一次数据要多久?数码管扫描周期是多少,扫描一次用多久?
只要合理安排任务,没问题的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

150

帖子

1

粉丝