H_Franky 2019-12-22 18:22 采纳率: 22.7%
浏览 1290
已结题

帮我改C语言代码(51单片机LCD1602显示时间从k1这些按键控制变成矩阵按键控制)

帮我改C语言代码,51单片机LCD1602显示时间从k1这些按键控制变成矩阵按键控制(现在是可以用k1这些按键来修改了)
原理图:
图片说明
图片说明

下面是代码:

//下面是main.c代码
/*******************************************************************************
* 实验名            : 万年历实验
* 使用的IO        : 
* 实验效果       :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒日月,按K2选择
*选择设置加1。 
*   注意                   :
*******************************************************************************/

#include<reg51.h>
#include"lcd.h"
#include"ds1302.h"

sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3;    //管脚接线

void Int0Configuration();
void LcdDisplay();
unsigned char SetState,SetPlace;
void Delay10ms(void);   //误差 0us
/*******************************************************************************
* 函数名         : main
* 函数功能         : 主函数
* 输入           : 无
* 输出             : 无
*******************************************************************************/

void main()
{
    unsigned char i;
    Int0Configuration();
    LcdInit();
    Ds1302Init();
    while(1)
    {   
        if(SetState==0)
        {
            Ds1302ReadTime();
        }
        else
        {
            if(K1==0)       //检测按键K1是否按下
            {
                Delay10ms();    //消除抖动
                if(K1==0)
                {
                    SetPlace++;
                    if(SetPlace>=7)
                        SetPlace=0;                 
                }

                while((i<50)&&(K1==0))   //检测按键是否松开
                {
                    Delay10ms();
                    i++;
                }
                i=0;
            }
            if(K2==0)       //检测按键K2是否按下
            {
                Delay10ms();    //消除抖动
                if(K2==0)
                {
                    TIME[SetPlace]++;
                    if((TIME[SetPlace]&0x0f)>9)                  //换成BCD码。
                    {
                        TIME[SetPlace]=TIME[SetPlace]+6;
                    }
                    if((TIME[SetPlace]>=0x60)&&(SetPlace<2))        //分秒只能到59
                    {
                        TIME[SetPlace]=0;
                    }
                    if((TIME[SetPlace]>=0x24)&&(SetPlace==2))       //小时只能到23
                    {
                        TIME[SetPlace]=0;
                    }
                    if((TIME[SetPlace]>=0x32)&&(SetPlace==3))       //日只能到31
                    {
                        TIME[SetPlace]=0;   
                    }
                    if((TIME[SetPlace]>=0x13)&&(SetPlace==4))       //月只能到12
                    {
                        TIME[SetPlace]=0;
                    }   
                    if((TIME[SetPlace]>=0x7)&&(SetPlace==5))        //周只能到7
                    {
                        TIME[SetPlace]=1;
                    }       
//                  if(SetPlace==5)     //月只能到12
//                  {
//                      TIME[SetPlace]=;
//                  }   
                }

                while((i<50)&&(K2==0))   //检测按键是否松开
                {
                    Delay10ms();
                    i++;
                }
                i=0;

            }                       
        }
        LcdDisplay();   
    }

}
/*******************************************************************************
* 函数名         : LcdDisplay()
* 函数功能         : 显示函数
* 输入           : 无
* 输出             : 无
*******************************************************************************/

void LcdDisplay()
{
    LcdWriteCom(0x80+0X40);
    LcdWriteData('0'+TIME[2]/16);               //时
    LcdWriteData('0'+(TIME[2]&0x0f));                
    LcdWriteData('-');
    LcdWriteData('0'+TIME[1]/16);               //分
    LcdWriteData('0'+(TIME[1]&0x0f));   
    LcdWriteData('-');
    LcdWriteData('0'+TIME[0]/16);               //秒
    LcdWriteData('0'+(TIME[0]&0x0f));

    LcdWriteCom(0x80);
    LcdWriteData('2');
    LcdWriteData('0');
    LcdWriteData('0'+TIME[6]/16);           //年
    LcdWriteData('0'+(TIME[6]&0x0f));
    LcdWriteData('-');
    LcdWriteData('0'+TIME[4]/16);           //月
    LcdWriteData('0'+(TIME[4]&0x0f));
    LcdWriteData('-');
    LcdWriteData('0'+TIME[3]/16);           //日
    LcdWriteData('0'+(TIME[3]&0x0f));
    LcdWriteCom(0x8D);
    LcdWriteData('0'+(TIME[5]&0x07));   //星期             
}
/*******************************************************************************
* 函数名         : Int0Configuration()
* 函数功能         : 配置外部中断0
* 输入           : 无
* 输出             : 无
*******************************************************************************/

void Int0Configuration()
{
    //设置INT0
    IT0=1;//跳变沿出发方式(下降沿)
    EX0=1;//打开INT0的中断允许。
    EA=1;//打开总中断  
}
/*******************************************************************************
* 函数名         : Int0() 
* 函数功能         : 外部中断0 中断函数
* 输入           : 无
* 输出             : 无
*******************************************************************************/

void Int0() interrupt 0      
{
    Delay10ms();
    if(K3==0)
    {
        SetState=~SetState;
        SetPlace=0;
        Ds1302Init();   
    }
}
/*******************************************************************************
* 函数名         : Delay10ms
* 函数功能         : 延时函数,延时10ms
* 输入           : 无
* 输出             : 无
*******************************************************************************/
void Delay10ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}



//下面为ds1302.c代码
#include"ds1302.h"

//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; 
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};

/*******************************************************************************
* 函 数 名         : Ds1302Write
* 函数功能         : 向DS1302命令(地址+数据)
* 输    入         : addr,dat
* 输    出         : 无
*******************************************************************************/

void Ds1302Write(uchar addr, uchar dat)
{
    uchar n;
    RST = 0;
    _nop_();

    SCLK = 0;//先将SCLK置低电平。
    _nop_();
    RST = 1; //然后将RST(CE)置高电平。
    _nop_();

    for (n=0; n<8; n++)//开始传送八位地址命令
    {
        DSIO = addr & 0x01;//数据从低位开始传送
        addr >>= 1;
        SCLK = 1;//数据在上升沿时,DS1302读取数据
        _nop_();
        SCLK = 0;
        _nop_();
    }
    for (n=0; n<8; n++)//写入8位数据
    {
        DSIO = dat & 0x01;
        dat >>= 1;
        SCLK = 1;//数据在上升沿时,DS1302读取数据
        _nop_();
        SCLK = 0;
        _nop_();    
    }   

    RST = 0;//传送数据结束
    _nop_();
}

/*******************************************************************************
* 函 数 名         : Ds1302Read
* 函数功能         : 读取一个地址的数据
* 输    入         : addr
* 输    出         : dat
*******************************************************************************/

uchar Ds1302Read(uchar addr)
{
    uchar n,dat,dat1;
    RST = 0;
    _nop_();

    SCLK = 0;//先将SCLK置低电平。
    _nop_();
    RST = 1;//然后将RST(CE)置高电平。
    _nop_();

    for(n=0; n<8; n++)//开始传送八位地址命令
    {
        DSIO = addr & 0x01;//数据从低位开始传送
        addr >>= 1;
        SCLK = 1;//数据在上升沿时,DS1302读取数据
        _nop_();
        SCLK = 0;//DS1302下降沿时,放置数据
        _nop_();
    }
    _nop_();
    for(n=0; n<8; n++)//读取8位数据
    {
        dat1 = DSIO;//从最低位开始接收
        dat = (dat>>1) | (dat1<<7);
        SCLK = 1;
        _nop_();
        SCLK = 0;//DS1302下降沿时,放置数据
        _nop_();
    }

    RST = 0;
    _nop_();    //以下为DS1302复位的稳定时间,必须的。
    SCLK = 1;
    _nop_();
    DSIO = 0;
    _nop_();
    DSIO = 1;
    _nop_();
    return dat; 
}

/*******************************************************************************
* 函 数 名         : Ds1302Init
* 函数功能         : 初始化DS1302.
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void Ds1302Init()
{
    uchar n;
    Ds1302Write(0x8E,0X00);      //禁止写保护,就是关闭写保护功能
    for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
    {
        Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]); 
    }
    Ds1302Write(0x8E,0x80);      //打开写保护功能
}

/*******************************************************************************
* 函 数 名         : Ds1302ReadTime
* 函数功能         : 读取时钟信息
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void Ds1302ReadTime()
{
    uchar n;
    for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
    {
        TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
    }

}



//下面是lcd.c代码
#include"lcd.h"

/*******************************************************************************
* 函 数 名         : Lcd1602_Delay1ms
* 函数功能         : 延时函数,延时1ms
* 输    入         : c
* 输    出         : 无
* 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/

void Lcd1602_Delay1ms(uint c)   //误差 0us
{
    uchar a,b;
    for (; c>0; c--)
    {
         for (b=199;b>0;b--)
         {
            for(a=1;a>0;a--);
         }      
    }

}

/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能         : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
#ifndef     LCD1602_4PINS    //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com)   //写入命令
{
    LCD1602_E = 0;     //使能
    LCD1602_RS = 0;    //选择发送命令
    LCD1602_RW = 0;    //选择写入

    LCD1602_DATAPINS = com;     //放入命令
    Lcd1602_Delay1ms(1);        //等待数据稳定

    LCD1602_E = 1;            //写入时序
    Lcd1602_Delay1ms(5);      //保持时间
    LCD1602_E = 0;
}
#else 
void LcdWriteCom(uchar com)   //写入命令
{
    LCD1602_E = 0;   //使能清零
    LCD1602_RS = 0;  //选择写入命令
    LCD1602_RW = 0;  //选择写入

    LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;   //写入时序
    Lcd1602_Delay1ms(5);
    LCD1602_E = 0;

//  Lcd1602_Delay1ms(1);
    LCD1602_DATAPINS = com << 4; //发送低四位
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;   //写入时序
    Lcd1602_Delay1ms(5);
    LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能         : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/           
#ifndef     LCD1602_4PINS          
void LcdWriteData(uchar dat)            //写入数据
{
    LCD1602_E = 0;  //使能清零
    LCD1602_RS = 1; //选择输入数据
    LCD1602_RW = 0; //选择写入

    LCD1602_DATAPINS = dat; //写入数据
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;   //写入时序
    Lcd1602_Delay1ms(5);   //保持时间
    LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat)            //写入数据
{
    LCD1602_E = 0;    //使能清零
    LCD1602_RS = 1;   //选择写入数据
    LCD1602_RW = 0;   //选择写入

    LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;    //写入时序
    Lcd1602_Delay1ms(5);
    LCD1602_E = 0;

    LCD1602_DATAPINS = dat << 4; //写入低四位
    Lcd1602_Delay1ms(1);

    LCD1602_E = 1;    //写入时序
    Lcd1602_Delay1ms(5);
    LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能       : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/           
#ifndef     LCD1602_4PINS
void LcdInit()                        //LCD初始化子程序
{
    LcdWriteCom(0x38);  //开显示
    LcdWriteCom(0x0c);  //开显示不显示光标
    LcdWriteCom(0x06);  //写一个指针加1
    LcdWriteCom(0x01);  //清屏
    LcdWriteCom(0x80);  //设置数据指针起点
}
#else
void LcdInit()                        //LCD初始化子程序
{
    LcdWriteCom(0x32);   //将8位总线转为4位总线
    LcdWriteCom(0x28);   //在四位线下的初始化
    LcdWriteCom(0x0c);  //开显示不显示光标
    LcdWriteCom(0x06);  //写一个指针加1
    LcdWriteCom(0x01);  //清屏
    LcdWriteCom(0x80);  //设置数据指针起点
}
#endif


  • 写回答

1条回答 默认 最新

  • 关注
    评论

报告相同问题?

悬赏问题

  • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面
  • ¥50 NT4.0系统 STOP:0X0000007B
  • ¥15 想问一下stata17中这段代码哪里有问题呀
  • ¥15 flink cdc无法实时同步mysql数据
  • ¥100 有人会搭建GPT-J-6B框架吗?有偿
  • ¥15 求差集那个函数有问题,有无佬可以解决
  • ¥15 【提问】基于Invest的水源涵养
  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组