标题:
单片机源程序如下:测双路脉冲的占空比,有一路数据不对
[打印本页]
作者:
ADMIN_ALLENY
时间:
2021-7-14 16:39
标题:
单片机源程序如下:测双路脉冲的占空比,有一路数据不对
现在想用外部中断0和外部中断1来测双路脉冲的占空比,实现的方法是先把定时器0设置成TMOD |=0x08(//T0开始计时的条件是INT0脚为高电平及TR0置1时)模式,以此来测P3^2脚输入脉冲高电平的时间,然后外部中断0是下降沿中断,通过两次下降沿中断来测P3^2脚输入脉冲的周期,以此来算占空比;同理用同样的再去测P3^3脚输入脉冲的占空比,两路脉冲每测试完以此刷新一下屏幕显示,然后延迟500ms再去测两个输入脉冲,如此循环,可是测量的结果却不对,P3^2脚的输入脉冲没有问题,但是P3^3脚输入脉冲的周期测试不准确,正常是8点几毫秒,但是测出来的值时零点几毫秒,但是高电平时间是对的。思考了好长时间实在找不到错误,因此来寻求大神的帮助,望不吝赐教。
单片机源程序如下:
#include "stc15.h"
#include "COMMON.H"
#include "LCD12864.H"
ulong atime_h =0; //a路正脉冲频宽
ulong atime = 0; //a路脉冲周期
ulong Dutycycle_a = 0; //a路脉冲占空比
uint int0_count = 0; //外部中断0的中断次数
ulong btime_h =0; //b路正脉冲频宽
ulong btime = 0; //b路脉冲周期
ulong Dutycycle_b = 0; //b路脉冲占空比
uint int1_count = 0; //外部中断1的中断次数
uint flag = 0;
void display_data(uchar address,ulong b) //脉冲周期或正脉冲频宽的显示函数 (6位)
{
lcd_write_byte(0xf8,address);
lcd_write_byte(0xfa,b/100000+0x30);
lcd_write_byte(0xfa,(b%100000)/10000+0x30);
lcd_write_byte(0xfa,(b%10000)/1000+0x30);
lcd_write_byte(0xfa,(b%1000)/100+0x30);
lcd_write_byte(0xfa,(b%100)/10+0x30);
lcd_write_byte(0xfa,(b%10)+0x30);
}
void display_data1(uchar address,ulong b)
{
lcd_write_byte(0xf8,address);
lcd_write_byte(0xfa,b/100+0x30);
lcd_write_byte(0xfa,(b%100)/10+0x30);
lcd_write_byte(0xfa,0x2e); //小数点
lcd_write_byte(0xfa,(b%10)+0x30);
}
void int0_init()
{
IT0 = 1; //为 1 是下降沿; 为 0 是下降沿或上升沿
EX0 = 0; //为 1 允许中断; 为 0 是禁止中断
}
void int1_init()
{
IT1 = 1; //为 1 是下降沿; 为 0 是下降沿或上升沿
EX1 = 0; //为 1 允许中断; 为 0 是禁止中断
}
void t0_init() //65536us@12MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF8; //设置定时器模式
//TMOD |= 0x08; //T0开始计时的条件是INT0脚为高电平及TR0置1时
TL0 = 0x00; //设置定时初值
TH0 = 0x00; //设置定时初值
TF0 = 0; //清除TF0标志
ET0 = 1; //允许T0中断
TR0 = 0; //定时器0停止计时
}
void t1_init() //65536us@12MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x8F; //设置定时器模式
//TMOD |= 0x80; //T1开始计时的条件是INT1脚为高电平及TR1置1时
TL1 = 0x00; //设置定时初值
TH1 = 0x00; //设置定时初值
TF1 = 0; //清除TF1标志
ET1 = 1; //允许T1中断
TR1 = 0; //定时器1停止计时
}
void show_freq()
{
if(flag == 1)
{
display_data1(0x91,Dutycycle_a);
display_data(0x95,atime_h);
display_data1(0x89,Dutycycle_b);
display_data(0x8D,btime);
delay_xms(500);
flag = 0;
}
else
{
TMOD |= 0x08;
EX0 = 1;
}
}
void fuwei() //复位函数
{
TR0 = 0;
TR1 = 0;
EX0 = 0;
EX1 = 0;
TH0 = 0;
TL0 = 0;
TH1 = 0;
TL1 = 0;
int0_count = 0;
int1_count = 0;
}
void main()
{
stc_init();
int0_init();
int1_init();
t0_init();
t1_init();
lcd_init();
delay_xms(5);
lcd_clean();
delay_xms(5);
lcd_write_string(0x80," 占空比 正周期");
lcd_write_string(0x90,"A:");
lcd_write_string(0x93,"%");
lcd_write_string(0x88,"B:");
lcd_write_string(0x8B,"%");
lcd_write_string(0x98,"C:");
lcd_write_string(0x9B,"%");
delay_xms(5);
EA=1;
while(1)
{
show_freq();
}
}
void int0() interrupt 0
{
if(flag == 0)
{
int0_count++;
}
if(int0_count == 1)
{
TR1 = 1;
TR0 = 1;
}
if(int0_count == 2)
{
TR0 = 0;
TR1 = 0;
atime_h = TH0<<8|TL0;
atime = TH1<<8|TL1;
Dutycycle_a = atime_h*1000/atime;
EX0 = 0;
TH0 = 0;
TL0 = 0;
TH1 = 0;
TL1 = 0;
int0_count = 0;
TMOD &= 0xF7;
TMOD |= 0x80;
EX1 = 1;
}
}
void int1() interrupt 2
{
if(flag == 0)
{
int1_count++;
}
if(int1_count == 1)
{
TR1 = 1;
TR0 = 1;
}
if(int1_count == 2)
{
TR0 = 0;
TR1 = 0;
btime_h = TH1<<8|TL1;
btime = TH0<<8|TL0;
Dutycycle_b = btime_h*1000/btime;
EX1 = 0;
TH0 = 0;
TL0 = 0;
TH1 = 0;
TL1 = 0;
int1_count = 0;
TMOD &= 0x7F;
flag = 1;
}
}
void t0() interrupt 1
{
fuwei();
}
void t1() interrupt 3
{
fuwei();
}
复制代码
作者:
yzwzfyz
时间:
2021-7-15 11:14
道理:INT0中断服务过程中,INT1是不会被响应的,需要等INT0中断服务结束,INT1才能被响应,这样INT1就失去了计时的准确性。
你需要好好的规划一下,解决中断优先级不平等的问题,或者将误差缩小到可接受的范围内。
作者:
ADMIN_ALLENY
时间:
2021-7-15 11:40
yzwzfyz 发表于 2021-7-15 11:14
道理:INT0中断服务过程中,INT1是不会被响应的,需要等INT0中断服务结束,INT1才能被响应,这样INT1就失去 ...
额,可是我就是在外部中断0的服务过程中完成取定时器的值后把外部中断0的中断允许位置0了,然后置位了外部中断1的中断允许位,就是一步步来的,先外部中断0后外部中断1.
作者:
glinfei
时间:
2021-7-15 17:29
TMOD&=0xF7 是否改成0xD5,M1M0至11时,是8位计数啊,也就能计算零点几个毫秒。
另外就是这句TMOD |= 0x80;是否应去掉?没意义。
作者:
开心就好hhhh
时间:
2021-7-15 17:40
在一个中断函数中置位另一个中断是不会立即响应的,就算你已经关闭了本次中断,也要等本次中断结束才能响应另外一个中断
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1