单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

LCD12864多功能测试仪仿真

  [复制链接]
跳转到指定楼层
楼主
本帖最后由 shuisheng 于 2019-1-14 01:14 编辑



#include <reg51.h>
#include <INTRINS.H>
#include <HZF.H>
#define        uchar unsigned char
#define uint  unsigned int
#define LCDoff           0x3e
#define LCDon           0x3f
#define pageadd         0xb8
#define lieadd             0x40
#define hangadd         0xc0
uint key_value;
uchar a=0,temp=0,b=0,number=0,pagenum=0;
char count_remain=0,count_c=0;
bit   flag=1;
char  temperature_buf[2]={0};
uchar temperature_display[8]={0};
double voltag=0;
double fr=0;

sbit RS=P2^0;
sbit RW=P2^1;
sbit EN=P2^2;
sbit cs1=P1^1;
sbit cs2=P1^0;
sbit cs=P1^7;
sbit sclk=P1^6;
sbit dout=P1^5;
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;
uchar data voldisp[8];
void delay(uint t);
void busy();
void wricmd(uchar cmd);
void wridat(uchar dat);
void LCD12864init();
void qiping();        
void L_disp(uchar page,  sl,  uchar code *tp);
void R_disp(uchar page, sl,  uchar code *tp);
void tpdisp(uchar page, sl,  uchar code *tp);
void cdispl(uchar ye,uchar lie,uchar tep);//16*16显示L
void cdispr(uchar ye,uchar lie,uchar tep);////16*16显示R
void edispl(uchar page,uchar lie,uchar tem);//字符L
void edispr(uchar page,uchar lie,uchar tem);//字符R
void qiping();// 清除所有显示RAM内容
void LCD_Busy();        //BUSY
void WRCommand_L(uchar command);         //写指令L
void WRCommand_R(uchar command);          //写指令R
void WRdata_L(uchar ucdata);         //写一个字节的显示数据L
void WRdata_R(uchar ucdata);
RDdata_L();//读显示数据l
RDdata_R();
void Init_LCD(void);
uint read_max1241() ;

bit I2C_clock(void)// I2C的时钟信号可发送和接收
{
        bit sample;
        I2C_SCL=1;
        sample=I2C_SDA;
        I2C_SCL=0;
        return(sample);
}

void I2C_ACK()  //应答
{
    I2C_SDA=0;
    I2C_clock();
    I2C_SDA=1;
}

void I2C_NACK() //非应答
{
    I2C_SDA=1;
    I2C_clock();
    I2C_SDA=1;
}

void I2C_start()//开始
{
    I2C_SDA=1;
    I2C_SCL=1;
    I2C_SDA=0;
    I2C_SCL=0;
}

void I2C_stop()        // 停止
{
    I2C_SDA=0;
    I2C_SCL=1;
    I2C_SDA=1;//产生停止控制信号,并且释放数据线
}

void I2C_init(void)//I2C初始化
{
    I2C_SDA=1;
    I2C_SCL=1;
    I2C_stop();
}

bit I2C_send(uchar I2C_data) //I2C总线写一个字节
{
    uchar a;
    for(a=0;a<8;a++)
        {
                I2C_SDA=(bit)(I2C_data&0x80);
                I2C_data=I2C_data<<1;
                I2C_clock();
        };
    I2C_SDA=1;
    return(I2C_clock()); //返回应答信号
}

uchar I2C_receive()// I2C总线读一个字节
{
        uchar a,receive_data;
        for(a=0;a<8;a++)
        {
                receive_data=receive_data<<1;
                if(I2C_clock())
                {
            receive_data++;
                };
        };
        return(receive_data);
}
DS1621_start()
{
        do
        {
                I2C_start();
        }
    while(I2C_send(0x90));//发送数据完地址字节的数据时,检测从机的应答位        
        if(I2C_send(0xee)==0)
        {
                I2C_stop();
                return 1;
           }
    else
                return 0;                                
}
DS1621_stop()
{
    do
        {
                I2C_start();
        }
        while(I2C_send(0x90));
        if(I2C_send(0x22)==0)
        {
                I2C_stop();
                return 1;
        }
        else
                return 0;            
}

char read_count_remain()
{
           char temp_remain=0;
           do
           {
                   I2C_start();
           }
           while(I2C_send(0x90));//是否应答
           if(I2C_send(0xa8)==0)
           {
                   I2C_start();
                   if(I2C_send(0x91)==0)
                   {
                           temp_remain=I2C_receive();
                           I2C_NACK();
                           I2C_stop();
                           return temp_remain;
                   }
                   else
                           return 0;
              }
           else
                   return 0;
}
char read_count_c()
{
           char temp_c=0;
           do
           {
                   I2C_start();
           }
           while(I2C_send(0x90));//是否应答
           if(I2C_send(0xa9)==0)
           {
                   I2C_start();
                   if(I2C_send(0x91)==0)
                   {
                           temp_c=I2C_receive();
                           I2C_NACK();
                           I2C_stop();
                           return temp_c;
                   }
                   else
                           return 0;
              }
           else
                   return 0;
}

bit read_temperature(char *point1)
{
        do
        {
                I2C_start();
        }
        while(I2C_send(0x90));
    if(I2C_send(0xaa)==0)
        {
                do{
                        I2C_start();
                }
                while(I2C_send(0x91));
                (*point1)=I2C_receive();
                I2C_ACK();
                (*(point1+1))=I2C_receive();
                I2C_NACK();
                I2C_stop();
                return 1;
           }
        else
                return 0;
}

void main()
{
        LCD12864init();
        qiping();
        tpdisp(0, 0, tupian1);
        delay(500);
        tpdisp(0, 0, tupian2);
        delay(500);
        qiping();
        while(1)
        {
                while(read_temperature(temperature_buf)==0);//读温度值(两字节有符数),并检测应答位,只使用第一字节
                count_remain=read_count_remain();//读斜率
                count_c=read_count_c();//读计数器
                fr = temperature_buf[0] -0.75 + (count_c-count_remain) / (double)count_c;
                DS1621_start();//读完数据后,重新开始一次温度转化
               
                temperature_display[0]=19;
                if(fr<0)
                {
                        temperature_display[1]=16;//显示负号
                        temperature_display[2]=(-fr)/10;//十位
                        temperature_display[3]=((uchar)(-fr))%10;
                        temperature_display[4]=17;//小数点
                        temperature_display[5]=(int)((-fr)*10)%10;
                        temperature_display[6]=(int)((-fr)*100)%10;//小数点后两位
                }
                else
                {
                        temperature_display[1]=fr/100;//百位
                        temperature_display[2]=((uchar)fr)/10%10;
                        temperature_display[3]=((uchar)fr)%10;
                        temperature_display[4]=17;
                        temperature_display[5]=((int)(fr*10))%10;
                        temperature_display[6]=((int)(fr*100))%10;//小数点后两位
                }
                //LCD显示第二部分
                for(b=0;b<40;b++)
               {
                        //更新max1241显示值                    
                        voltag=(double)read_max1241();
                        voltag=5000*voltag/4095;
                        voldisp[0]=19;
                        voldisp[5]=(uint)voltag %10;//个位
                        voldisp[2]=17;
                        voldisp[4]=(uint)(voltag/10)%10;//小数点后1位
                        voldisp[3]=(uchar)(voltag/100)%10;//小数点后2位
                        voldisp[1]=(uchar)(voltag/1000)%10;//小数点后3位
                        
                        //显示文字:电压测量               
                        pagenum=2;
                        for(a=0;a<2;a++)
                                cdispl(pagenum,a*16,a+8);
                        for(a=0;a<2;a++)
                                cdispl(pagenum,(a+2)*16,a+12);        
                        //显示文字:温度测量
                        pagenum=5;
                        for(a=0;a<2;a++)
                                cdispl(pagenum,a*16,a+10);
                        for(a=0;a<2;a++)
                                cdispl(pagenum,(a+2)*16,a+12);
                        
                        //显示1241采样值
                        pagenum=3;
                        for(a=0;a<6;a++)
                        {
                                edispr(pagenum,a*8,voldisp[a]);
                        }
                        
                        //显示ds1621采样值
                        pagenum=6;
                        for(a=0;a<7;a++)
                        {
                                edispr(pagenum,a*8,temperature_display[a]);
                        }
                };
               
        }
}

void LCD_Busy()        
{
        uchar busy;
        EN=0;
        RS=0;
        RW=1;
        while(1)
        {
                EN=1;
                _nop_();
                _nop_();
                busy=P0;
                _nop_();
                EN=0;
                if((busy&0x90)==0)
                        break;
        };
}  

void WRCommand_L(uchar command)         //写指令L
{
        cs1=1;
        cs2=0;
        LCD_Busy();
        RS=0;
        _nop_();
        RW=0;
        _nop_();
        EN=1;
        _nop_();
        P0=command;
        _nop_();
        EN=0;
        _nop_();
}

void WRCommand_R(uchar command)        //写指令R
{
        cs1=0;
        cs2=1;
        LCD_Busy();
        RS=0;
        _nop_();
        RW=0;
        _nop_();
        EN=1;
        _nop_();
        P0=command;
        _nop_();
        EN=0;
        _nop_();
}

void WRdata_L(uchar ucdata)//写一个字节的显示数据L
{
        cs1=1;
        cs2=0;
        LCD_Busy();
        RS=1;
        _nop_();
        RW=0;
        _nop_();
        EN=1;
        _nop_();
        P0=ucdata;
        _nop_();
        EN=0;
        _nop_();
}

void WRdata_R(uchar ucdata)
{
        cs1=0;
        cs2=1;
        LCD_Busy();  
        RS=1;
        _nop_();
        RW=0;
        _nop_();
        EN=1;
        _nop_();
        P0=ucdata;
        _nop_();
        EN=0;
        _nop_();
}

RDdata_L()//读显示数据l
{
        uchar receiver;
        cs1=1;
        cs2=0;
        LCD_Busy();
        RS=1;
        _nop_();
        WR=1;
        _nop_();
        EN=1;
        _nop_();
        receiver=P0;
        EN=0;
        return(receiver);
}

RDdata_R()
{
        uchar receiver;
        cs1=0;
        cs2=1;
        LCD_Busy();
        RS=1;
        _nop_();
        WR=1;
        _nop_();
        EN=1;
        _nop_();
        receiver=P0;
        EN=0;
        return(receiver);
}

void cdispl(uchar ye,uchar lie,uchar tep)//16*16显示L
{
        uchar k;
        ye=pageadd|ye;
        lie=lieadd|lie;
        WRCommand_L(ye);
        WRCommand_L(lie);
        for(k=0;k<16;k++)
        {
                WRdata_L(table2[tep*32+k]);
        };
        ye=ye+1;
        WRCommand_L(ye);
        WRCommand_L(lie);
        for(k=0;k<16;k++)
        {
                WRdata_L(table2[tep*32+k+16]);
           };
}

void cdispr(uchar ye,uchar lie,uchar tep)////16*16显示R
{
        uchar k;
        ye=pageadd|ye;
        lie=lieadd|lie;
        WRCommand_R(ye);
        WRCommand_R(lie);
        for(k=0;k<16;k++)
        {
                WRdata_R(table2[tep*32+k]);
        };
        ye=ye+1;
        WRCommand_R(ye);
        WRCommand_R(lie);
        for(k=0;k<16;k++)
        {
                WRdata_R(table2[tep*32+k+16]);
        };
}


void edispl(uchar page,uchar lie,uchar tem)//字符L
{
        uchar k;
        WRCommand_L(pageadd|page);
        WRCommand_L(lieadd|lie);
        for(k=0;k<8;k++)
        {
                WRdata_L(table1[tem*8+k]);
           };
}   
void edispr(uchar page,uchar lie,uchar tem)//字符R
{
        uchar k;
        WRCommand_R(pageadd|page);
        WRCommand_R(lieadd|lie);
        for(k=0;k<8;k++)
        {
                WRdata_R(table1[tem*8+k]);
           };
}

uint read_max1241()    // max1241读转换结果
{
        uint voltagtemp=0;
        uchar ucloop=12;
        cs=1;
        
        sclk=0;
        cs=0;
        while(dout==0);   //EOC信号为高表示转换结束
        sclk=1;
        sclk=0;
        while(ucloop--)
           {
                sclk=1;//上升沿数据稳定并读出
                voltagtemp<<=1;
                if(dout==1)
                        voltagtemp+=1;
                sclk=0;
        };         
        cs=1;
        return voltagtemp;
}

//-----------LCD12864--------------------------------------
void delay(uint t)
{
        uint i,j;
        for(i=0;i<t;i++);
        for(j=0;j<40000;j++);
}

void busy()//LCD是否忙               
{
        uchar dat,buysbit;//状态信息(判断是否忙)
        RS=0;
        RW=1;
        do
        {
                buysbit=0x00;
                EN=1;
                dat=buysbit;
                EN=0;
                dat=0x80 & dat; //仅当第7位为0时才可操作(判别busy信号)
    }
    while(!(dat==0x00));
}

void wricmd(uchar cmd)//写命令
{
    busy();//检测LCD是否忙
        RS=0;
        RW=0;
        P0=cmd;               
        EN=1;
        EN=0;
}




void L_disp(uchar page, sl,  uchar code *tp) //右屏位置显示
{
        uchar j=0,i=0;
        for(j=0;j<8;j++)
        {
                wricmd(pageadd+page+j);
                wricmd(lieadd+sl);
                for(i=64;i<128;i++)
                        wridat(tp[128*j+i]);
        }
}

void tpdisp(uchar page, sl,  uchar code *tp)
{
    cs1=0; //左屏开显示
        cs2=1;
    L_disp(page,sl,tp);
    cs1=1; //右屏开显示
        cs2=0;
        R_disp(page,sl,tp);
}


lcd12864多功能测试仪.rar (150.22 KB, 下载次数: 13)   仿真时,大家请用Proteus 8.6及以上版本,后继的案例都会用Proteus 8.6来做


评分

参与人数 7黑币 +135 收起 理由
yoxi + 10
shuisheng60 + 35
areyouok + 12 赞一个!
刀刀见红 + 10 很给力!
#include51.h + 10 很给力!
Sawardeakar + 8 共享资料的黑币奖励!
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
shuisheng60 发表于 2019-2-4 19:03 | 只看该作者
不错不错!谢谢了!

评分

参与人数 2黑币 +31 收起 理由
jinsheng7533967 + 16
#include51.h + 15

查看全部评分

回复

使用道具 举报

板凳
还有谁? 发表于 2019-2-9 16:02 | 只看该作者
很强大,学习了

评分

参与人数 3黑币 +65 收起 理由
站着说话不腰疼 + 15
找人PK + 15
shuisheng60 + 35

查看全部评分

回复

使用道具 举报

地板
王秋冬 发表于 2019-2-9 18:44 | 只看该作者
谢谢,留个记号学习。
回复

使用道具 举报

5#
还有谁? 发表于 2019-2-10 20:59 | 只看该作者
学习了 ,牛人!

评分

参与人数 2黑币 +26 收起 理由
jinsheng7533967 + 16
就你?呸! + 10

查看全部评分

回复

使用道具 举报

6#
就你?呸! 发表于 2019-2-11 13:32 | 只看该作者
正在做这方面,好资料
回复

使用道具 举报

7#
春风十里吹死你 发表于 2019-2-19 19:16 | 只看该作者
学习了!谢谢!

评分

参与人数 2黑币 +26 收起 理由
Sawardeakar + 10
#include51.h + 16

查看全部评分

回复

使用道具 举报

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

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛单片机.

Powered by 单片机教程网

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