找回密码
 立即注册

QQ登录

只需一步,快速开始

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

程序导入单片机以后,1602显示一排黑色格子。

[复制链接]
跳转到指定楼层
楼主
#include<reg52.h>                 //调用单片机头文件
#define uchar unsigned char  //无符号字符型宏定义        变量范围0~255
#define uint unsigned int         //无符号整型宏定义        变量范围0~65535
#include<intrins.h>
bit flag_300ms ;
uchar menu_1;           //菜单设计的变量
sbit beep = P3^7;   //蜂鸣器IO口定义
uchar flag_200ms ;
sbit dq   = P3^3;        //18b20IO口的定义
uint temperature ;  //
uchar code table_num[]="0123456789abcdefg";
sbit rs=P1^0;         //寄存器选择信号H:数据寄存器        L:指令寄存器
sbit rw=P1^1;         //寄存器选择信号H:数据寄存器        L:指令寄存器
sbit e =P1^2;         //片选信号下降沿触发
unsigned char i=0,timecount=0,displayOK=0,rate=0,aa=0;
unsigned int time[6]={0};
uchar rate_l=50,rate_h=120;   //心跳报警值
/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
        int i,j;
        for(i=0;i<q;i++)
                for(j=0;j<110;j++);
}
/********************************************************************
* 名称 : delay_uint()
* 功能 : 小延时。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay_uint(uint q)
{
        while(q--);
}
/********************************************************************
* 名称 : write_com(ucharcom)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
        e=0;
        rs=0;
        rw=0;
        P0=com;
        delay_uint(25);
        e=1;
        delay_uint(100);
        e=0;
}
/********************************************************************
* 名称 : write_data(uchardat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
        e=0;
        rs=1;
        rw=1;
        P0=dat;
        delay_uint(25);
        e=1;
        delay_uint(100);
        e=0;       
}
/********************************************************************
* 名称 : write_string(ucharhang,ucharadd,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"abcdef" ,调用该函数如下
                write_string(1,5,"abcdef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang, uchar add , uchar *p )
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        while(1)
        {
                if(*p == '\0')  break;
                write_data(*p);
                p++;
        }       
}
/*****************控制光标函数********************/
void write_guanbiao(uchar hang,uchar add,uchar date)
{               
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        if(date == 1)
                write_com(0x0f);     //显示光标并且闪烁       
        else
                write_com(0x0c);   //关闭光标
}       


/***********************lcd1602上显示两位十进制数************************/
void write_sfm3(uchar hang,uchar add,uint date)
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(0x30+date/100%10);
        write_data(0x30+date/10%10);
        write_data(0x30+date%10);       
}
/***********************lcd1602初始化设置************************/
void init_1602()
{
        write_com(0x38);        //
        write_com(0x0e);
        write_com(0x06);
        write_com(0x01);
        write_com(0x80+0x00);
        delay_uint(1000);
        write_string(1,0," 000/min00.00   ");       
        write_string(2,0,"  H:000L:000  ");
}

/*************定时器0初始化程序***************/
void time_init()       
{
        EA   = 1;                  //开总中断
        TMOD = 0X01;          //定时器0、定时器1工作方式1
        ET0  = 1;                  //开定时器0中断
        TR0  = 1;                  //允许定时器0定时
}
/***********************lcd1602上显示两位十进制数************************/
void write_sfm3_18B20(uchar hang,uchar add,uint date)
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(0x30+date/100%10);
        write_data(0x30+date/10%10);
        write_data('.');
        write_data(0x30+date%10);       
}
/***********外部中断0初始化程序****************/
void init_int0()          //外部中断0初始化程序
{
        EX0=1;                          //允许外部中断0中断
        EA=1;                          //开总中断
        IT0 = 1;                   //外部中断0负跳变中断
}

/********************独立按键程序*****************/
uchar key_can;         //按键值
void key()         //独立按键程序
{
        static uchar key_new;

        key_can = 20;                   //按键值还原
        P3 |= 0x78;                     //对应的按键IO口输出为1
        if((P3 & 0x78) != 0x78)                //按键按下
        {
                delay_1ms(1);                //按键消抖动
                if(((P3 & 0x78) != 0x78) && (key_new == 1))
                {                                                //确认是按键按下
                        key_new = 0;
                        switch(P3 & 0x78)
                        {
                                case 0x68:  key_can = 3;  break;         //得到按键值
                                case 0x58:  key_can = 2;  break;         //得到按键值
                                case 0x38:  key_can = 1;  break;         //得到按键值
                        }
                }                       
        }
        else
                key_new = 1;       
}

/**********************设置函数************************/
void key_with()
{
        if(key_can == 1)        //设置键
        {
                menu_1++;
                if(menu_1 > 2)    //回到正常显示
                {
                        menu_1 = 0;
                        write_guanbiao(1,2,0);         //关闭光标
                        init_1602();      //初始化液晶显示               
                }
        }
/***************设置*********************/
        if(menu_1 != 0)
        {
                if(menu_1 == 1)                  //设置上限报警
                {
                        if(key_can == 2)        //加
                        {
                            rate_h ++;
                                if(rate_h>= 255)
                                        rate_h = 0;
                        }               
                        if(key_can == 3)        //减       
                        {
                                rate_h -- ;
                                if(rate_h<= rate_l)
                                        rate_h = rate_l + 1;
                        }       
                }
                if(menu_1 == 2)                  //设置下限报警
                {
                        if(key_can == 2)        //加
                        {
                            rate_l ++;
                                if(rate_l>= rate_h)
                                        rate_l = rate_h - 1;
                        }       
                        if(key_can == 3)        //减       
                        {
                                if(rate_l == 0x00)
                                        rate_l = 1;
                                rate_l -- ;                       
                        }
                }
                write_sfm3(2,4,rate_h);           //
                write_sfm3(2,11,rate_l);           //
                switch(menu_1)           // 光标显示
                {
                        case 1:  write_guanbiao(2,4,1);  break;
                        case 2:  write_guanbiao(2,11,1);  break;
                }       
        }
}

/****************报警函数***************/
void clock_h_l()
{
        static uchar value;
        if(rate != 0)
        {
                if((rate<= rate_l) || (rate>= rate_h))
                {
                        value ++;  //消除实际距离在设定距离左右变化时的干扰
                        if(value>= 2)
                        {
                                beep = ~beep;           //蜂鸣器报警                       
                        }       
                }
                else
                {
                        beep = 1;        //取消报警
                }
        }else
        {
                beep = 1;   //取消报警       
        }
                       
}
/***********************18b20初始化函数*****************************/
void init_18b20()
{
        bit q;
        dq = 1;                                //把总线拿高
        delay_uint(1);            //15us
        dq = 0;                                //给复位脉冲
        delay_uint(80);                //750us
        dq = 1;                                //把总线拿高等待
        delay_uint(10);                //110us
        q = dq;                                //读取18b20初始化信号
        delay_uint(20);                //200us
        dq = 1;                                //把总线拿高释放总线
}
/*************写18b20内的数据***************/
void write_18b20(uchar dat)
{
        uchar i;
        for(i=0;i<8;i++)
        {                                         //写数据是低位开始
                dq = 0;                         //把总线拿低写时间隙开始
                dq = dat&0x01; //向18b20总线写数据了
                delay_uint(5);         // 60us
                dq = 1;                         //释放总线
                dat >>= 1;
        }       
}
/*************读取18b20内的数据***************/
uchar read_18b20()
{
        uchar i,value;
        for(i=0;i<8;i++)
        {
                dq = 0;                         //把总线拿低读时间隙开始
                value>>= 1;         //读数据是低位开始
                dq = 1;                         //释放总线
                if(dq == 1)                 //开始读写数据
                        value |= 0x80;
                delay_uint(5);         //60us        读一个时间隙最少要保持60us的时间
        }
        return value;                 //返回数据
}

/*************读取温度的值读出来的是小数***************/
uint read_temp()
{
        uint value;
        uchar low;                           //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
        init_18b20();                   //初始化18b20
        write_18b20(0xcc);           //跳过64位ROM
        write_18b20(0x44);           //启动一次温度转换命令
        delay_uint(50);                   //500us
        init_18b20();                   //初始化18b20
        EA = 0;
        write_18b20(0xcc);           //跳过64位ROM
        write_18b20(0xbe);           //发出读取暂存器命令
        EA = 1;
        low = read_18b20();           //读温度低字节
        value = read_18b20();  //读温度高字节
        value<<= 8;                   //把温度的高位左移8位
        value |= low;                   //把读出的温度低位放到value的低八位中
        value *= 0.625;               //转换到温度值小数
        return value;                   //返回读出的温度带小数
}
/****************主函数***************/
void main()
{       
        init_1602();                    //1602初始化
        time_init();                    //初始化定时器
        init_int0();          //外部中断0初始化程序
        while(1)
        {                       
                key();                                         //按键函数
                if(key_can<10)
                {
                        key_with();                         //按键处理函数
                }
                if(displayOK==0)//如果显示关
                {
                        rate = 0;
                }
                else//如果显示开
                {
        rate=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
                }
                write_sfm3(2,5,rate);
                flag_200ms ++;
                if(flag_200ms>= 200)        //200ms
                {
                        flag_200ms = 0;
                        write_sfm3(1,5,rate);
                        clock_h_l();    //报警函数
                        temperature = read_temp();        //先读出温度的值
                        write_sfm3_18B20(1,10,temperature);
                }
                delay_1ms(1);
        }
}

void int0() interrupt 0
{
        if(timecount<6)   //
        {
                        TR0=1;//开定时器
        }
        else
        {
                time[i]=timecount*50+TH0+TL0;//
                timecount=0;//100ms
                i++;
                if(i==6)//记
                {
                        i=1;//
                        displayOK=1;    //
                }                                                               
        }
}
/*************定时器1中断服务程序***************/
void time0_int() interrupt 1
{       
        TH0 = 0x3c;
        TL0 = 0xb0;     //
        timecount++;//
        if(timecount>6)     //
        {
                        i=0;//
                        timecount=0;//计数清零
                        displayOK=0;//显示关
                        TR0=0;//定时器关
        }
}

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

使用道具 举报

沙发
ID:25310 发表于 2019-11-14 05:55 | 只看该作者
检查硬件连接,上图看看。一般问题都出之细节。
回复

使用道具 举报

板凳
ID:635528 发表于 2019-11-14 19:05 | 只看该作者
pcbboy 发表于 2019-11-14 05:55
检查硬件连接,上图看看。一般问题都出之细节。

今天重新下载了以下程序之后,不显示黑色格子了。但是就变成了一片白

IMG_20191114_185619.jpg (5.03 MB, 下载次数: 11)

IMG_20191114_185619.jpg
回复

使用道具 举报

地板
ID:524818 发表于 2019-11-15 08:45 | 只看该作者
这个程序是自己对照硬件接线顺序自己写的吗?看看程序中指定的I/O口和硬件连接相符吗?如果对就调调对比度电位器试试
回复

使用道具 举报

5#
ID:635528 发表于 2019-11-17 13:55 | 只看该作者
cphnkj188 发表于 2019-11-15 08:45
这个程序是自己对照硬件接线顺序自己写的吗?看看程序中指定的I/O口和硬件连接相符吗?如果对就调调对比度 ...

是的 现在还没有连温度监测 和红外线检测的硬件 就是单单连接了1602. 1602的rs rw e 分别是2.7、2.6、2.5
下完程序之后是两行黑色格子
回复

使用道具 举报

6#
ID:93224 发表于 2019-11-17 15:45 | 只看该作者
调节下电位器,调整亮度,然后检查下程序和电路
回复

使用道具 举报

7#
ID:213173 发表于 2019-11-17 21:39 | 只看该作者
/********************************************************************
* 名称 : write_data(uchardat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
        e=0;
        rs=1;
        rw=1;//这里错........rw=0;
        P0=dat;
        delay_uint(25);
        e=1;
        delay_uint(100);
        e=0;        
}
回复

使用道具 举报

8#
ID:635528 发表于 2019-11-20 18:46 | 只看该作者
wulin 发表于 2019-11-17 21:39
/********************************************************************
* 名称 : write_data(uchardat) ...

显示了 谢谢大家的帮助
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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