完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
我所编写的变频器程序在调整频率后,使用示波器来观察频率时,发现波形有抖动的现象,请问如何才能解决这个问题,单片机的型号是STC89C51。ヽ(*。>Д<)o
|
|
相关推荐
1个回答
|
|
|
定时器中断服务程序中,每次中断都会切换波形状态,并重新设置定时器的重载值。但是,由于中断响应和代码执行的时间,可能会造成一定的误差。另外,在设置频率时,关闭了中断,然后重新设置定时器值,这可能会引起波形的不连续。
此外,使用的STC89C51是12T的8051单片机,每个机器周期由12个时钟周期组成。因此,定时器每12个时钟周期计数一次。在计算定时器计数时,我们已经考虑了这一点(除以12)。 但是,在计算high_count和low_count时,使用了公式: high_count = (high_us * SYS_CLK) / 12000000UL; 这是因为:high_us * SYS_CLK 得到的是时钟周期数,而定时器每12个时钟周期计数一次,所以除以12,即12000000UL实际上是12*1000000。 另外,减去了一个INTERRUPT_DELAY(3)来补偿中断响应时间。但是,这个值可能需要根据实际情况调整。 可能的问题: 1. 中断响应时间补偿不准确。 2. 在设置新频率时,关闭中断可能会造成波形抖动。 3. 定时器重载值的计算可能因为整数除法的舍入而产生误差。 试下 #include sbit WAVE_OUT = P1^0; volatile unsigned int freq = 1000; volatile unsigned short high_count; volatile unsigned short low_count; volatile bit wave_state = 0; #define SYS_CLK 11059200UL #define MIN_FREQ 50 #define MAX_FREQ 10000 #define INTERRUPT_OVERHEAD 8 void calculate_timer_counts() { unsigned long half_period_ticks; // 精确计算半周期定时器计数 half_period_ticks = (SYS_CLK / 12UL) / freq / 2; // 范围保护 if (half_period_ticks > 65535) half_period_ticks = 65535; if (half_period_ticks < 10) half_period_ticks = 10; // 补偿中断延迟 if (half_period_ticks > INTERRUPT_OVERHEAD) { high_count = half_period_ticks - INTERRUPT_OVERHEAD; low_count = half_period_ticks - INTERRUPT_OVERHEAD; } else { high_count = 1; low_count = 1; } } void timer0_init() { TMOD &= 0xF0; TMOD |= 0x01; // 定时器0,模式1,16位定时器 ET0 = 1; // 允许定时器0中断 EA = 1; // 开总中断 } void timer0_isr() interrupt 1 { if (wave_state) { WAVE_OUT = 0; TH0 = (0x10000 - low_count) >> 8; TL0 = (0x10000 - low_count) & 0xFF; } else { WAVE_OUT = 1; TH0 = (0x10000 - high_count) >> 8; TL0 = (0x10000 - high_count) & 0xFF; } wave_state = !wave_state; } void set_frequency(unsigned int freq_val) { EA = 0; // 关中断保护 if (freq_val < MIN_FREQ) freq_val = MIN_FREQ; if (freq_val > MAX_FREQ) freq_val = MAX_FREQ; freq = freq_val; calculate_timer_counts(); // 立即更新定时器 TR0 = 0; // 暂停定时器 if (wave_state) { TH0 = (0x10000 - low_count) >> 8; TL0 = (0x10000 - low_count) & 0xFF; } else { TH0 = (0x10000 - high_count) >> 8; TL0 = (0x10000 - high_count) & 0xFF; } TR0 = 1; // 重启定时器 EA = 1; // 开中断 } void main() { timer0_init(); set_frequency(1000); // 初始频率1kHz TR0 = 1; // 启动定时器0 while(1) { // 可以在这里添加频率调整逻辑 // set_frequency(新的频率值); } } |
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
【瑞萨RA6E2】瑞萨E2S软件安装过程,等待过程玩下97_e2 studio_ZGZZ
331 浏览 0 评论
532 浏览 0 评论
【原创】【RA4M2-SENSOR开发板评测】低功耗+USB综合测试
842 浏览 0 评论
1383 浏览 2 评论
824 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
16911 浏览 31 评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-3 07:40 , Processed in 0.533941 second(s), Total 42, Slave 35 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
4518