求大神们看看不显示问题出到哪里
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();
}
}
记忆模块代码
#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;
} 按键模块代码:
#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);
}
}
}
1652模块代码没修改。
页:
[1]