我的硬件目前有四组传感器,我将其视为四个独立的串行端口,接收功能仅启用连接到端口0的低4位。我已多次尝试检索正确的串行端口数据(通过瞄准lazer直接在传感器上)没有成功。然后我研究了为了获得更高的可靠性,在标准UART上,每个位以16x秒的速度进行采样(我在https://www.allaboutcircuits.com/technical-articles/back-to-basics-the-universal-asynchronous-receiver-transmitter-uart/的页面上找到了这个3/4)。
所以我最终推出了我自己的版本,但由于我的时间安排,我的计数更像是32x秒,但没关系。
我将首先解释我的所作所为,以便每个人都了解正在发生的事情。
代码说明
我有四个连续的地址位置设置为指向每个位的计数器值。从硬件同时读取4位,并且该位的计数器根据该位是设置(在该组传感器上检测到的光)还是清除(未检测到光)而上升或下降。此循环以大约9600bps的速度频繁执行。
第二个循环仅在需要值时执行。这种情况每16次执行一次,最后一次循环执行(更像是600bps的速度)。它将每个位的计数器值视为有符号数,并使用MSB值作为该位的最终值。那些MSB值被挤在一起形成从传感器读取的官方位。
这种方法是否可以可靠地确定位值是设置还是清除?
我可以以某种方式重做此代码,以便进程运行得更快吗?因为每个循环消耗大量的时钟周期(32到40),如果我可以将它降低到大约20个时钟周期,我会很高兴。
此外,此代码在AT89S52微控制器上执行,因此我使用其扩展内存地址。
代码
;memory is preinitialized to nulls
LAZMAJ equ 0E0h ;majority counters start address (end address at 0E4h)
MAJT equ 20h ;Majority value at bit address
mov A,P0 ;get bit values from hardware
mov R1,#LAZMAJ ;go to start of pointer
;loop uses 40 clock cycles out of 192 available
countmaj:
rrc A ;get bit
jnc noincmaj
inc @R1 ;bit is set so add 1 to counter for that bit
noincmaj:
jc incmaj
dec @R1 ;bit is clear so subtract 1 from counter for that bit
incmaj:
inc R1 ;move pointer to next bit
cjne R1,#LAZMAJ+4,countmaj ;see if pointer is out of range
;it is so end loop
;loop uses about 32 clock cycles and executes when we want data
mov R1,#LAZMAJ+4 ;go to out of range position
chkmaj:
dec R1 ;decrement pointer first so we are within range
mov MAJT,@R1 ;load value to majority variable. treat it as signed
mov @R1,#0h ;clear value from memory space
mov C,MAJT.7 ;Take sign and use that as carry
rlc A ;and put it into our final variable
cjne R1,#LAZMAJ,chkmaj ;if pointer isn't in first address then keep going
;otherwise exit loop and A=value we want