找回密码
 立即注册

QQ登录

只需一步,快速开始

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

Proteus8.8仿真单片机tm1637时按键程序不工作,怎么解决?哪位给点意见啊!

[复制链接]
跳转到指定楼层
楼主
本帖最后由 3205440665 于 2020-3-5 22:45 编辑

/*
截止2020.3.5,用protues8.8能正常仿真tm1637进行数码管显示,但是不能正常仿真按键检测,
经与keil4联调后发现,在仿真时DIO端口一直为0,哪怕写上DIO=1;但是实际DIO依然为0;
导致按键检测的返回值为0x00;目前还不能找到原因,
根据tm1638使用经验,大概率是protues软件问题,个人分析。
示例程序由官方程序修改,电路也按照官方要求连线。
*/

单片机源程序如下:
#include <reg52.h>                                                //头文件
#include "intrins.h"                                                //包含_nop_()指令头文件

#define nop _nop_();_nop_();_nop_();_nop_();_nop_();                 //宏定义

/********************定义控制端口**********************/
sbit CLK=P1^0;                                                                 //定义CLK
sbit DIO=P1^1;                                                                 //定义DIO


/********************定义数据*************************/
unsigned char code CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共阳显示数据0-F
                                                        /* 0   1    2    3    4     5    6    7     8    9   a     b    c    d    e    f*/
unsigned char code TAB[10]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};//数码管不显示

/********************延时函数,延时nms******************/
void delay_nms(unsigned int n)
{
unsigned int i;
while(n--)
   for(i=0;i<550;i++);
}

/********************Start函数*************************/
void I2CStart()
{
        DIO=1;
        CLK=1;
        nop;
        DIO=1;
        nop;
        DIO=0;
        nop;
        CLK=0;
}

/********************Stop函数*************************/
void I2CStop()
{
    CLK=0;
    nop;
    nop;
    DIO=0;
    nop;
    nop;
    CLK=1;
    nop;
    nop;
    nop;
    DIO=1;
    nop;
    CLK=0;
    DIO=0;
}

/***************发送8bit数据,从低位开始**************/
void I2CWritebyte(unsigned char oneByte)
{
  unsigned char i;
  for(i=0;i<8;i++)
  {
    CLK=0;
        if(oneByte&0x01)
          DIO=1;
        else
          DIO=0;
        nop;
    CLK=1;
    oneByte=oneByte>>1;
  }
                                                                                  //8位数据传送完                 
        CLK = 0;                                                                //判断芯片发过来的ACK应答信号
        nop;
        while(DIO==1);
        nop;
        CLK = 1;
        nop;
}

/***************读按键程序**************/
unsigned char read_key()
{
        unsigned char rekey=0,i;
        I2CStart();
        I2CWritebyte(0x42);                                                         //写读键指令0x42
        DIO=1;
        for(i=0;i<8;i++)
        {
                CLK=0;
                nop;
                nop;
                rekey=rekey>>1;                                                           //先读低位
                nop;
                nop;
                CLK=1;
                if(DIO)
                  rekey=rekey|0x80;
                else
                  rekey=rekey|0x00;
                nop;
                  
        }

                CLK = 0;                                                          //判断芯片发过来的ACK应答信号
                nop;
                nop;
                while(DIO==1);
                nop;
                nop;
                CLK = 1;
                nop;
                nop;
                I2CStop();
                        
                return rekey;
}

/************显示函数,地址自加一************/
void disp0(unsigned char *p)                              
{
        unsigned char i;
        I2CStart();
        I2CWritebyte(0x40);                                  //数据命令设置:地址自动加1,写数据到显示寄存器
        I2CStop();
        
        I2CStart();
        I2CWritebyte(0xc0);                                  //地址命令设置:初始地址为00H
        for(i=0;i<6;i++)                                  //发送6字节数据到显存
        {
        I2CWritebyte(*p);
        p++;
        }
        I2CStop();
        
        I2CStart();
        I2CWritebyte(0x8C);                                 //显示控制命令:开显示,脉冲宽度为11/16.
        I2CStop();

}

/************显示函数,固定地址写数据************/
void smg_disp(unsigned char add, unsigned char value)
{
        I2CStart();
        I2CWritebyte(0x44);                                 //数据命令设置:固定地址,写数据到显示寄存器
        I2CStop();
        
        I2CStart();
        I2CWritebyte(0XC0+add);                                //地址命令设置:写入add对应地址
        
        I2CWritebyte(~CODE[value]);                        //给add地址写数据
        I2CStop();
        
        I2CStart();
        I2CWritebyte(0x8C);                                //显示控制命令:开显示,脉冲宽度为11/16.
        I2CStop();

}

/************按键处理函数,按键数据低位在前高位在后************/

void key_process()
{
unsigned char temp;
temp=read_key();                                   //读取按键返回值
  P0=temp;                //用于直观显示rekey的值

if(temp!=0xff)
{
  disp0(TAB);                                           //清屏
  switch(temp)
  {
                case 0xf7 : smg_disp(0,1);break;                  //K1与SG1对应按键按下,显示1
        case 0xf6 : smg_disp(1,2);break;                  //K1与SG2对应按键按下,显示2
        case 0xf5 : smg_disp(2,3);break;                  //K1与SG3对应按键按下,显示3
        case 0xf4 : smg_disp(3,4);break;                  //K1与SG4对应按键按下,显示4
        case 0xef : smg_disp(4,5);break;                  //K2与SG1对应按键按下,显示5
        case 0xee : smg_disp(5,6);break;                  //K2与SG2对应按键按下,显示6


  }
}
}

void main()
{   
    smg_disp(0,6);
        smg_disp(1,5);
        smg_disp(2,4);
        smg_disp(3,3);
        smg_disp(4,2);
        smg_disp(5,1);        
        delay_nms(1);

        while(1)
        {
                key_process(); //问题:按键程序无用
                delay_nms(100);
        }

}





tm1637.png (53.89 KB, 下载次数: 64)

电路

电路

TM1637读按键时序及说明.png (213.58 KB, 下载次数: 55)

时序及说明

时序及说明

TM1637_V2.5.pdf

945.97 KB, 下载次数: 29

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

使用道具 举报

沙发
ID:687694 发表于 2020-3-5 22:50 | 只看该作者
电路图发个全的看看。主要看不到DIO引脚接线全图。你可断开mcu与芯片的DIO连接,写入P1^1=1,观察是否可以拉高。再观察芯片DIO引脚是高还是低,这个通讯结构时序貌似就是I2C,正常情况应该双高释放总线,如果DIO上电就是低电平,则芯片的仿真有问题。查看属性设置能否解决。
回复

使用道具 举报

板凳
ID:703348 发表于 2020-3-6 10:52 | 只看该作者
延迟时间应该要设置长一点吧,一般IO端口的工作频率比CPU主频低很多,我看你延迟用的nop,估计不够
回复

使用道具 举报

地板
ID:703348 发表于 2020-3-6 10:53 | 只看该作者
IO端口工作频率比CPU低很多,延迟设置长一点应该是可以的。
顺便问一下,你这个Proteus 8.8 SP1版本的license怎么搞的?怎么破解的
回复

使用道具 举报

5#
ID:82043 发表于 2020-3-6 16:00 | 只看该作者
lovexulu 发表于 2020-3-5 22:50
电路图发个全的看看。主要看不到DIO引脚接线全图。你可断开mcu与芯片的DIO连接,写入P1^1=1,观察是否可以 ...

1、单独测试DIO,能正常工作。2、传入一位后双高释放总线,DIO依然为0.

3、tm1637属性对话框如图,没看到什么能改的????
4、延时改为delay100us(1)和delay100us(10)进行测试,按键均不工作。

搞不定就用实物,不仿真了

111.jpg (43.22 KB, 下载次数: 37)

tm1637电路

tm1637电路

222.jpg (54.13 KB, 下载次数: 30)

tm1637属性对话框

tm1637属性对话框
回复

使用道具 举报

6#
ID:82043 发表于 2020-3-6 16:01 | 只看该作者
者旨於陽 发表于 2020-3-6 10:52
延迟时间应该要设置长一点吧,一般IO端口的工作频率比CPU主频低很多,我看你延迟用的nop,估计不够

延时改为delay100us(1)和delay100us(10)进行测试,按键均不工作。
回复

使用道具 举报

7#
ID:82043 发表于 2020-3-6 16:02 | 只看该作者
者旨於陽 发表于 2020-3-6 10:53
IO端口工作频率比CPU低很多,延迟设置长一点应该是可以的。
顺便问一下,你这个Proteus 8.8 SP1版本的lice ...

网上找的,安装后就已经破了
回复

使用道具 举报

8#
ID:516163 发表于 2021-1-20 17:15 | 只看该作者
相同的问题,我也遇到了,应该DIO端口的问题,改为INPUT应该可以,问题不知道怎么改
回复

使用道具 举报

9#
ID:115923 发表于 2021-10-13 16:28 | 只看该作者
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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