找回密码
 立即注册
查看: 99|回复: 5

求大师们帮忙

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:120
  • 最近打卡:2025-05-01 07:02:40

71

主题

84

回帖

212

积分

中级会员

积分
212
发表于 2025-4-21 14:00:39 | 显示全部楼层 |阅读模式
这是一个频率计代码,显示部分用的是TM1652驱动5位LED数码管,显示采用KHz做单位,这部分采用的是模块化,头文件和C文件完整。现在的问题是:全局变量count, 也就是中断0的P3.2输入端脉冲个数,为int型时显示正常,但只能显示65.535KHZ以下的频率,现在要求能显示99.999KHZ以下的频率,将count由int型改为long型时,就无法显示应有的频率了,五位数码管一直死在改前的数值上,求大师们指点一二。源主代码如下(未贴TM1652头文件和C文件):



#include "TM1652.h"
#include "REG51.h"

typedef unsigned char u8;
typedef unsigned int u16;

// 定义变量
unsigned int count = 0;  // 用于计数脉冲个数
unsigned int time_count = 0;  // 用于计时
float frequency = 0;  // 保存频率值(Hz),改为 float 类型以支持小数

// 共阴 LED 0--F 段码,包含小数点
const u8 CODE[16] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
const u8 CODE_WITH_DOT[16] = {0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF, 0xF7, 0xFC, 0xB9, 0xDE, 0xF9, 0xF1};

// 延时 10ms 函数
void Delay10ms()         //@11.0592MHz
{
    unsigned char i, j;
    i = 18;
    j = 235;
    do
    {
        while (--j);
    } while (--i);
}

// 数码管显示函数,显示缩小 1000 倍后的频率(保留 3 位小数,最大显示 99.999)
void TM_Digtal_Display(float num)
{
    // 定义所有局部变量在函数开头
    unsigned int integer_part;  // 整数部分
    unsigned int decimal_part1, decimal_part2, decimal_part3;  // 三位小数部分
    unsigned int tens;
    unsigned int units;
    float decimal_part_float;  // 声明小数部分的临时变量

    // 计算缩小 1000 倍后的整数部分和小数部分
    integer_part = (unsigned int)(num / 1000);
    decimal_part_float = (num / 1000 - integer_part) * 1000;
    decimal_part1 = (unsigned int)(decimal_part_float / 100);
    decimal_part2 = (unsigned int)((decimal_part_float - decimal_part1 * 100) / 10);
    decimal_part3 = (unsigned int)(decimal_part_float - decimal_part1 * 100 - decimal_part2 * 10);

    // 计算整数部分的十位和个位
    tens = (integer_part % 100) / 10;
    units = integer_part % 10;

    // 发送显示命令
    tm1652_send_data(0x08);  // 可能是设置显示模式相关命令

    // 显示十位
    tm1652_send_data(CODE[tens]);
    // 显示个位并带小数点
    tm1652_send_data(CODE_WITH_DOT[units]);
    // 显示小数第一位
    tm1652_send_data(CODE[decimal_part1]);
    // 显示小数第二位
    tm1652_send_data(CODE[decimal_part2]);
    // 显示小数第三位
    tm1652_send_data(CODE[decimal_part3]);

    // 空位补零(这里可以根据实际情况调整,比如如果前面的位没有显示,补零方式可能不同)
    tm1652_send_data(CODE[0]);

    Delay10ms();
    tm1652_send_data(0x18);  // 可能是设置显示模式相关命令
    tm1652_send_data(0xFE);  // 可能是设置显示模式相关命令
}

// 定时器 0 中断服务函数
void timer0_isr() interrupt 1 {
    float timer0_reload_float;
    unsigned int timer0_reload;
    // 更精确的定时器初值计算并微调
    timer0_reload_float = 65536 - (11059200.0 / 12 / 1000) + 3.7;
    // 四舍五入
    timer0_reload = (unsigned int)(timer0_reload_float + 0.5);
    TH0 = (unsigned char)(timer0_reload / 256);
    TL0 = (unsigned char)(timer0_reload % 256);
    time_count++;
    if (time_count >= 1000) {  // 定时 1s
        time_count = 0;
        // 读取计数值
        TR1 = 0;  // 停止计数
        frequency = (float)count;  // 保存频率值(Hz),转换为 float 类型
        // 加上补偿值 365
        frequency += 365;
        count = 0;  // 清零计数值
        TR1 = 1;  // 重新开始计数

        // 输出当前频率值

        // 在中断服务程序中调用显示函数
        TM_Digtal_Display(frequency);
    }
}

// 外部中断 0 服务函数,用于计数脉冲
void int0_isr() interrupt 0
{
    count++;
    // 输出当前计数值
}

void main()
{
    float timer0_reload_float;
    unsigned int timer0_reload;
    // 定时器 0 初始化
    TMOD |= 0x01;  // 定时器 0 工作在模式 1(16 位定时器)
    // 更精确的定时器初值计算并微调
    timer0_reload_float = 65536 - (11059200.0 / 12 / 1000) + 3.7;
    // 四舍五入
    timer0_reload = (unsigned int)(timer0_reload_float + 0.5);
    TH0 = (unsigned char)(timer0_reload / 256);
    TL0 = (unsigned char)(timer0_reload % 256);
    ET0 = 1;  // 使能定时器 0 中断
    TR0 = 1;  // 启动定时器 0

    // 外部中断 0 初始化
    IT0 = 1;  // 下降沿触发
    EX0 = 1;  // 使能外部中断 0

    // 定时器 1 初始化,用于计数脉冲
    TMOD |= 0x50;  // 定时器 1 工作在模式 1(16 位计数器)
    TH1 = 0;
    TL1 = 0;
    TR1 = 1;  // 启动定时器 1

    EA = 1;  // 全局中断使能

    // 开机显示 00000
    TM_Digtal_Display(0);         

    while (1)
    {
        // 主循环可以留空或者进行其他非紧急任务
    }
}

回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-21 14:03:00 | 显示全部楼层
针对您提出的问题,以下是一些可能的原因和解决方案:

问题分析
1. 数据类型溢出:int型变量在大多数系统中是16位,最大值为32767(有符号)或65535(无符号)。当count超过65535时,int型变量会溢出,导致显示异常。将count改为long型(32位)可以解决溢出问题,但需要确保代码的其他部分也支持32位数据处理。

2. 显示驱动问题:TM1652驱动5位LED数码管时,可能只支持16位数据的显示。如果count改为long型,但显示驱动未做相应调整,可能导致显示异常。

3. 中断处理问题:中断服务程序(ISR)可能未正确处理32位数据,导致count值未正确更新。

解决方案
1. 修改数据类型:将count改为long型,并确保所有相关变量和函数也支持32位数据。

2. 更新显示驱动:检查TM1652驱动代码,确保其支持32位数据的显示。可能需要修改显示函数,以正确处理32位数据。

3. 调整中断服务程序:确保中断服务程序正确处理32位数据,并在更新count时避免数据丢失。

代码修改示例
以下是对代码的修改建议:
  1. c
  2. include "TM1652.h"
  3. include "REG51.h"
  4. typedef unsigned char u8;
  5. typedef unsigned int u16;
  6. typedef unsigned long u32;  // 添加32位数据类型
  7. // 定义变量
  8. u32 count = 0;  // 用于计数脉冲个数,改为u32型
  9. u16 timecount = 0;  // 用于计时
  10. float frequency = 0;  // 保存频率值(Hz),改为 float 类型以支持小数
  11. // 共阴 LED 0--F 段码,包含小数点
  12. const u8 CODE[16] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
  13. const u8 CODEWITHDOT[16] = {0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF, 0xF7, 0xFC, 0xB9, 0xDE, 0xF9, 0xF1};
  14. // 延时 10ms 函数
  15. void Delay10ms() {
  16.     // 延时函数实现
  17. }
  18. // 中断服务程序
  19. void Timer0ISR() interrupt 1 {
  20.     count++;  // 计数脉冲个数
  21. }
  22. // 显示频率函数
  23. void DisplayFrequency(u32 freq) {
  24.     u8 digits[5];
  25.     digits[0] = freq / 10000 % 10;
  26.     digits[1] = freq / 1000 % 10;
  27.     digits[2] = freq / 100 % 10;
  28.     digits[3] = freq / 10 % 10;
  29.     digits[4] = freq % 10;
  30.     // 调用TM1652显示函数,显示digits数组中的数字
  31.     TM1652Display(digits);
  32. }
  33. void main() {
  34.     // 初始化TM1652
  35.     TM1652Init();
  36.     // 配置定时器0
  37.     // ...
  38.     while (1) {
  39.         // 计算频率
  40.         frequency = (float)count / (timecount  0.001);  // 假设timecount单位为ms
  41.         // 显示频率
  42.         DisplayFrequency((u32)frequency);
  43.         // 延时
  44.         Delay10ms();
  45.     }
  46. }
复制代码

注意事项
1. TM1652驱动代码:确保TM1652Display函数支持32位数据的显示。如果驱动代码只支持16位数据,需要修改驱动代码以支持32位数据。

2. 中断服务程序:确保中断服务程序正确处理32位数据,并在更新count时避免数据丢失。

3. 调试和测试:在修改代码后,进行充分的调试和测试,确保频率计能够正确显示99999KHz以下的频率。

通过以上修改和调整,您应该能够解决count改为long型后无法正常显示频率的问题。如果问题仍然存在,建议进一步检查硬件连接和驱动代码的实现细节。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:32
  • 最近打卡:2025-04-30 10:59:33

25

主题

1154

回帖

2391

积分

超级版主

积分
2391
发表于 2025-4-21 14:41:51 | 显示全部楼层
截图202504211430541508.jpg 截图202504211433467182.jpg 截图202504211436238766.jpg



STC8H4K64TL系列集成了80mA大电流LED数码管自动刷新。一个芯片搞定外设+驱动功能。后面新产品您可以考虑试用。

手册下载链接:https://www.stcaimcu.com/data/download/Datasheet/AI8.pdf
段码LCD/80mA大电流LED数码管自动刷新显示论坛支持板块:https://www.stcaimcu.com/forum-52-1.html


STC官网:https://www.stcai.com/
QQ:2593903262
微信号:18106296598
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:120
  • 最近打卡:2025-05-01 07:02:40

71

主题

84

回帖

212

积分

中级会员

积分
212
发表于 2025-4-21 14:47:09 | 显示全部楼层
AI-32*** 发表于 2025-4-21 14:41
STC8H4K64TL系列集成了80mA大电流LED数码管自动刷新。一个芯片搞定外设+驱动功能。后面新产品您可以考 ...

你发的手册下载连接打开是空白的

点评

[attachimg]94746[/attachimg] 链接是可以打开的。或者您自己去官网下载:深圳国芯人工智能有限公司-产品_STC8H系列 https://www.stcai.com/cp_stc8hxl  详情 回复 发表于 2025-4-21 15:45
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2025-4-21 15:25:49 | 显示全部楼层
注意数据类型转换
建议使用AI8H4K64TL直接驱动数码管
以下是我9年前写的5位数码管频率计程序供参考:
  1. #include"reg51.h"
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. #define ulong unsigned long
  5. sbit ww=P2^0;//万位
  6. sbit qw=P2^1;//千位
  7. sbit bw=P2^2;//百位
  8. sbit sw=P2^3;//十位
  9. sbit gw=P2^4;//个位
  10. uchar wan,qian,bai,shi,ge,a;
  11. ulong count,b;
  12. uint code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳极数码管不带小数点代码表
  13. void delay(uint i)//延时i*100微秒
  14. {
  15.   uint j,k;
  16.   for(j=i;j>0;j--)
  17.     for(k=9;k>0;k--);
  18. }
  19. void init()//初始化函数
  20. {
  21.         TMOD=0x01;
  22.         TH0=(65536-50000)/256;
  23.         TL0=(65536-50000)%256;
  24.         PX0=0;
  25.         PT0=1;
  26.         IT0=1;
  27.         EA=1;
  28.         ET0=1;
  29.         EX0=1;
  30.         TR0=1;
  31.         a=0;
  32.         count=0;
  33. }
  34. void display()//显示函数
  35. {
  36.         wan=count/10000;
  37.         qian=count%10000/1000;
  38.         bai=count%1000/100;
  39.         shi=count%100/10;
  40.         ge=count%10;
  41.         P0=table[wan];
  42.         ww=1;
  43.         delay(5);
  44.         ww=0;
  45.         P0=table[qian];
  46.         qw=1;
  47.         delay(5);
  48.         qw=0;
  49.         P0=table[bai];
  50.         bw=1;
  51.         delay(5);
  52.         bw=0;
  53.         P0=table[shi];
  54.         sw=1;
  55.         delay(5);
  56.         sw=0;
  57.         P0=table[ge];
  58.         gw=1;
  59.         delay(5);
  60.         gw=0;
  61. }
  62. void main()//主函数
  63. {
  64.         init();
  65.         while(1)
  66.         {
  67.                 display();
  68.                 if(a>=20)
  69.                 {
  70.                         a=0;
  71.                         count=b;
  72.                         b=0;
  73.                 }
  74.         }
  75. }
  76. void add() interrupt 0
  77. {
  78.         b++;
  79. }
  80. void time() interrupt 1
  81. {
  82.         TH0=(65536-50000)/256;
  83.         TL0=(65536-50000)%256;
  84.         a++;
  85. }
复制代码


DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:32
  • 最近打卡:2025-04-30 10:59:33

25

主题

1154

回帖

2391

积分

超级版主

积分
2391
发表于 2025-4-21 15:45:15 | 显示全部楼层
cjt*** 发表于 2025-4-21 14:47
你发的手册下载连接打开是空白的

截图202504211544324219.jpg
链接是可以打开的。或者您自己去官网下载:深圳国芯人工智能有限公司-产品_STC8H系列  https://www.stcai.com/cp_stc8hxl

截图202504211542136763.jpg
STC官网:https://www.stcai.com/
QQ:2593903262
微信号:18106296598
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-1 20:54 , Processed in 0.121369 second(s), 85 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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