微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 求助大神啊LCD1602显示乱码怎么回事啊

求助大神啊LCD1602显示乱码怎么回事啊

时间:10-02 整理:3721RD 点击:

//设置P0作为输出连接LCD1602的数据端D0-D7,P2.3为SCLK,P2.4为SDA,P2.5为RST(都配置为输出)

//P2.0为rs,P2.1为rw,P2.2为e(都配置为输出)

//P2.67配置为输入,下降沿中断,中断处理函数 void key_pro(),P2。6接key1(控制光标),P2.7接key2,控制调节(增加)

//grace配置中设置P2.345为输出,MCLK=1MHz,

//本程序将数据用ASCII表示,方便LCD1602显示

//在做DS1302的硬件时应该特别注意:数据线RST。SCLK、SDA一定上拉电阻,晶振添加负载电容,连接线尽量短

//date代表日,day代表星期几

#include <msp430.h>

#include <ti/mcu/msp430/csl/CSL.h>

//定义全局变量年月日时分秒

char year,month,date,hour,minute,second,n;//n代表周几

char love_years;                                                        //恋爱纪念年

char day[7][3]={"MON","TUE","WED","THI","FRI","SAT","SUN"};

char i=0;                                                        //用来记录key1按下的次数

char dis_buf1[16];                                  //lcd上排显示缓冲区

char dis_buf2[16];                                         //lcd下排显示缓冲区

char weiwei1[16]={"weiwei: I love u"};

char weiwei2[16]={"so much! by xuxu"};

char love1[16]={"We've been toget"};

char love2[16]={"her for    years"};

//LCD1602控制位

#define rs_0 (P2OUT &= ~BIT0)

#define rs_1 (P2OUT |= BIT0)

#define rw_0 (P2OUT &= ~BIT1)

#define rw_1 (P2OUT |= BIT1)

#define e_0  (P2OUT &= ~BIT2)

#define e_1  (P2OUT |= BIT2)

//DS1302控制位

#define SCLK_0 (P2OUT &= ~BIT3)

#define SCLK_1 (P2OUT |=  BIT3)

#define SDA_0  (P2OUT &= ~BIT4)

#define SDA_1  (P2OUT |=  BIT4)

#define RST_0  (P2OUT &= ~BIT5)

#define RST_1  (P2OUT |=  BIT5)

#define SDA    (P2IN  &=  BIT4)

//宏定义DS1302数据地址

#define write_second  0x80

#define read_second   0x81

#define write_minute  0x82

#define read_minute   0x83

#define write_hour    0x84

#define read_hour     0x85

#define write_date    0x86

#define read_date     0x87

#define write_month   0x88

#define read_month    0x89

#define write_year    0x8c

#define read_year     0x8d

#define write_day     0x8a

#define read_day             0x8b

#define write_protect 0x8e

#define write_power   0x90

//*******************以下为LCD1602的子函数************************//

//***********************************************************//

//查询是否忙碌(每次输入指令前都要判断液晶模块是否处于忙的状态)

char busy(void)

{

        char busyc;

        rs_0;

        rw_1;

        e_1;

        __delay_cycles(1000);

        P1DIR = 0x00;                                                        //P1口置为输入,读取LCD状态

        busyc = P1IN & BIT7;                                                                //从P1输入是否忙碌(D7高电平表示忙碌)

        P1DIR = 0xff;

        e_0;

        return busyc;

}

//向LCD1602写字节命令

void write_command(char command)

{

        while(busy());                                                        //判断LCD是否忙碌

        rs_0;

        rw_0;

        P1OUT = command;

        __delay_cycles(1);                                                //时间间隔MIN=30nS

        e_1;

        __delay_cycles(1);                                                //MIN=150nS

        e_0;

}

//向LCD1602写数据命令

void write_data(char data)

{

        while(busy());                                                        //判断LCD是否忙碌

        rs_1;

        rw_0;

        __delay_cycles(1);

        e_1;

        P1OUT=data;

        __delay_cycles(1);

        e_0;

}

//LCD1602初始化函数

void lsd1602_init()

{

        e_0;

        write_command(0x38);

        __delay_cycles(15000);

        write_command(0x0c);

        write_command(0x06);

        write_command(0x01);

}

void update_disbuf()

{

         dis_buf1[0]='2';

         dis_buf1[1]='0';

         dis_buf1[2]=year/16 + 0x30;

         dis_buf1[3]=year%16 + 0x30;

         dis_buf1[4]='-';

         dis_buf1[5]=month/16 + 0x30;

         dis_buf1[6]=month%16 + 0x30;

         dis_buf1[7]='-';

         dis_buf1[8]=date/16 + 0x30;

         dis_buf1[9]=date%16 + 0x30;

         dis_buf1[10]=' ';

         dis_buf1[11]=' ';

         dis_buf1[12]=' ';

         dis_buf1[13]=day[n-1][0];

         dis_buf1[14]=day[n-1][1];

         dis_buf1[15]=day[n-1][2];

         dis_buf2[0]=' ';

         dis_buf2[1]='j';

         dis_buf2[2]='w';

         dis_buf2[3]='w';

         dis_buf2[4]='&';

         dis_buf2[5]='z';

         dis_buf2[6]='x';

         dis_buf2[7]=' ';

         dis_buf2[8]=hour/16 + 0x30;

         dis_buf2[9]=hour%16 + 0x30;

         dis_buf2[10]=':';

         dis_buf2[11]=minute/16 + 0x30;

         dis_buf2[12]=minute%16 + 0x30;

         dis_buf2[13]=':';

         dis_buf2[14]=second/16 + 0x30;

         dis_buf2[15]=second%16 + 0x30;

}

void display()

{

        char t;

        write_command(0x80);

        for (t=0;t<=15;t++)

          {write_data(dis_buf1[t]);}

        write_command(0xc0);

        for (t=0;t<=15;t++)

          {write_data(dis_buf2[t]);}

}

//********************以下为DS1302的子函数************************//

//***********************************************************//

//向DS1302写一个字节的数据

void ds1302_Wbyte(char dat)

{

        char s,temp;

        temp = dat;

        for(s=0;s<8;s++)

          {if(temp & 0x01)                                //从低位开始传输数据

                {SDA_1;}

           else

                   SDA_0;

          SCLK_1;                                                //上升沿锁存数据

          temp = temp>>1;                                                //数据右移一位为下次输出做准备

          SCLK_0;                                                //为下一次做准备

      }

}

//从DS1302读取8位数据

char ds1302_Rbyte()

{

         char u,temp;

         P2DIR &= ~BIT4;

         for(u=8; u>0;u--)

          {

            temp=temp>>1;

            temp += (P2IN&BIT4)<<3;

            SCLK_1;

            SCLK_0;

          }

         P2DIR |=  BIT4;

         return(temp);

}

//向DS1302写入地址然后读取数据

char ds1302_Read(char cmd)

{

        char dat;

        RST_0;                                                        //初始化RST为低

        SCLK_0;                                                        //SLK=0

        RST_1;                                                        //开始传输数据

        ds1302_Wbyte(cmd);                                //传输命令字,写入要读取的时间、日期地址

        dat = ds1302_Rbyte();                        //读取八位数据

        RST_0;                                                        //结束数据传输

        SCLK_0;                                                        //拉高时钟线

        return(dat);

}

//向DS1302写入地址后写入数据

void ds1302_Write(char cmd,char dat)

{

        RST_0;

        SCLK_0;                                                        //在RST的上升沿,SCLK必须为0

        RST_1;                                                        //开始传输数据

        ds1302_Wbyte(cmd);                                //写入要修改的地址

        ds1302_Wbyte(dat);                                //写入数据

        SCLK_1;                                                        //拉高时钟线

        RST_0;                                                        //拉低RST

}

//初始化DS1302的程序

void ds1302_init(void)

{

        ds1302_Write(write_protect,0x00);//关闭写保护

        ds1302_Write(write_second,0x00); //初始化秒为00,不暂停时钟(BIT7)

        ds1302_Write(write_minute,0x59); //初始化分为00

        ds1302_Write(write_hour,0x23);   //初始化时为23,设置为24小时制(BIT7)

        ds1302_Write(write_date,0x01);         //初始化日期为01

        ds1302_Write(write_month,0x01);         //初始化月为01

        ds1302_Write(write_year,0x12);         //初始化年为(20)12

        ds1302_Write(write_day,0x07);         //周日

        ds1302_Write(write_power,0x0a5); //一个二极管压降,电阻4K

        ds1302_Write(write_protect,0x80);//打开写保护

}

//DS1302数据处理函数,此函数将个位、十位分别用char表示,方便用数码管显示

void data_pro(void)

{

        ds1302_Write(write_protect,0x00);//关闭写保护

        date   = ds1302_Read(read_date); //读取日

        if(date>0x29 && month==0x02)         //如果调时时2月超过29

                {ds1302_Write(write_date,0x01);

                date = ds1302_Read(read_date);

                ds1302_Write(write_month,month + 1);

                }

        month  = ds1302_Read(read_month);//读取月

        year   = ds1302_Read(read_year); //读取年

        hour   = ds1302_Read(read_hour); //读取时

        hour   = hour & 0x3f;                          //屏蔽掉前两位

        minute = ds1302_Read(read_minute);//读取分

        second = ds1302_Read(read_second);//读取秒

        n      = ds1302_Read(read_day);//读取星期

        ds1302_Write(write_protect,0x80);//打开写保护

}

//按键中断处理程序(使用grace配置)

void key_pro(void)

{

        char j;                                                        //用于复制自定义的显示计数(16个)

        __delay_cycles(8000);                        //延时去抖动

        if(!(P2IN & BIT6))                                        //判断是否有按键按下

        {

                i++;

                switch(i)

                {

                case 1:

                        write_command(0x83);        //显示光标到年

                        write_command(0x0f);

                        break;

                case 2:

                        write_command(0x86);        //显示光标到月

                        write_command(0x0f);

                        break;

                case 3:

                        write_command(0x89);        //显示光标到日

                        write_command(0x0f);

                        break;

                case 4:

                        write_command(0x8f);        //显示光标到周

                        write_command(0x0f);

                        break;

                case 5:

                        write_command(0xc9);        //显示光标到时

                        write_command(0x0f);

                        break;

                case 6:

                        write_command(0xcc);        //显示光标到分

                        write_command(0x0f);

                        break;

                case 7:

                        write_command(0xcf);        //显示光标到秒

                        write_command(0x0f);

                        break;

                default: break;

                }

        }

        if(i>7)

                {

                i=0;

                write_command(0x0c);                //关闭光标显示

                }

        P2IFG=0;                                                //软件复位标志

        while(!(P2IN & BIT6))

        {

          ds1302_Write(write_protect,0x00);//关闭写保护

          while(!(P2IN & BIT7))                                //如果按键2被按下

            {

                switch(i)                                        //根据i的值来确定某变量进行加1

                {case 0:                                        //显示自定义的语句

                        for(j=0;j<16;j++)

                        {

                                dis_buf1[j] = weiwei1[j];

                                dis_buf2[j] = weiwei2[j];

                                display();

                        }

                        break;

                case 1:                                                //此事处理全局变量year

                        year++;                                        //year加1

                        if(year>0x99)                        //如果year大于99则置0

                                year=0;

                        if((year & 0x0f)>0x09)        //如果year低四位大于9(第四位BCD码表示个位),十位加1,个位置0

                                {year +=0x10;

                                 year &=0xf0;

                                }

                        ds1302_Write(write_year,year);//将变化后的year写入DS1302

                        year   = ds1302_Read(read_year);//读出来year显示(使调节year时同步变化,为了人性化)

                        update_disbuf();                                //更新显示字符

                        while(!(P2IN & BIT7))

                                display();

                        break;

                case 2:                                                //此时处理全局变量month

                        month++;

                        if(month>0x12)

                                month=1;

                        if((month & 0x0f)>0x09)

                                {month +=0x10;

                                 month &=0xf0;

                                }

                        ds1302_Write(write_month,month);

                        month  = ds1302_Read(read_month);

                        update_disbuf();                //更新显示字符

                        while(!(P2IN & BIT7))

                                display();

                        break;

                case 3:                                                //此时处理全局变量date

                        date++;

                        if( (date>0x29 && month==0x02)

                           || (month==0x04 || month==0x06 || month==0x09 || month==0x11) && date>0x30

                           || date>0x31 )

                          date=0x01;

                        if((date & 0x0f)>0x09)

                        {date +=0x10;

                         date &=0xf0;

                        }

                        ds1302_Write(write_date,date);

                        date   = ds1302_Read(read_date);

                        update_disbuf();                //更新显示字符

                        while(!(P2IN & BIT7))

                                display();

                        break;

                case 4:                                                //此时处理全局变量day

                        n++;

                        if(n>0x07)

                                n=1;

                        ds1302_Write(write_day,n);

                        n = ds1302_Read(read_day);

                        update_disbuf();                //更新显示字符

                        while(!(P2IN & BIT7))

                                display();

                        break;

                case 5:                                                //此时处理全局变量hour

                        hour++;

                        if(hour>0x23)

                                hour=0;

                        if((hour & 0x0f)>0x09)

                                {hour +=0x10;

                                 hour &=0xf0;

                                }

                        ds1302_Write(write_hour,hour);

                        hour  = ds1302_Read(read_hour);

                        update_disbuf();                //更新显示字符

                        while(!(P2IN & BIT7))

                                display();

                        break;

                case 6:                                                //此时处理全局变量minute

                        minute++;

                        if(minute>0x59)

                                minute=0;

                        if((minute & 0x0f)>0x09)

                                {minute +=0x10;

                                 minute &=0xf0;

                                }

                        ds1302_Write(write_minute,minute);

                        minute  = ds1302_Read(read_minute);

                        update_disbuf();                //更新显示字符

                        while(!(P2IN & BIT7))

                                display();

                        break;

                case 7:                                                //此时处理全局变量second

                        second++;

                        if(second>0x59)

                                second=0;

                        if((second & 0x0f)>0x09)

                                {second +=0x10;

                                second &=0xf0;

                                }

                        ds1302_Write(write_second,second);

                        second  = ds1302_Read(read_second);

                        update_disbuf();                //更新显示字符

                        while(!(P2IN & BIT7))

                                display();

                        break;

                default: break;

                }

          }

        ds1302_Write(write_protect,0x80);//打开写保护

        }

}

//纪念日处理程序

void jww(void)

{char ww_xx;

for(ww_xx=0;ww_xx<16;ww_xx++)

        {

                 dis_buf1[ww_xx] = love1[ww_xx];

                dis_buf2[ww_xx] = love2[ww_xx];

        }

love_years= year - 0x11;                //减去2011年

dis_buf2[8]=love_years/16 + 0x30;

dis_buf2[9]=love_years%16 + 0x30;

display();

_DINT();

__delay_cycles(2000000);                //延时显示出来

_EINT();

}

//主函数

void main (void)

{

        CSL_init();                 // 初始化单片机

        lsd1602_init();                                // 初始化LCD1602

        ds1302_init();                                //初始化DS1302

        while(1)

                {

                _DINT();

                data_pro();                                //读取并处理数据

                _EINT();

                if(month== 0x03 && date== 0x07)//3月7日纪念日

                        jww();

                update_disbuf();                //更新显示字符

                display();                                //显示时间

                if(month== 0x03 && date== 0x07)//3月7日纪念日

                 __delay_cycles(1000000);

                }

}



来个大神帮解决一下谢谢

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top