cjtdz 发表于 2025-5-29 18:04:30

求大神们看看不显示问题出到哪里

3个按键,一个增,一个减,一个清零,STC15F204单片机,TM1652驱动4位LED数码管,按增键数值逐一增加,不松手时快速增加;按减键则相反。按清除键显示清零。这些都正常。

后来增加了一个确认OK键,要求按下后记住当前数值,断电后要求显示以前的数值,增加了数值记忆模块,在主程序里添加了两行代码,现在不显示了,求指点哪里有误。
主代码:

#include "STC15.H"
#include "TM1652.h"
#include "key.h"
#include "memory.h"

// 声明全局变量
unsigned int count = 0;// 关键:确保count为全局变量

typedef unsigned char u8;
typedef unsigned int u16;

const u8 CODE = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};

void Delay5ms(void)        //@11.0592MHz
{
    unsigned char data i, j;

    i = 54;
    j = 199;
    do
    {
      while (--j);
    } while (--i);
}

void TM_Digtal_Display(u16 num)
{
    tm1652_send_data(0x08);// 启动命令
    // 分解数值(确保万位非零时有显示,否则补零)
    u8 data = {
      CODE,
      CODE[(num % 10000) / 1000],
      CODE[(num % 1000) / 100],
      CODE[(num % 100) / 10],
      CODE
    };
    for (u8 i = 0; i < 5; i++)
    {
      tm1652_send_data(data);
    }
    Delay5ms();
    tm1652_send_data(0x1F);// 最高亮度
    tm1652_send_data(0xFE);// 结束命令
}

void main()
{
    u16 delaytick = 0;
    TM_Digtal_Display(0);// 初始化显示
   
    // 加载并显示EEPROM数值
    count = LoadCountFromEEPROM();// 关键:接收返回值
    TM_Digtal_Display(count);
   
    while (1)
    {
      key();
      if (++delaytick == 10)
      {
            delaytick = 0;
            TM_Digtal_Display(count);
      }
      Delay5ms();
    }
}


cjtdz 发表于 2025-5-29 18:05:54

记忆模块代码
#ifndef __MEMORY_H__
#define __MEMORY_H__

#include "STC15.H"
unsigned int value;
// 函数声明
void Memory_Init(void);            // 初始化记忆模块
void SaveCountToEEPROM(unsigned int count);// 保存计数值到EEPROM
unsigned int LoadCountFromEEPROM(void);      // 从EEPROM加载计数值

#endif


#include "memory.h"
#include <intrins.h>

// 定义EEPROM相关寄存器地址
#define IAP_DATA    (*(unsigned char volatile xdata *)0xC000)
#define IAP_ADDRH   (*(unsigned char volatile xdata *)0xC002)
#define IAP_ADDRL   (*(unsigned char volatile xdata *)0xC003)
#define IAP_CMD   (*(unsigned char volatile xdata *)0xC004)
#define IAP_TRIG    (*(unsigned char volatile xdata *)0xC005)
#define IAP_CONTR   (*(unsigned char volatile xdata *)0xC006)

// EEPROM数据存储地址
#define COUNT_ADDRESS 0x2000// 计数值存储地址

// 通用延时函数(ms级)
static void delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for(i = 0; i < ms; i++)
      for(j = 0; j < 120; j++);// 根据晶振频率调整
}

// 使能IAP
static void IAP_ENABLE()
{
    IAP_CONTR = 0x83;// 允许IAP操作,设置等待时间
    IAP_CMD = 0;       // 待机模式
    IAP_TRIG = 0;      // 清除触发寄存器
}

// 关闭IAP
static void IAP_DISABLE()
{
    IAP_CONTR = 0;   // 禁止IAP操作
    IAP_CMD = 0;       // 待机模式
    IAP_TRIG = 0;      // 清除触发寄存器
}

// 擦除扇区
static void SectorErase(unsigned int addr)
{
    IAP_ENABLE();
    IAP_ADDRL = addr & 0xFF;
    IAP_ADDRH = addr >> 8;
    IAP_CMD = 3;       // 扇区擦除命令
    EA = 0;            // 关中断
    IAP_TRIG = 0x5A;   // 触发IAP命令
    IAP_TRIG = 0xA5;
    _nop_();
    EA = 1;            // 开中断
    IAP_DISABLE();
   
    delay_ms(5);// 擦除后延时
}

// 写一个字节到EEPROM
static void ByteWrite(unsigned int addr, unsigned char dat)
{
    IAP_ENABLE();
    IAP_ADDRL = addr & 0xFF;
    IAP_ADDRH = addr >> 8;
    IAP_CMD = 2;       // 字节写命令
    IAP_DATA = dat;
    EA = 0;            // 关中断
    IAP_TRIG = 0x5A;   // 触发IAP命令
    IAP_TRIG = 0xA5;
    _nop_();
    EA = 1;            // 开中断
    IAP_DISABLE();
   
    delay_ms(5);// 写入后延时
}

// 从EEPROM读一个字节
static unsigned char ByteRead(unsigned int addr)
{
    unsigned char dat;
    IAP_ENABLE();
    IAP_ADDRL = addr & 0xFF;
    IAP_ADDRH = addr >> 8;
    IAP_CMD = 1;       // 字节读命令
    EA = 0;            // 关中断
    IAP_TRIG = 0x5A;   // 触发IAP命令
    IAP_TRIG = 0xA5;
    _nop_();
    dat = IAP_DATA;
    EA = 1;            // 开中断
    IAP_DISABLE();
    return dat;
}

// 初始化记忆模块
void Memory_Init(void)
{
    // 可添加初始化代码,如检查EEPROM是否有效
}

// 保存计数值到EEPROM
void SaveCountToEEPROM(unsigned int count)
{
    SectorErase(COUNT_ADDRESS);// 擦除扇区
   
    // 保存16位计数值(拆分为两个字节)
    ByteWrite(COUNT_ADDRESS, count & 0xFF);      // 低字节
    ByteWrite(COUNT_ADDRESS + 1, (count >> 8) & 0xFF);// 高字节
}

// 从EEPROM加载计数值
unsigned int LoadCountFromEEPROM(void)
{
    unsigned char lowByte, highByte;
    unsigned int value;// 定义value变量
   
    // 读取两个字节
    lowByte = ByteRead(COUNT_ADDRESS);
    highByte = ByteRead(COUNT_ADDRESS + 1);
   
    // 组合成16位数值
    value = (highByte << 8) | lowByte;
   
    // 验证数值范围(可选)
    if (value > 99999) {
      value = 0;// 如果读取的值无效,返回0
    }
   
    return value;
}

cjtdz 发表于 2025-5-29 18:07:12

按键模块代码:
#ifndef KEY_H
#define KEY_H

#include "STC15.H"

// 宏定义
#define LONG_PRESS_THRESHOLD 500// 长按阈值(ms)
#define REPEAT_INTERVAL    20    // 重复间隔(ms)

// 按键引脚定义(根据实际硬件调整)
sbit up   = P3^3;// 上键
sbit down = P3^4;// 下键
sbit clr= P3^5;        // 清零键
sbit ok   = P3^6;// 确认键

// 外部变量声明
extern unsigned int count;
extern unsigned int upPressTime;
extern unsigned int downPressTime;
extern bit upIsPressed;
extern bit downIsPressed;

// 函数声明
void key();
void delay(unsigned int time);

#endif // KEY_H


#include "key.h"
#include "TM1652.h"// 包含显示驱动头文件,用于更新显示
#include "STC15.h"// 包含STC15单片机头文件
#include <intrins.h>// 包含_nop_()函数的头文件

// 全局变量定义
unsigned int count = 0;
unsigned int upPressTime = 0;
unsigned int downPressTime = 0;
bit upIsPressed = 0;
bit downIsPressed = 0;
bit confirmFlag = 0;// 确认标志

// 定义长按阈值和重复间隔(单位:ms)
#define LONG_PRESS_THRESHOLD 500// 500ms长按触发
#define REPEAT_INTERVAL 100       // 100ms重复间隔



// 通用延时函数(ms级)
void delay1ms(unsigned int time)        //@11.0592MHz
{
        unsigned char data i, j;

        while(time--)
        {
                _nop_();
                _nop_();
                _nop_();
                i = 11;
                j = 190;
                do
                {
                        while (--j);
                } while (--i);
        }
}

// 按键扫描函数
void key()
{
       unsigned char i;
       
    static bit confirmIsPressed = 0;// 确认键状态标志

    // --------------------- 上键检测 ---------------------
    if (up == 0)// 按键按下(低电平有效)
    {
      if (!upIsPressed)// 未触发长按标志
      {
            delay1ms(20);// 消抖
            if (up == 0)// 确认按下
            {
                upIsPressed = 1;      // 标记为已按下
                upPressTime = 0;      // 重置长按计时
                count = (count < 99999) ? count + 1 : 99999;// 数值加1(上限99999)
                TM_Digtal_Display(count);// 更新显示
            }
      }
      else// 已触发长按标志,进入连续计数模式
      {
            upPressTime += 10;// 计时(10ms/次)
            if (upPressTime >= LONG_PRESS_THRESHOLD && upPressTime % REPEAT_INTERVAL == 0)
            {
                count = (count < 99999) ? count + 1 : 99999;// 连续加1
                TM_Digtal_Display(count);// 更新显示
            }
      }
    }
    else// 按键释放
    {
      if (upIsPressed)// 清除长按状态
      {
            upIsPressed = 0;
            upPressTime = 0;
            delay1ms(20);// 释放后消抖
      }
    }

    // --------------------- 下键检测 ---------------------
    if (down == 0)
    {
      if (!downIsPressed)
      {
            delay1ms(20);
            if (down == 0)
            {
                downIsPressed = 1;
                downPressTime = 0;
                count = (count > 0) ? count - 1 : 0;// 数值减1(下限0)
                TM_Digtal_Display(count);
            }
      }
      else
      {
            downPressTime += 10;
            if (downPressTime >= LONG_PRESS_THRESHOLD && downPressTime % REPEAT_INTERVAL == 0)
            {
                count = (count > 0) ? count - 1 : 0;
                TM_Digtal_Display(count);
            }
      }
    }
    else
    {
      if (downIsPressed)
      {
            downIsPressed = 0;
            downPressTime = 0;
            delay1ms(20);
      }
    }

   // --------------------- 确认键检测 ---------------------
    if (ok == 0)// 按下确认键
    {
      if (!confirmIsPressed)// 未触发确认状态
      {
            delay1ms(20);// 消抖
            if (ok == 0)// 确认按下
            {
                confirmIsPressed = 1;// 标记为已确认
                SaveCountToEEPROM();   // 保存当前数值到EEPROM
                confirmFlag = 1;       // 设置确认标志
               
                // 添加确认成功的提示(可选)
                // 例如:闪烁显示或蜂鸣器响
               
                for(i = 0; i < 3; i++)
                                                        {
                  TM_Digtal_Display(0xFFFF);// 显示全亮
                  delay1ms(100);
                  TM_Digtal_Display(count);    // 恢复显示
                  delay1ms(100);
                }
            }
      }
    }
    else// 释放确认键
    {
      confirmIsPressed = 0;// 重置状态
   
                }
    // --------------------- 清零键检测 ---------------------
    if (clr == 0)// 按下清零键
    {
      delay1ms(20);// 消抖
      if (clr == 0)// 确认按下
      {
            count = 0;         // 清零
            TM_Digtal_Display(count);
      }
    }
}

cjtdz 发表于 2025-5-29 18:07:48

1652模块代码没修改。
页: [1]
查看完整版本: 求大神们看看不显示问题出到哪里