找回密码
 立即注册
查看: 94|回复: 3

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

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:167
  • 最近打卡:2025-06-17 00:02:12

122

主题

162

回帖

369

积分

中级会员

积分
369
发表于 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[16] = {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[5] = {
        CODE[num / 10000],
        CODE[(num % 10000) / 1000],
        CODE[(num % 1000) / 100],
        CODE[(num % 100) / 10],
        CODE[num % 10]
    };
    for (u8 i = 0; i < 5; i++)
    {
        tm1652_send_data(data[i]);
    }
    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();
    }
}


回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:167
  • 最近打卡:2025-06-17 00:02:12

122

主题

162

回帖

369

积分

中级会员

积分
369
发表于 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;
}
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:167
  • 最近打卡:2025-06-17 00:02:12

122

主题

162

回帖

369

积分

中级会员

积分
369
发表于 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);
        }
    }
}
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:167
  • 最近打卡:2025-06-17 00:02:12

122

主题

162

回帖

369

积分

中级会员

积分
369
发表于 2025-5-29 18:07:48 | 显示全部楼层
1652模块代码没修改。
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-6-17 15:30 , Processed in 0.127158 second(s), 62 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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