求大师们帮忙
这是一个频率计代码,显示部分用的是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 = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
const u8 CODE_WITH_DOT = {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);
// 显示个位并带小数点
tm1652_send_data(CODE_WITH_DOT);
// 显示小数第一位
tm1652_send_data(CODE);
// 显示小数第二位
tm1652_send_data(CODE);
// 显示小数第三位
tm1652_send_data(CODE);
// 空位补零(这里可以根据实际情况调整,比如如果前面的位没有显示,补零方式可能不同)
tm1652_send_data(CODE);
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)
{
// 主循环可以留空或者进行其他非紧急任务
}
}
针对您提出的问题,以下是一些可能的原因和解决方案:
问题分析
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时避免数据丢失。
代码修改示例
以下是对代码的修改建议:
c
include "TM1652.h"
include "REG51.h"
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;// 添加32位数据类型
// 定义变量
u32 count = 0;// 用于计数脉冲个数,改为u32型
u16 timecount = 0;// 用于计时
float frequency = 0;// 保存频率值(Hz),改为 float 类型以支持小数
// 共阴 LED 0--F 段码,包含小数点
const u8 CODE = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
const u8 CODEWITHDOT = {0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF, 0xF7, 0xFC, 0xB9, 0xDE, 0xF9, 0xF1};
// 延时 10ms 函数
void Delay10ms() {
// 延时函数实现
}
// 中断服务程序
void Timer0ISR() interrupt 1 {
count++;// 计数脉冲个数
}
// 显示频率函数
void DisplayFrequency(u32 freq) {
u8 digits;
digits = freq / 10000 % 10;
digits = freq / 1000 % 10;
digits = freq / 100 % 10;
digits = freq / 10 % 10;
digits = freq % 10;
// 调用TM1652显示函数,显示digits数组中的数字
TM1652Display(digits);
}
void main() {
// 初始化TM1652
TM1652Init();
// 配置定时器0
// ...
while (1) {
// 计算频率
frequency = (float)count / (timecount0.001);// 假设timecount单位为ms
// 显示频率
DisplayFrequency((u32)frequency);
// 延时
Delay10ms();
}
}
注意事项
1. TM1652驱动代码:确保TM1652Display函数支持32位数据的显示。如果驱动代码只支持16位数据,需要修改驱动代码以支持32位数据。
2. 中断服务程序:确保中断服务程序正确处理32位数据,并在更新count时避免数据丢失。
3. 调试和测试:在修改代码后,进行充分的调试和测试,确保频率计能够正确显示99999KHz以下的频率。
通过以上修改和调整,您应该能够解决count改为long型后无法正常显示频率的问题。如果问题仍然存在,建议进一步检查硬件连接和驱动代码的实现细节。
[本文内容由国芯人工智能辅助生成,仅供参考]
STC8H4K64TL系列集成了80mA大电流LED数码管自动刷新。一个芯片搞定外设+驱动功能。后面新产品您可以考虑试用。
手册下载链接:https://www.stcaimcu.com/data/download/Datasheet/AI8.pdf
段码LCD/80mA大电流LED数码管自动刷新显示论坛支持板块:https://www.stcaimcu.com/forum-52-1.html
AI-32位8051 发表于 2025-4-21 14:41
STC8H4K64TL系列集成了80mA大电流LED数码管自动刷新。一个芯片搞定外设+驱动功能。后面新产品您可以考 ...
你发的手册下载连接打开是空白的 注意数据类型转换
建议使用AI8H4K64TL直接驱动数码管
以下是我9年前写的5位数码管频率计程序供参考:
#include"reg51.h"
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit ww=P2^0;//万位
sbit qw=P2^1;//千位
sbit bw=P2^2;//百位
sbit sw=P2^3;//十位
sbit gw=P2^4;//个位
uchar wan,qian,bai,shi,ge,a;
ulong count,b;
uint code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳极数码管不带小数点代码表
void delay(uint i)//延时i*100微秒
{
uint j,k;
for(j=i;j>0;j--)
for(k=9;k>0;k--);
}
void init()//初始化函数
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
PX0=0;
PT0=1;
IT0=1;
EA=1;
ET0=1;
EX0=1;
TR0=1;
a=0;
count=0;
}
void display()//显示函数
{
wan=count/10000;
qian=count%10000/1000;
bai=count%1000/100;
shi=count%100/10;
ge=count%10;
P0=table;
ww=1;
delay(5);
ww=0;
P0=table;
qw=1;
delay(5);
qw=0;
P0=table;
bw=1;
delay(5);
bw=0;
P0=table;
sw=1;
delay(5);
sw=0;
P0=table;
gw=1;
delay(5);
gw=0;
}
void main()//主函数
{
init();
while(1)
{
display();
if(a>=20)
{
a=0;
count=b;
b=0;
}
}
}
void add() interrupt 0
{
b++;
}
void time() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
a++;
}
cjtdz 发表于 2025-4-21 14:47
你发的手册下载连接打开是空白的
链接是可以打开的。或者您自己去官网下载:深圳国芯人工智能有限公司-产品_STC8H系列https://www.stcai.com/cp_stc8hxl
页:
[1]