- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在为 AVR Atmega328p 微 Controller 编写代码。微 Controller 应该读取编码器并根据编码器的旋转递增或递减 r23。不幸的是,此时,无论我转动编码器的方向如何,输出只会下降到 0,然后从 255 开始。
我的代码相当简单,它基于结合了编码器先前状态和当前状态的表查找值。如果之前的状态和当前状态没有结合起来创建一个有效的回合,则会返回一个错误并且代码不执行任何操作。如果发生有效的状态更改,则通过 r24 将 1 或 -1 添加到 r23。
让微 Controller 读取编码器没有问题,但我不知道如何防止 r23 溢出。我的问题是当我打到 255 并加 1 时,寄存器溢出并变为 0。我不希望寄存器变为零;我希望它保持在 255,直到我以相反的方向旋转编码器。我对 0 有同样的问题。如果寄存器为 0 并且我添加 -1,我不希望寄存器转到 255,我希望它保持在 0,直到我以相反的方向旋转它。
我对跳出框框思考没有问题。如果您有解决方案或想法,请随时发布。
;**** A P P L I C A T I O N N O T E *************************************
;*
;* Title:
;* Version:
;* Last updated:
;* Target: AVR Dragon
;*
;*
;* DESCRIPTION
;*
;*.device ATmega328P @ 1M clock speed
;*
;* This is a simple program to test an optical encoder
;***************************************************************************
.include "m328Pdef.inc"
.org 0x0000
jmp RESET ;Reset Handle
.org 0x0008
jmp Interrupt1 ; PCINT1 Handler
enc_states:
.db 0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0
RESET:
;Setup stack pointer
ldi temp, low(RAMEND)
out SPL, temp
ldi temp, high(RAMEND)
out SPH, temp
//Set Port B pins to output
ser temp ; Set Register Rd <-- 0xff (output)
out DDRB,temp ; set all PORTB bits as output
//Clear analog input pins and enable pull ups on Pin 0 and 1 (Port C)
clr temp
out DDRC, temp ;all pins input
ldi temp, (1<<PC1)|(1<<PC0)
out PORTC,temp ;Enable pullups on Pin 0 and 1
//Set Port D pins to output
ser temp ; Set Register Rd <-- 0xff
out DDRD,temp ; set all PORTD bits as output
//Enable encoder pins interrupt sources (Encoder 1)
ldi temp, (1<<PCINT9)|(1<<PCINT8)
sts PCMSK1, temp
//Enable encoder pins interrupt sources (Encoder 2)
// ldi temp, (1<<PCINT11)|(1<<PCINT10)
// sts PCMSK1, temp
//Enable pin change interrupts
ldi temp, (1<<PCIE1)
sts PCICR, temp
//Enable global interrupts
sei
//Lookup table initial value
ldi ZL, 0x00 ;lookup table index and initial state
.def temp = r16
clr r25
clr r24
clr r23
loop:
out PORTB, r23
jmp loop
Interrupt1:
// Push SREG, etc
in r25, PORTC ;encoder value from PORTC
ldi ZH, High(enc_states*2) ; setup Z pointer hi
ldi ZL, Low (enc_states*2) ; setup Z pointer lo
rol r22 ;remember previous state and shift left twice
rol r22
cbr r25, 0xFC ;clear encoder bits 7:2
mov r21,r25
or r25, r22 ;combine encoder bits with old bits
cbr r25, 0xF0 ;clear bits 7:4 for table lookup
mov r22, r25 ;save table lookup value
mov ZL, r25 ;load index value into table
lpm r24, z ;get result
add r23,r24
// Pop SREG, etc.
reti
最佳答案
“饱和度”可以通过利用进位标志非常简单地完成,例如:
mov __tmp_reg__, r23
add __tmp_reg__, r24 ; do the addition
brcs saturated ; if the carry flag is set we have an overflow and should discard the result
mov r23, __tmp_reg__ ; there was no overflow so we store the result
saturated:
将 ISR 末尾的 add r23,r24
替换为上述代码,您应该没问题。 (显然,您可能需要将 __tmp_reg__
更改为可以用作临时存储的寄存器。)
考虑到 r24
可能是正数、负数或零,所有情况都可以通过稍微扩展上述原则来正确处理:
mov __tmp_reg__, r23
tst r24
breq doreturn ; if r24 == 0 we have nothing to do and may just return
brmi subtract ; if r24 is 'negative' we need to subtract
add __tmp_reg__, r24 ; if r24 is not negative we just add
rjmp store ; and go to where the result may be stored
subtract:
neg r24 ; r24 := -r24
sub __tmp_reg__, r24 ; do the subtraction
store:
brcs doreturn ; if the carry flag is set we have an overflow and should discard the result
mov r23, __tmp_reg__ ; there was no overflow so we store the result
doreturn:
仔细查看您的代码,在我看来,当 Z 指针的计算完成时,其中还有另一个“故障”:
ldi ZH, High(enc_states*2) ; setup Z pointer hi
ldi ZL, Low (enc_states*2) ; setup Z pointer lo
和
mov ZL, r25 ;load index value into table
看起来有问题:Z 地址的较低部分只是被忽略并被索引值覆盖。如果 Low (enc_states*2)
恰好不是 0
,这将导致麻烦;您可能需要执行 add ZL, r25
和 adc ZH, __zero_reg__
(16 位加法)而不是 mov ZL, r25
。
另一种可能降低日常工作复杂性的想法:
增量旋转编码器的输出可以解释为某种同步串行数据:一个输出(比如“A”)代表“时钟”信号,而另一个输出(“B”)代表“数据”信号。
您可以自由选择哪个输出用于哪个信号,以及您选择的“时钟”极性。算法就相当简单了:
在伪代码中,这看起来像:
bit lastClockState;
void readEncoder() {
bit currentClockState = readClockPin();
if ( lastClockState == 1 && currentClockState == 0 ) {
// A (falling) edge was detected...
// Get the direction of the rotation:
bit direction = readDataPin();
if ( direction == 1 ) {
value++;
} else {
value--;
}
}
lastClockState = currentClockState; // Update the lastClockState for the next iteration
}
例如,让它每 10 毫秒执行一次,您就已经拥有了一些“免费”的极简去抖动。
(顺便说一句,总结之前许多其他人的教训:不要尝试使用一些外部/引脚变化中断来检测任何机械开关或机械编码器产生的(未去抖动的)信号转换这很重要。机械元件的弹跳特性将确保它永远不会按预期工作。)
关于c - 旋转编码器防溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15235060/
...沮丧。我希望我的游戏仅在横向模式下运行。我已将适当的键/值添加到 Info.plist 文件中,以强制设备方向在启动时正确。 我现在正在尝试旋转 OpenGL 坐标空间以匹配设备的坐标空间。我正
我如何创建一个旋转矩阵,将 X 旋转 a,Y 旋转 b,Z 旋转 c? 我需要公式,除非您使用的是 ardor3d api 的函数/方法。 矩阵是这样设置的 xx, xy, xz, yx, yy, y
假设我有一个包含 3 个 vector 的类(一个用于位置,一个用于缩放,一个用于旋转)我可以使用它们生成一个变换矩阵,该矩阵表示对象在 3D 空间中的位置、旋转和大小。然后我添加对象之间的父/子关系
所以我只是在玩一个小的 javascript 游戏,构建一个 pacman 游戏。你可以在这里看到它:http://codepen.io/acha5066/pen/rOyaPW 不过我对旋转有疑问。你
在我的应用程序中,我有一个 MKMapView,其中显示了多个注释。 map 根据设备的航向旋转。要旋转 map ,请执行以下语句(由方法 locationManager 调用:didUpdateHe
使用此 jquery 插件时:http://code.google.com/p/jqueryrotate/wiki/Documentation我将图像旋转 90 度,无论哪个方向,它们最终都会变得模糊
我有以下代码:CSS: .wrapper { margin:80px auto; width:300px; border:none; } .square { widt
本篇介绍Manim中的两个旋转类的动画,名称差不多,分别是Rotate和Rotating。 Rotate类主要用于对图形对象进行指定角度、围绕特定点的精确旋转,适用于几何图形演示、物理模拟和机械运动
我只想通过小部件的轴移动图像并围绕小部件的中心旋转(就像任何数字绘画软件中的 Canvas ),但它围绕其左顶点旋转...... QPainter p(this); QTransform trans;
我需要先旋转图像,然后再将其加载到 Canvas 中。据我所知,我无法使用 canvas.rotate() 旋转它,因为它会旋转整个场景。 有没有好的JS方法来旋转图片? [不依赖于浏览器的方式] 最
我需要知道我的 Android 设备屏幕何时从一个横向旋转到另一个横向(rotation_90 到 rotation_270)。在我的 Android 服务中,我重新实现了 onConfigurati
**摘要:**本篇文章主要讲解Python调用OpenCV实现图像位移操作、旋转和翻转效果,包括四部分知识:图像缩放、图像旋转、图像翻转、图像平移。 本文分享自华为云社区《[Python图像处理] 六
我只是在玩MTKView中的模板设置;并且,我一直在尝试了解以下内容: 相机的默认位置。 使用MDLMesh和MTKMesh创建基元时的默认位置。 为什么轮换还涉及翻译。 相关代码: matrix_f
我正在尝试使用包 dendexend 创建一个树状图。它创建了非常好的 gg 树状图,但不幸的是,当你把它变成一个“圆圈”时,标签跟不上。我将在下面提供一个示例。 我的距离对象在这里:http://s
我想将一个完整的 ggplot 对象旋转 90°。 我不想使用 coord_flip因为这似乎会干扰 scale="free"和 space="free"使用刻面时。 例如: qplot(as.fac
我目前可以通过首先平移到轴心点然后执行旋转最后平移回原点来围绕轴心点旋转。在我的例子中,我很容易为肩膀做到这一点。但是,我不知道如何为前臂添加绕肘部的旋转。 我已经尝试了以下围绕肘部旋转的前臂: 平移
我想使用此功能旋转然后停止在特定点或角度。现在该元素只是旋转而不停止。代码如下: $(function() { var $elie = $("#bkgimg");
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 4 年前。 Improve this ques
我正在尝试创建一个非常简单的关键帧动画,其中图形通过给定的中点从一个角度旋转到另一个角度。 (目的是能够通过大于 180 度的 OBTUSE 弧角来制作旋转动画,而不是让动画“作弊”并走最短路线,即通
我需要旋转 NSView 实例的框架,使其宽度变为其高度,其高度变为其宽度。该 View 包含一个字符串,并且该字符串也被旋转,这一点很重要。 我查看了 NSView 的 setFrameRotati
我是一名优秀的程序员,十分优秀!