找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3122|回复: 7
收起左侧

单片机+DS18B20程序 数码管闪烁

[复制链接]
ID:709561 发表于 2020-8-22 21:10 | 显示全部楼层 |阅读模式
DS18B20温度显示程序,使用74hc595控制数码管位选【2个4位数码管】,数码管闪烁频率很高,闪烁是显示的也能看得见,不知是那一个环节出现了问题更改了好久无法解决,闪烁时就好像在不间断扫描一样???麻烦各位大佬指出。
由于拍摄无法看出数码管闪烁所以没有上传照片
#include<reg52.h>
#include<intrins.h>


#define uchar unsigned char
#define uint  unsigned int
        
sbit SER  = P1^2;    //数据输入
sbit SCK  = P1^0;    //串行移位时钟
sbit RCK  = P1^1;    //锁存器时钟
sbit DQ   = P2^2;    //18B20数据输入


uint tvalue;
uchar tflag;


uchar code tab[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
uchar data buf[5]={0,0,0,0,0xC6};//显示缓存


void hc595(uchar Data)//74HC595的数据串入并出子程序
{
        uchar i;            
        for(i=0;i<8;i++)        //由高位到低位发送一个字节
        {
                Data<<=1;                //左移一位,最高位溢出到位寄存器CY
                SER=CY;                        //从位寄存器的进位标志位CY读取
                SCK = 0;                         //串行移位
                                _nop_();
                        _nop_();
                SCK = 1;
                        _nop_();
                            _nop_();
                                SCK = 0;
        }
   RCK = 0;                 //锁存
   _nop_();
                _nop_();
   RCK = 1;
        _nop_();
                _nop_();
   RCK = 0;
}


void delay(unsigned int n)


{


unsigned int i,j;


for(j=n;j>0;j--)


for(i=112;i>0;i--);


}




void delay_18B20(uchar i)
{
        while(i--);
}


void ds1820()  //初始化
{
        uchar x=0;
        DQ = 1;
        delay_18B20(4);
        DQ = 0;
        delay_18B20(100);;
        DQ = 1;
        delay_18B20(40);;
}
uchar ds1820rd()  //读数据
{
        uchar i=0;
        uchar dat=0;
        for(i=8;i>0;i--)
        {
                DQ=0;
                dat>>=1;
                DQ=1;
                if(DQ)
                dat|=0x80;
                delay_18B20(10);;
        }
        return(dat);
}
void ds1820wr(uchar wdata)  //写数据
{
        uchar i=0;
        for(i=8;i>0;i--)
        {
                DQ=0;
                DQ=wdata&0x01;
                delay_18B20(10);;
                DQ=1;
                wdata>>=1;
        }
}


uint read_temp()
{
        uchar a,b;
        ds1820();
        ds1820wr(0xcc);  //跳过读序列号
        ds1820wr(0x44);  //启动温度转化
        ds1820();
        ds1820wr(0xcc);  //跳过读序列号
        ds1820wr(0xbe);  //启动温度转化
        a=ds1820rd();
        b=ds1820rd();
        tvalue=b;
        tvalue<<=8;
        tvalue=tvalue|a;
        if(tvalue<0x0fff)
                tflag=0;
        else
        {
                tvalue=~tvalue+1;
                tflag=1;
        }
        tvalue=tvalue*(0.625);  //温值扩大10倍精确到1位小数
        return(tvalue);
}
void ds1820disp()
{
        static uchar k=0;
        buf[0]=tab[tvalue/1000];  //百位数
        buf[1]=tab[tvalue%1000/100];  //十位数
        buf[2]=tab[tvalue%100/10]&0x7f;  //个位数
        buf[3]=tab[tvalue%10];  //小数
        P0=0xFF;
        hc595(0x01<<k);
        P0=buf[k];
        k++;
        k%=5;
        
}






void main()
{
        ds1820();
        while(1)
        {
                ds1820disp();
                read_temp();
               
        }
}


回复

使用道具 举报

ID:782419 发表于 2020-8-23 08:47 | 显示全部楼层
数码管显示一般在定时器中断程序执行定时刷新,同时要注意消隐。
回复

使用道具 举报

ID:213173 发表于 2020-8-23 11:59 | 显示全部楼层
造成数码管闪烁的原因是楼主的主程序循环周期时间太长,达到8.2ms,5个数码管扫描一轮需要41ms,远超20ms极限。由于操作18B20耗时6.3ms,占时过长,把read_temp()函数分3次完成,就可以使主循环周期平均约2.5ms,5个数码管扫描一轮小于20ms。完美解决数码管闪烁问题。
  1. #include<reg52.h>
  2. #include<intrins.h>

  3. #define uchar unsigned char
  4. #define uint  unsigned int
  5.         
  6. sbit SER  = P1^2;    //数据输入
  7. sbit SCK  = P1^0;    //串行移位时钟
  8. sbit RCK  = P1^1;    //锁存器时钟
  9. sbit DQ   = P2^2;    //18B20数据输入

  10. uint  Temp;
  11. uchar tflag;
  12. uchar code tab[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
  13. uchar data buf[5]={0,0,0,0,0xC6};//显示缓存


  14. void hc595(uchar Data)//74HC595的数据串入并出子程序
  15. {
  16.         uchar i;            
  17.         for(i=0;i<8;i++)        //由高位到低位发送一个字节
  18.         {
  19.                 Data<<=1;            //左移一位,最高位溢出到位寄存器CY
  20.                 SER=CY;              //从位寄存器的进位标志位CY读取
  21.                 SCK = 0;             //串行移位
  22.                 _nop_();
  23.                 _nop_();
  24.                 SCK = 1;
  25.                 _nop_();
  26.                 _nop_();
  27.                 SCK = 0;
  28.         }
  29.                 RCK = 0;              //锁存
  30.                 _nop_();
  31.                 _nop_();
  32.                 RCK = 1;
  33.                 _nop_();
  34.                 _nop_();
  35.                 RCK = 0;
  36. }
  37. /*
  38. void delay(unsigned int n)
  39. {
  40.         unsigned int i,j;
  41.         for(j=n;j>0;j--)
  42.                 for(i=112;i>0;i--);
  43. }
  44. */
  45. void delay_18B20(uchar i)
  46. {
  47.         while(i--);
  48. }

  49. void ds1820()  //初始化
  50. {
  51.         uchar x=0;
  52.         DQ = 1;
  53.         delay_18B20(4);
  54.         DQ = 0;
  55.         delay_18B20(100);
  56.         DQ = 1;
  57.         delay_18B20(40);
  58. }
  59. uchar ds1820rd()  //读数据
  60. {
  61.         uchar i=0;
  62.         uchar dat=0;
  63.         for(i=8;i>0;i--)
  64.         {
  65.                 DQ=0;
  66.                 dat>>=1;
  67.                 DQ=1;
  68.                 if(DQ)
  69.                 dat|=0x80;
  70.                 delay_18B20(10);
  71.         }
  72.         return(dat);
  73. }
  74. void ds1820wr(uchar wdata)  //写数据
  75. {
  76.         uchar i=0;
  77.         for(i=8;i>0;i--)
  78.         {
  79.                 DQ=0;
  80.                 DQ=wdata&0x01;
  81.                 delay_18B20(10);
  82.                 DQ=1;
  83.                 wdata>>=1;
  84.         }
  85. }

  86. void read_temp()
  87. {
  88.         static uchar c=0;
  89.         uint tvalue;
  90.         uchar a,b;
  91.         switch(c)
  92.         {
  93.                 case 0:
  94.                         ds1820();
  95.                         ds1820wr(0xcc);  //跳过读序列号
  96.                         ds1820wr(0x44);  //启动温度转化
  97.                         break;
  98.                 case 1:
  99.                         ds1820();
  100.                         ds1820wr(0xcc);  //跳过读序列号
  101.                         ds1820wr(0xbe);  //启动温度转化
  102.                         break;
  103.                 case 2:
  104.                         a=ds1820rd();
  105.                         b=ds1820rd();
  106.                         tvalue=b;
  107.                         tvalue<<=8;
  108.                         tvalue=tvalue|a;
  109.                         if(tvalue<0x0fff)
  110.                                 tflag=0;
  111.                         else
  112.                         {
  113.                                 tvalue=~tvalue+1;
  114.                                 tflag=1;
  115.                         }
  116.                         Temp=tvalue*(0.625);  //温值扩大10倍精确到1位小数
  117.                         break;
  118.         }
  119.         c++;
  120.         c%=3;
  121. }

  122. void ds1820disp()
  123. {
  124.         static uchar k=0;
  125.         switch(k)
  126.         {
  127.                 case 0:         if(tflag)buf[0]=0xbf;
  128.                                         else buf[0]=tab[Temp/1000]; break;//百位数
  129.                 case 1: buf[1]=tab[Temp%1000/100]; break;//十位数
  130.                 case 2: buf[2]=tab[Temp%100/10]&0x7f; break;//个位数
  131.                 case 3: buf[3]=tab[Temp%10]; break;//小数
  132.                 case 4: break;//"C"
  133.         }       
  134.         P0=0xff;
  135.         hc595(0x01<<k);
  136.         P0=buf[k];
  137.         k++;
  138.         k%=5;        
  139. }

  140. void main()
  141. {
  142.         ds1820();
  143.         while(1)
  144.         {
  145.                 read_temp();
  146.                 ds1820disp();
  147.         }
  148. }
复制代码

评分

参与人数 1黑币 +10 收起 理由
1P1P + 10 最具有说服力的解答 洞察羽翼

查看全部评分

回复

使用道具 举报

ID:72088 发表于 2020-8-23 12:32 | 显示全部楼层
读取18B20需要750ms,所以闪烁,即便你更改18B20到9位精度,读取时间也超过了人眼最低扫描频率
回复

使用道具 举报

ID:709561 发表于 2020-8-23 20:01 | 显示全部楼层
wulin 发表于 2020-8-23 11:59
造成数码管闪烁的原因是楼主的主程序循环周期时间太长,达到8.2ms,5个数码管扫描一轮需要41ms,远超20ms极 ...

多谢大佬的解答,这个超出20ms极限,确实没有想到一直以为是自己写程序那个环节的问题!!!
经过此次问题的解答,感觉自己还是不够严谨,以后要加强自己在软件与硬件间的微小变化!!
回复

使用道具 举报

ID:709561 发表于 2020-8-23 20:03 | 显示全部楼层
新乡家电维修 发表于 2020-8-23 12:32
读取18B20需要750ms,所以闪烁,即便你更改18B20到9位精度,读取时间也超过了人眼最低扫描频率

这个问题确实没有考虑到,多谢大佬的提示解答
回复

使用道具 举报

ID:65956 发表于 2020-8-28 09:26 | 显示全部楼层
开一个定时器专门给显示驱动用的,定时时间按你实际情况调试一下就OK了
回复

使用道具 举报

ID:693480 发表于 2022-5-2 02:16 | 显示全部楼层
aking991 发表于 2020-8-28 09:26
开一个定时器专门给显示驱动用的,定时时间按你实际情况调试一下就OK了

会不会在执行动态数码管扫描时影响ds18b20读取时序啊,一般我们操作这个温感都是关中断执行的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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