找回密码
 立即注册

QQ登录

只需一步,快速开始

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

大佬们好,设计的电子码表时间误差大是为什么

[复制链接]
跳转到指定楼层
楼主
ID:1168017 发表于 2026-3-12 21:02 来自触屏版 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
这是我根据网上的一些电路图自己改的,但是它的时间误差很大,正常20秒时间,上面显示16 17。是代码问题还是电路逻辑问题?

Image_1773319705559_301.png (85.68 KB, 下载次数: 0)

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

使用道具 举报

沙发
ID:1168017 发表于 2026-3-13 00:06 来自触屏版 | 只看该作者
#include <reg51.h> #include <absacc.h>  // 8255端口地址定义(基于P2.5=A0, P2.6=A1, P2.7=CS,低有效) #define PA8255  XBYTE[0x0000]   // A口:P2.7=0, P2.6=0, P2.5=0 #define PB8255  XBYTE[0x2000]   // B口:P2.7=0, P2.6=0, P2.5=1 #define PC8255  XBYTE[0x4000]   // C口:P2.7=0, P2.6=1, P2.5=0 #define COM8255 XBYTE[0x6000]   // 控制口:P2.7=0, P2.6=1, P2.5=1  // 共阴极数码管段码表(0-9,空白) code unsigned char seg_code[] = {     0x3F, // 0     0x06, // 1     0x5B, // 2     0x4F, // 3     0x66, // 4     0x6D, // 5     0x7D, // 6     0x07, // 7     0x7F, // 8     0x6F, // 9     0x00  // 空白 };  // 按键位定义(PC0~PC5) #define KEY_START_PAUSE 0x01 #define KEY_RESET       0x02 #define KEY_SAVE        0x04 #define KEY_QUERY       0x08 #define KEY_PREV        0x10 #define KEY_NEXT        0x20  // 全局变量 unsigned long count = 0;            // 改为long型,支持0~9分59.99秒,避免溢出 bit running = 0;                    // 计时运行标志 unsigned long record[10] = {0};     // 记录数组同步改为long型,保存分钟+秒信息 unsigned char record_count = 0;     // 已存记录数(0~10) bit mode = 0;                       // 0=计时模式,1=查询模式 unsigned char query_index = 0;      // 当前查询的记录索引(0~9) unsigned char display_buffer[8];    // 显示缓冲区  // 按键扫描相关 unsigned char key_prev = 0; bit key_scan_flag = 0;              // 10ms扫描标志  // 定时器0中断服务程序(10ms) void timer0_isr(void) interrupt 1 {     TH0 = 0xD8;                     // 12MHz,10ms初值     TL0 = 0xF0;     if (running) {         count++;         // 取消99.99秒清零,累计为分钟,最大支持9分59.99秒         if (count >= 5999) {}     }     key_scan_flag = 1;              // 通知主循环扫描按键 }  // 定时器0初始化 void timer_init() {     TMOD &= 0xF0;     TMOD |= 0x01;                   // 定时器0,模式1     TH0 = 0xD8;     TL0 = 0xF0;     ET0 = 1;     EA = 1;     TR0 = 1; }  // 更新显示缓冲区(核心修改:分钟位加分隔符,分·秒清晰区分) void update_display() {     unsigned char i;     unsigned char buf[8];     unsigned char minute;           // 分钟(1位,0~9)     unsigned int sec_total;         // 剩余秒数(0~5999,对应00.00~59.99秒)     unsigned int int_part, frac_part; // 秒的整数部分、小数部分     unsigned char tens, ones, tenths, hundredths;     unsigned long val;          for (i = 0; i < 8; i++) buf[i] = 0x00; // 先全灭      if (mode == 0) {                 // 计时模式         // 第1、2位:已存记录数(两位,不足补零)         buf[0] = seg_code[record_count / 10];         buf[1] = seg_code[record_count % 10];         buf[2] = 0x00;                // 第3位空白          // 计算分钟和剩余秒数         minute = count / 6000;      // 6000个0.01秒=60秒=1分钟,取个位分钟         sec_total = count % 6000;   // 剩余秒数(0~5999)                  // 拆分剩余秒数:整数部分(秒)=sec_total/100,小数部分=sec_total%100         int_part = sec_total / 100;         frac_part = sec_total % 100;         tens = int_part / 10;       // 秒的十位(0~5)         ones = int_part % 10;       // 秒的个位(0~9)         tenths = frac_part / 10;    // 秒的十分位         hundredths = frac_part % 10;// 秒的百分位          // 第4~8位:分钟(1位+分隔符)+ 秒(99.99格式)【核心修改】         buf[3] = seg_code[minute] | 0x80;  // 分钟位+右侧小数点(分隔符),分·秒         buf[4] = seg_code[tens];    // 第5位:秒十位         buf[5] = seg_code[ones] | 0x80; // 第6位:秒个位+小数点         buf[6] = seg_code[tenths];  // 第7位:秒十分位         buf[7] = seg_code[hundredths]; // 第8位:秒百分位     } else {                          // 查询模式【同步修改分钟位分隔符】         if (record_count > 0) {             // 显示当前记录序号(从1开始)             buf[0] = seg_code[(query_index + 1) / 10];             buf[1] = seg_code[(query_index + 1) % 10];             buf[2] = 0x00;                          // 显示记录值(同步支持分钟+分隔符)             val = record[query_index];             minute = val / 6000;    // 记录的分钟             sec_total = val % 6000; // 记录的剩余秒数                          // 拆分剩余秒数             int_part = sec_total / 100;             frac_part = sec_total % 100;             tens = int_part / 10;             ones = int_part % 10;             tenths = frac_part / 10;             hundredths = frac_part % 10;                          buf[3] = seg_code[minute] | 0x80;  // 分钟位+分隔符(和计时模式一致)             buf[4] = seg_code[tens];             buf[5] = seg_code[ones] | 0x80;             buf[6] = seg_code[tenths];             buf[7] = seg_code[hundredths];         } else {             // 如果没有记录,返回计时模式             mode = 0;         }     }     // 复制到全局显示缓冲区     for (i = 0; i < 8; i++) display_buffer[i] = buf[i]; }  // 动态扫描显示(位选低电平有效,无修改) void display() {     unsigned char i;     unsigned int j;          for (i = 0; i < 8; i++) {         PB8255 = 0xFF;               // 消隐,关闭所有位         PA8255 = display_buffer[i];  // 送段码         PB8255 = ~(1 << i);          // 选中第i位(i=0对应最左边)         // 短暂延时         for (j = 0; j < 100; j++);     } }  // 按键扫描 void scan_key() {     unsigned char key_current, key_down;     unsigned char i;          key_current = ~PC8255 & 0x3F;    // 读PC0~PC5,取反得按下为1     key_down = key_current & (key_current ^ key_prev);     key_prev = key_current;      // 处理按键事件     if (key_down & KEY_START_PAUSE) {         if (mode == 0) {             running = !running;      // 计时模式下开始/暂停         }     }          // 复位按键     if (key_down & KEY_RESET) {         running = 0;                 // 停止计时         count = 0;                   // 清零当前值(分钟+秒都清零)                  if (mode == 1) {             // 如果在查询模式,退出查询             mode = 0;         } else {             // 在计时模式下,清除所有记录             record_count = 0;             for (i = 0; i < 10; i++) {                 record[i] = 0;             }         }     }          // 保存按键     if (key_down & KEY_SAVE) {         if (mode == 0) {              // 计时模式下保存             if (record_count < 10) {                 record[record_count] = count; // 保存当前count(含分钟信息)                 record_count++;             }         } else {                      // 查询模式下清除所有记录             record_count = 0;             mode = 0;                  // 退出查询         }     }          // 查询按键 - 修改为点击一次直接进入查询模式     if (key_down & KEY_QUERY) {         if (mode == 0) {               // 当前在计时模式             if (record_count > 0) {     // 有记录可查                 mode = 1;                // 直接切换到查询模式                 query_index = 0;          // 指向第一个记录             }         } else {                       // 当前在查询模式             mode = 0;                    // 退出查询,返回计时模式         }     }          // 上一个按键     if (key_down & KEY_PREV) {         if (mode == 1 && record_count > 0) {             // 查询模式下切换上一个记录             if (query_index == 0) query_index = record_count - 1;             else query_index--;         }     }          // 下一个按键     if (key_down & KEY_NEXT) {         if (mode == 1 && record_count > 0) {             // 查询模式下切换下一个记录             query_index = (query_index + 1) % record_count;         }     } }  // 主函数(无修改) void main() {     // 初始化8255:方式0,A口输出,B口输出,C口输入     COM8255 = 0x89;                  // 1000 1001B      timer_init();                    // 初始化定时器      // 初始状态     count = 0;     running = 0;     record_count = 0;     mode = 0;     key_prev = 0;      while (1) {         if (key_scan_flag) {         // 每10ms扫描一次按键             key_scan_flag = 0;             scan_key();         }         update_display();             // 更新显示内容         display();                    // 动态扫描显示     } }
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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