关于KeilC51仿真中由于不认真造成的小问题

文章讲述了作者在使用C51单片机编写定时器1PWM代码时,由于TMOD配置错误,导致实际频率计算错误,最终发现是由于少写了一个H,使得定时器工作在模式0而非预期的模式1,引发的频率偏差和误导。作者借此强调编程时的细心和准确性的重要性。
摘要由CSDN通过智能技术生成

起因

首先说明,这篇文章可能没什么营养,如果读者不希望浪费时间,可以直接跳到结果看看发生了什么,直接看结果也可以看明白的。

由于课程作业要求用汇编语言写,就尝试使用C51单片机,用汇编语言来写,然后测试看看代码有无问题,题目是这样的:

要求使用定时计数器1的定时功能实现一个PWM的输出,周期为100ms,占空比为20%,P1.0输出,P1.1输出它的反相波形。

代码思路不难,定时器1工作在定时功能,计数机器周期,也就是1MHz(后文会提到这个值怎么得来),也就是1us,此时计数值设置成1000,也就是重装载值为2^16 – 1000 = 64536,也就是FC1BH,得到初始计数值。

先把这个逻辑用汇编语言实现一下:

;思路就是拉高20个中断,在拉低80个中断,这样只需要两个跳转就能实现功能了
;还需要一个寄存器来记录一下P1口的状态
ORG  0000H
		AJMP MAIN
ORG  001BH	;T1中断服务程序
		MOV	 TH1,#0FCH
		MOV	 TL1,#01BH
		SUBB A,#01H
		RETI
		
MAIN: 	MOV  SP,#60H	;堆栈指针位置
		MOV  TMOD,#10
		MOV	 TH1,#0FCH
		MOV	 TL1,#01BH
		MOV  P1,#0FDH
		MOV  R0,#01H	;先把R0置1,表示高电平
		MOV	 A,#14H		;先用20ms,表示高电平时间
		SETB TR1	 	;启动T1计数
		SETB ET1		;允许T1中断
		SETB EA			;打开CPU中断
L1:		JZ	 A0			;如果A中的值变成0了,说明需要翻转IO口
		AJMP L1			;不是0,则循环检测A的值
A0:		DJNZ R0,OUT2	;检测R0的值,如果是1就跳转到OUT1,否则跳转到OUT2,注意这条指令完成后R0的值被减1
		AJMP OUT1
OUT1:	MOV  R0,#00H	;修改R0的值,下次跳转进入OUT2
		MOV  A,#14H		;
		MOV  P1,#0FDH
		AJMP L1			;返回主程序
OUT2:	MOV  R0,#01H
		MOV  A,#50H		;这里赋值80,表示低电平持续时间80ms
		MOV  P1,#0FEH
		AJMP L1			;返回主程序

		END

然后仿真,利用keil的逻辑分析仪查看周期,发现不是100ms,一开始我以为是中断函数中其他语句影响了时间,后来发现并不是,波形如下:

可以发现一个周期是10.19367ms,也就是说跟100ms差的很远,此时我们计算一下定时器的中断频率:100*1000/10.19367,忽略掉误差大概在10MHz,然后经过不断尝试,发现定时器频率其实是8MHz,我们给计数8000,也就是65535-8000 = 57535,也就是E0BFH:

现在达到目的了,但是问题还没有解决,因为从理论上来说,定时器频率使用的是机器周期,是振荡器频率的1/12,此时我给的振荡器频率是12MHz,也就是晶振频率,由此计算得到的定时器频率应该是1MHz,我以为是我的keil哪里设置有问题,于是打开proteus顺手搭了个基本电路测试一下:

到这里来测量一下高电平的宽度:

可以发现高电平时间确实是20ms,也就是说定时器频率确实是8MHz,这就奇怪了……

结果

找了好久也没有讲这个是为什么,当我正要放弃的时候,想着要不看看T0怎么样,结果正打算改TMOD的时候,发现赋值TMOD的时候少写了个H,真离谱,找半天,看来敲代码还是要认真……

理论上看一下少写H会发生什么(唉,被迫复习知识),原本想表达的是0x10,结果变成了0x0A,也就是定时器1工作在模式0,诶,这个时候是13位计数器,也就是TL高三位应该没有用,我给的初值是0xE0BF,一定要注意这里是第八位的高三位没用,也就是第八位满32进1,这时候相当于低五位初值为全1,高八位是E0,计数值就是1E * 32 + 1 = 961,怪不得此时相当于1us,已经很接近1000了,这就造成了8MHz的错觉……

我不知道世界上会不会有第二个人遇到这个问题并且恰好能得出8MHz这个数字,反正我就是按照比例在计算了一番,算出了这个数字,然后就被误导进去了。所以以后敲代码还是要认真一些,不然费时费力。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值