定时器测频率
测量 100Hz 方波,STC8H8K64U@11.0592MHz, 12T 应该是 921,600Hz,测量100Hz应该计数 9216 即 0x2400
程序来源于AIAPP-ISP的例程,可以工作,但是输出为 0x12 (只看TH0) 比预计少一半?
void INT0_Isr() interrupt 0
{
TR0 = 0; // 停止计时
EX0 = 0; // 关中断
UART_SendChar(TH0); // 12T,100Hz 串口输出12
TL0 =0x00;
TH0 =0x00;
while (P32); // 等待INT0为低
TR0 = 1; // 启动定时器
EX0 = 1;
}
void main()
{
UART_Init();
AUXR = 0x00; // 12T模式
TMOD = 0x08; // 使能GATE,INT0为1时使能计时
TL0 =0x00;
TH0 =0x00;
while (P32); // 等待INT0为低
TR0 = 1; // 启动定时器
IT0 = 1; // 使能INT0下降沿中断
EX0 = 1;
EA = 1;
while (1);
}
在分析您提供的代码和测量结果时,我们可以从以下几个方面进行探讨:
1. 定时器配置与频率计算
STC8H8K64U单片机在12T模式下,定时器的时钟频率为系统时钟频率的1/12。因此,当系统时钟为11.0592MHz时,定时器的时钟频率为:
\[ f{timer} = \frac{11.0592 \text{MHz}}{12} = 921.6 \text{kHz} \]
对于100Hz的方波信号,每个周期的时间为:
\[ T = \frac{1}{100 \text{Hz}} = 10 \text{ms} \]
在10ms内,定时器应计数的次数为:
\[ N = f{timer} \times T = 921.6 \text{kHz} \times 10 \text{ms} = 9216 \]
因此,理论上TH0和TL0的计数值应为0x2400。
2. 代码分析
在您的代码中,定时器在INT0中断服务程序(ISR)中停止并读取TH0的值,然后通过串口发送。然而,您提到实际输出的TH0值为0x12,这与预期的0x24相差一半。
可能的原因包括:
2.1 定时器启动与停止时机
在ISR中,定时器在读取TH0后立即停止,并重新启动。如果定时器在读取TH0时尚未完成一个完整的周期计数,可能会导致计数值不准确。
2.2 中断响应时间
中断响应时间可能会影响定时器的计数。如果中断响应时间较长,定时器可能会在中断处理期间继续计数,导致读取的计数值不准确。
2.3 定时器模式配置
您配置了TMOD为0x08,即GATE模式,定时器的启动和停止由INT0引脚的电平控制。如果INT0引脚的电平变化不稳定,可能会导致定时器的启动和停止时机不准确。
3. 改进建议
为了确保定时器能够准确测量100Hz方波的频率,可以采取以下改进措施:
3.1 确保定时器完整计数
在ISR中,确保定时器在读取TH0和TL0之前已经完成一个完整的周期计数。可以通过在读取TH0和TL0之前等待一段时间来实现。
3.2 优化中断响应时间
尽量减少ISR中的操作,以缩短中断响应时间。例如,可以将串口发送操作移至主循环中,而不是在ISR中直接发送。
3.3 检查INT0引脚电平
确保INT0引脚的电平变化稳定,避免因电平抖动导致定时器启动和停止时机不准确。
4. 修改后的代码示例
以下是一个修改后的代码示例,供参考:
c
void INT0Isr() interrupt 0
{
TR0 = 0; // 停止计时
EX0 = 0; // 关中断
// 读取TH0和TL0
unsigned int count = (TH0 > 8); // 发送高字节
UARTSendChar(count & 0xFF); // 发送低字节
TL0 = 0x00;
TH0 = 0x00;
while (P32); // 等待INT0为低
TR0 = 1; // 启动定时器
EX0 = 1; // 开中断
}
void main()
{
UARTInit();
AUXR = 0x00; // 12T模式
TMOD = 0x08; // 使能GATE,INT0为1时使能计时
TL0 = 0x00;
TH0 = 0x00;
while (P32); // 等待INT0为低
TR0 = 1; // 启动定时器
EX0 = 1; // 开中断
while (1) {
// 主循环
}
}
通过以上改进,您应该能够更准确地测量100Hz方波的频率,并得到预期的计数值。
[本文内容由国芯人工智能辅助生成,仅供参考] 在分析您提供的代码和测量结果时,首先需要明确定时器的工作原理以及代码中可能存在的问题。根据您的描述,STC8H8K64U单片机工作在12T模式下,系统时钟频率为11.0592MHz,因此定时器的计数频率为11.0592MHz / 12 = 921.6kHz。对于100Hz的方波信号,理论上每个周期内定时器应计数9216次,即0x2400。
然而,您的代码输出结果为0x12(仅看TH0),这比预期值少了一半。以下是对可能原因的分析及改进建议:
1. 定时器模式配置
您将TMOD寄存器配置为0x08,即模式1(16位定时器)并启用了GATE位。GATE位的作用是当INT0引脚为高电平时,定时器才开始计数。这种配置在测量频率时是合理的,但需要确保INT0引脚的电平变化与定时器的启动和停止同步。
2. 中断处理逻辑
在INT0Isr中断服务程序中,您停止了定时器并关闭了外部中断0(EX0),然后通过串口发送TH0的值。这里可能存在以下问题:
TH0的值未与TL0组合:TH0和TL0共同组成16位定时器计数值。如果仅发送TH0,可能会丢失TL0的低8位信息,导致计数值不准确。
定时器未完全停止:在停止定时器(TR0 = 0)后,建议读取TL0和TH0的值,以确保获取完整的计数值。
3. 定时器清零时机
在中断服务程序中,您在发送TH0值后立即清零TL0和TH0。这可能导致在定时器停止和清零之间存在微小的时间差,从而影响计数值的准确性。
4. 等待INT0为低的逻辑
在中断服务程序中,您使用while (P32);等待INT0引脚为低电平。这种忙等待的方式可能会影响程序的实时性,尤其是在高频信号测量时。
改进建议
以下是针对上述问题的改进建议:
c
void INT0Isr() interrupt 0
{
TR0 = 0; // 停止定时器
EX0 = 0; // 关闭外部中断0
uint16t count = (TH0 > 8); // 发送高8位
UARTSendChar(count & 0xFF); // 发送低8位
TL0 = 0x00; // 清零TL0
TH0 = 0x00; // 清零TH0
while (P32); // 等待INT0为低
TR0 = 1; // 启动定时器
EX0 = 1; // 使能外部中断0
}
void main()
{
UARTInit();
AUXR = 0x00; // 12T模式
TMOD = 0x08; // 使能GATE, INT0为1时使能计时
TL0 = 0x00;
TH0 = 0x00;
while (P32); // 等待INT0为低
TR0 = 1; // 启动定时器
EX0 = 1; // 使能外部中断0
while (1) {
// 主循环
}
}
改进点说明
1. 组合TH0和TL0:在中断服务程序中,将TH0和TL0组合为16位计数值,确保获取完整的计数值。
2. 发送完整的计数值:通过串口发送完整的16位计数值,避免仅发送高8位导致的误差。
3. 定时器清零时机:在停止定时器后立即读取计数值,确保计数值的准确性。
通过以上改进,您的代码应能更准确地测量100Hz方波的频率,并输出正确的计数值。如果问题仍然存在,建议进一步检查硬件连接和信号质量,确保INT0引脚的电平变化与预期一致。
[本文内容由国芯人工智能辅助生成,仅供参考]
页:
[1]