找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3735|回复: 1
打印 上一主题 下一主题
收起左侧

pic单片机数码管显示实时温度问题

[复制链接]
跳转到指定楼层
楼主
ID:187532 发表于 2017-9-28 21:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
3黑币
代码如下:
#include <pic.h>           //调用PIC16F87XA单片机的头文件


__CONFIG(HS&WDTDIS&LVPDIS);
unsigned char temp1;
unsigned char temp2;
unsigned char buf,buf1,buf2;
//转换后的温度值小数点部分查表
const unsigned char table[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};
//---------------------------------------
//数码管字形表,供显示时查询
const unsigned char LED[11]=
{                          //定义表格一定要使用const,这样会做到程序存储区中
    0B00111111,            //"0"的字形表,0x3F
    0B00000110,            //"1"的字形表,0x06
    0B01011011,            //"2"的字形表,0x5B
    0B01001111,            //"3"的字形表,0x4F
    0B01100110,            //"4"的字形表,0x66
    0B01101101,            //"5"的字形表,0x6D
    0B01111101,            //"6"的字形表,0x7D
    0B00000111,            //"7"的字形表,0x07
    0B01111111,            //"8"的字形表,0x7F
    0B01101111,            //"9"的字形表,0x6F
  0B10000000,                //.
   
};

//---------------------------------------
//4位数码管相关I/O设置
#define U5A  RB0           //4位数码管单元的U5(74HC138)的A脚接在RB0口上
#define U5B  RB1           //4位数码管单元的U5(74HC138)的B脚接在RB1口上
#define U5C  RB2           //4位数码管单元的U5(74HC138)的C脚接在RB2口上

//名称:复位DS18B20函数

unsigned char Reset(void)
{
        unsigned int i;   
        unsigned char k;       
        TRISA4=0;                                //设置RA4位输出口
        RA4=0;                                     //拉低DQ总线开始复位       
           i=67;                                     //保持DQ低大约870uS,符合不低于480US的要求
           while(i>0)                             //保持DQ低大约870uS,符合不低于480US的要求
       i--;                               //保持DQ低大约870uS,符合不低于480US的要求       
    TRISA4=1;               //设置RA4为输入口,以释放总线等电阻拉高总线
    i=6;                                    //大约78uS后,判断是否复位成功
           while(i>0)                            //大约78uS后,判断是否复位成功
       i--;                              //大约78uS后,判断是否复位成功
        if(RA4==0)                             //读出数据并保存
                   k=0;     
        else
                k=1;
           i=31;                                            //维持约400US,符合总读时隙不低于480US的要求
           while(i>0)                            //维持约400US,符合总读时隙不低于480US的要求
       i--;                              //维持约400US,符合总读时隙不低于480US的要求
           return k;               //k=0为复位成功,k=1为复位失败
}


//名称:写字节函数

void WriteByte(unsigned char dat)
{
        unsigned int i;
           unsigned char j;
           for(j=0;j<8;j++)
           {            
                if(dat&0x01)                        //如果写1
              {      
                        TRISA4=0;                        //设置RA4位输出口
                           RA4=0;                                 //拉低      
                 NOP();                       //维持6US,符合大于1US小于15US的规范
                 NOP();                       //维持6US,符合大于1US小于15US的规范   
                        NOP();                       //维持6US,符合大于1US小于15US的规范
                 NOP();                       //维持6US,符合大于1US小于15US的规范
                        NOP();                       //维持6US,符合大于1US小于15US的规范
                 NOP();                       //维持6US,符合大于1US小于15US的规范      
                 TRISA4=1;           //设置RA4为输入口,以释放总线等电阻拉高总线        
                 i=5;                                  //维持约63US,符合不低于60US的要求
                 while(i>0)                  //维持约63US,符合不低于60US的要求
                         i--;                     //维持约63US,符合不低于60US的要求
                }
              else                                        //如果写0
              {         
                        TRISA4=0;                        //设置RA4位输出口   
                        RA4=0;                                 //拉低                 
                 i=5;                                //维持约63US,符合不低于60US的要求
                 while(i>0)                        //维持约63US,符合不低于60US的要求
                         i--;                    //维持约63US,符合不低于60US的要求        
                 TRISA4=1;           //设置RA4为输入口,以释放总线等电阻拉高总线                
                 NOP();                       //维持2US,符合大于1US的规范
                 NOP();                       //维持2US,符合大于1US的规范                   
              }
                dat=dat>>1;                                //写入字节右移1位
        }
}

//名称:读字节函数

unsigned char ReadByte(void)
{
        unsigned int i;
           unsigned char j,buf=0;
           for(j=1;j<=8;j++)                        //接收8次还原一个字节数据
           {
                buf=buf>>1;                          //接收前,先将接收缓冲区右移
                TRISA4=0;                                //设置RA4位输出口   
                RA4=0;                                         //拉低      
              NOP();                               //维持2US,符合大于1US小于15US的规范
        NOP();                               //维持2US,符合大于1US小于15US的规范       
              TRISA4=1;               //设置RA4为输入口,以释放总线等电阻拉高总线 准备读               
                NOP();                               //维持6US,符合大于1US小于15US的规范
        NOP();                               //维持6US,符合大于1US小于15US的规范
                NOP();                               //维持6US,符合大于1US小于15US的规范
        NOP();                               //维持6US,符合大于1US小于15US的规范
                NOP();                               //维持6US,符合大于1US小于15US的规范
        NOP();                               //维持6US,符合大于1US小于15US的规范               
                if(RA4==1) buf|=0x80;          //读出1位数据保存于buf中最高位
                i=4;                                          //维持约52US,符合总读时隙不低于60US的要求
              while(i>0)                          //维持约52US,符合总读时隙不低于60US的要求
                      i--;                             //维持约52US,符合总读时隙不低于60US的要求
        }
           return buf;                     //退出的同时将接收缓冲区参数返回       
}


//名称:启动读温度函数

unsigned char Convert(void)
{
        unsigned int i;
    if(Reset()==0)                    //如果复位成功
        {  
                i=77;                                         //延时约1000US
              while(i>0)                                 //延时约1000US
                      i--;                            //延时约1000US
        WriteByte(0xcc);             // 跳过多器件识别
        WriteByte(0x44);             // 启动温度转换
                return 1;
    }
        else
        {
                return 0;
        }
}


//名称:读温度函数

void ReadFlash(void)
{
        unsigned int i;
    unsigned char Lsb,Msb;            
    if(Reset()==0)
        {  
                i=77;                                         //延时约1000US
              while(i>0)                                 //延时约1000US
                      i--;                            //延时约1000US
        WriteByte(0xcc);              // 跳过多器件识别
        WriteByte(0xbe);              // 读暂存器
        Lsb=ReadByte();               // 低字节
        Msb=ReadByte();                     // 高字节
                temp2=Lsb&0x0f;                //LSB的低4位为小数部分
                temp1=(Lsb>>4)|(Msb<<4);//LSB的高4位和MSB拼成整数部分
    }   
        else
        {
                temp1=0;
                temp2=0;
        }
}
void tempture()
{
        if(Convert()==1)                                 //启动转换
                {                            
                    ReadFlash();                       //读取温度                           
                if(temp1>99) temp1=99;                         
                         if(temp2>15) temp2=0;         
                        buf=temp1/10;                                                 
                        buf1=temp1%10;       
                        buf2=table[temp2&0x0f];
       
               
                                       
                }
}
//---------------------------------------
//名称: 主函数

//---------------------------------------
void main(void)            //主函数,单片机开机后就是从这个函数开始运行
{

    unsigned int c=0;     //定义一个char型变量,做延时用
    unsigned char d=0;     //定义一个char型变量,控制显示位置

    TRISB=0B11111000;      //初始化RB7-RB0的输入输出方向
    TRISD=0B00000000;      //初始化RD7-RD0的输入输出方向
    PORTB=0B00000000;      //初始化RB7-RB0的数值
    PORTD=0B00000000;      //初始化RD7-RD0的数值

    while(1)               //死循环,单片机初始化后,将一直运行这个死循环
    {
               
                    tempture();
                        for(c=0;c<20;c++);//做一个0-250的循环,不执行其他操作,只为延时
                PORTD=0;           //关一次显示,以免显示出鬼影
                if(++d>3) d=0;     //先将d加1,然后判断是否大于3,大于3归零
                if(d==0)           //如果d=0,显示千位
                {
                    U5A=0;         //U5A=0,U5B=0,U5C=0,选通数码管的千位进行显示
                    U5B=0;         //U5A=0,U5B=0,U5C=0,选通数码管的千位进行显示
                    U5C=0;         //U5A=0,U5B=0,U5C=0,选通数码管的千位进行显示
                    PORTD=LED[buf];          //温度整数部分十位
                }
                else if(d==1)      //如果d=1,显示百位
                {
                    U5A=1;         //U5A=1,U5B=0,U5C=0,选通数码管的百位进行显示
                    U5B=0;         //U5A=1,U5B=0,U5C=0,选通数码管的百位进行显示
                    U5C=0;         //U5A=1,U5B=0,U5C=0,选通数码管的百位进行显示       
                    PORTD=LED[buf1];  //温度整数部分个位
                }
                else if(d==2)      //如果d=2,显示十位
                {
                    U5A=0;         //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
                    U5B=1;         //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
                    U5C=0;         //U5A=0,U5B=1,U5C=0,选通数码管的十位进行显示
                    PORTD=LED[10];  //十位显示"2"
                }
                else if(d==3)      //如果d=3,显示个位
                {
                    U5A=1;         //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
                    U5B=1;         //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
                    U5C=0;         //U5A=1,U5B=1,U5C=0,选通数码管的个位进行显示
                    PORTD=LED[buf2];  //温度小数部分
                }
            }
       
}

   我用四位数码管显示实时温度,显示的现象有微小闪烁,跪求大神们如何解决,帮忙改一下代码。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:123289 发表于 2017-9-28 23:53 | 只看该作者
1、建议每4ms切换一个LED显示,或更短时间。【视觉残留】
2、切换时先关全体,然后送“数字”,再开需要显示的LED。【交差干扰】
3、“关全体”之前,必须先将“数字”准备好,不可在“关全体后,才始处理“数字”。【显示效率】
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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