使用取反(CPL)实现的闪烁,随后给P0口赋值实现移动。
注;使用的是12MHZ频率,
带C循环做移动,使用一条跳转转移指令就可实现一直循环下去,延时为1.3s!
;蜂鸣器就使用哪种小的无源的有源的5v蜂鸣器都可以,经过试验发现用无源的效果更好,接在p1.2口,最好用一个三极管放大一下电流,晶振用12兆的.
实验的代码很简单。但是实际操作过程中还是遇到了以下问题:
要注意的是用C语言不大可能做出精确的延时效果,肯定会存在一定的误差!!!!
首先先来了解几个单片机的周期知识:
在这里,我把晶振的频率设置为跟自己设备一样,为12MHZ,所以机器周期为1?s。而整个程序的时间可以根据Keil的调试功能查看。
如图所示,在15行,16行位置设置了断点。图片左侧部分,可以找到“sec”这一项,这一项就是执行到这步所需要的时间,然后可以根据时间差计算延时的时间。
这里可以看到执行到15行的时间为0.s
执行到16行的时候时间为0.s,所以执行P0=0x00的时间为2?s,即两个机器周期,因为这里用的是立即数寻址,取值一周期,执行一周期。
执行到19行的时间为0.s,所以执行delay(45)这句代码的时间为0.978535s,接近1s,所以说是存在误差的。但是对于实验效果来说,也已经够了。
最重要的还有一点就是,经过自己实验,不同的类型符号所需要的时间也是不一样的,比如我采用无符号整形,所需时间就是3.7s,所以差别还是很大的。
不过总结来说,还是应该遵循一些简单的原则:
另外的话,在这里也把汇编的延时程序放出来。同样的,也是先来看用来实现这个目标的代码。
其中DJNZ是减一不为零转移指令。有两个参数,第一个是被减数,第二个是转移的地址编号。
还有一点要注意的就是MOV指令时单周期指令,DJNZ是双周期指令。
执行到MOV指令时的时间为0.s
执行到12行时,时间为0.s,所以执行MOV P0,#00H这句语句的时间为2?s,同样的是因为采用了立即数寻址。
可以看到延时程序的消耗时间大约为1s,计算分析过程:
所以采用汇编编写延时程序明显比C语言准确的多,当然也不是完全正确,还是有很小的误差,准确的延时应该用定时器来设计。
intrins.h头文件内部函数描述:
(1)循环移位用法如上代码。
功能:即空指令。什么都不做,但是占用一个指令的时间。
功能:产生一个JBC 指令,该函数测试一个位,当置位时返回1,否则返回0。如果该位置为1,则将该位复位为0。8051 的JBC 指令即用作此目的。
_testbit_只能用于可直接寻址的位;在表达式中使用是不允许的。