打印

还有比这更精简的编码开关程序吗?

[复制链接]
7675|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
enum phase_status{
    phase_no_move= 0,
    phase_dec,
phase_inc,     
    phase_bad
};

u8 volatile PhaseShift;
const u8 table_Phase[16]=
{
phase_no_move,phase_dec,phase_inc,phase_bad,
phase_inc,phase_no_move,phase_bad,phase_dec,
phase_dec,phase_bad,phase_no_move,phase_inc,
phase_bad,phase_inc,phase_dec,phase_no_move,
};

U8 whell_scan(void)
{
static s8 PhaseCount = 0;
PhaseShift <<= 2;
if((REG32(P4SIN) & (1<<3)))  PhaseShift |= 0x01;
if((REG32(P1SIN) & (1<<2)))  PhaseShift |= 0x02;
PhaseShift &= 0x0f;
if(table_Phase[PhaseShift] == phase_inc) PhaseCount++;
if(table_Phase[PhaseShift] == phase_dec) PhaseCount--;
if(PhaseCount > 3)
{
  PhaseCount -= 4;
   return phase_inc;
}
else if(PhaseCount < -3)
{
  PhaseCount += 4;
   return phase_dec;
}
return phase_no_move;
}

去抖都完成了,这个编码开关的程序,一直没有看懂。
请教各位怎么理解这个程序

相关帖子

来自 2楼
lxyppc| | 2009-10-30 09:21 | 只看该作者
本帖最后由 lxyppc 于 2009-10-30 09:51 编辑
 
/**
  不妨设旋转编码器的输出波形如下
                 ______        ______        ______        ______
正转时:  A相   __|      |______|      |______|      |______|   
                      ______        ______        ______        ___
         B相   ______|      |______|      |______|      |______|   
低位为A相         01  11 10  00 01  11 10  00 01  11 10  00 01  11
                     ______        ______        ______        ______
反转时:  A相   ______|      |______|      |______|      |______|   
                  ______        ______        ______        ___
         B相   __|      |______|      |______|      |______|   
低位为A相         10 11  01  00 10  11 01  00 10  11 01  00 10  11
A相接在某端口上,对应检测代码为 if((REG32(P4SIN) & (1<<3)))  PhaseShift |= 0x01;
B相接在某端口上,对应检测代码为 if((REG32(P1SIN) & (1<<2)))  PhaseShift |= 0x02;
PhaseShift的<1:0>两位表示当前AB两相的状态,<3:2>两位表示上一次AB两相的状态
正转时,AB相变化顺序为   01->11->10->00->01    低位为A相
因此正转时,PhaseShift的低四位值为 0111 1110 1000 0001
反转时,AB相变化顺序为   10->11->01->00->10    低位为A相
因此反转时,PhaseShift的低四位值为 1011 1101 0100 0010
*/
/* 假设正转为减,反转为加,则可得如下一表 */
const u8 table_Phase[16]=
{
  phase_no_move,    // 0000 未转动
  phase_dec,        // 0001 正转
  phase_inc,        // 0010 反转
  phase_bad,        // 0011 不可能
  phase_inc,        // 0100 反转
  phase_no_move,    // 0101 未转动
  phase_bad,        // 0110 不可能
  phase_dec,        // 0111 正转
  phase_dec,        // 1000 正转
  phase_bad,        // 1001 不可能
  phase_no_move,    // 1010 未转动
  phase_inc,        // 1011 反转
  phase_bad,        // 1100 不可能
  phase_inc,        // 1101 反转
  phase_dec,        // 1110 正转
  phase_no_move,    // 1111 未转动
};
/* 根据PhaseShift的低四位值来查此表即可得转动方向 */
PhaseShift &= 0x0f;
if(table_Phase[PhaseShift] == phase_inc) PhaseCount++;
if(table_Phase[PhaseShift] == phase_dec) PhaseCount--;
/* 当同一方向上的转动次数为4次时,才认为是一次有效的转动,达到了去抖的目的 */
if(PhaseCount > 3)
{
  PhaseCount -= 4;
   return phase_inc;
}
else if(PhaseCount < -3)
{
  PhaseCount += 4;
   return phase_dec;
}

使用特权

评论回复
来自 3楼
ZRL700424| | 2009-10-31 10:42 | 只看该作者
本帖最后由 ZRL700424 于 2009-10-31 10:48 编辑

还是来个流程图吧
和普通的按键扫描一样调用,但周期不能太长,否则会丢脉冲

流程图.GIF (10.97 KB )

流程图.GIF

使用特权

评论回复
地板
ppsen| | 2009-10-30 10:04 | 只看该作者
通过计数去斗程序,怎么啦了

使用特权

评论回复
5
inter_zhou|  楼主 | 2009-10-30 12:54 | 只看该作者
感谢2楼 lxyppc
分析得很详细,精辟!

使用特权

评论回复
6
mcufan001| | 2009-10-30 16:13 | 只看该作者
呵呵,典型的简单问题复杂化!又去抖又分析4种状态!为什么不能在A的上升沿判断B的状态呢.......他们只是有个相位差

使用特权

评论回复
7
ZRL700424| | 2009-10-30 17:28 | 只看该作者
呵呵,典型的简单问题复杂化!又去抖又分析4种状态!为什么不能在A的上升沿判断B的状态呢.......他们只是有个相位差
mcufan001 发表于 2009-10-30 16:13


是的,用不了几条指令

使用特权

评论回复
8
inter_zhou|  楼主 | 2009-10-30 17:30 | 只看该作者
楼上的口气未免太过牵强了!

你如果采用其他思路,写出可移植性更好更精简的程序算我服了你。
为什么不能在A的上升沿判断B的状态呢.......他们只是有个相位差?


1,就算是在A的上升沿判断B,那也需要去抖!
2,你的程序可移植性为多少? 基本为0。并非所有的单片机都有那么大把的资源能让你恰好在A上升沿的时候能够检测B。(并非所有MCU都有上升沿中断)

使用特权

评论回复
9
lxyppc| | 2009-10-30 17:31 | 只看该作者
本帖最后由 lxyppc 于 2009-10-30 17:32 编辑

to 5楼,6楼
如果用带编码器接口的芯片,写再少的代码我觉得都是多余的
如果用连中断都没有的芯片,不知道还有没有更好的方法

使用特权

评论回复
10
ZRL700424| | 2009-10-31 10:15 | 只看该作者
TO:7楼
你检测普通的按键一定需要上升沿或者下降沿中断吗?如果答案是肯定的,那我无话可说了

这个和检测普通的按键没有本质区别,只是:1,编码开关扫描的速度要快些;2,需要同时判断两个口。(假设编码开关接上拉:两个都为高时相当于没有按键,两个都为低时相当于按键没有释放,一高一低时处理:第一个开关为高时--顺时针,否则逆时针)

使用特权

评论回复
11
ZRL700424| | 2009-10-31 10:20 | 只看该作者
2,你的程序可移植性为多少? 基本为0。

我用过的单片机不下7、8种了(包括没有中断的PIC16C54),90%用汇编,如果用到编码开关都是用的相同的程序(只是把指令一条一条地换成相应的指令而已),如果是用C的话,程序一个字符都不用改,只是在IO口定义时修改相应的端口

不知道这样算不算可移植

使用特权

评论回复
12
ZRL700424| | 2009-11-9 17:14 | 只看该作者
楼主哪去了?

使用特权

评论回复
13
icmap| | 2009-11-9 20:19 | 只看该作者
还有更简单的方法,只需建立一个4字节的表格即可。

使用特权

评论回复
14
inter_zhou|  楼主 | 2009-11-10 11:28 | 只看该作者
请教楼上更简单的方法!

使用特权

评论回复
15
BLUE2008| | 2009-11-11 22:07 | 只看该作者
不知道采用单纯的查表是否会有很大的问题呢?

使用特权

评论回复
16
bmw0028| | 2011-12-27 11:12 | 只看该作者
1# inter_zhou


学习 一下 谢谢分享

使用特权

评论回复
17
wangjun403| | 2011-12-27 17:25 | 只看该作者
mark

使用特权

评论回复
18
hificwc| | 2011-12-27 18:55 | 只看该作者
不错,收藏

使用特权

评论回复
19
维修超人| | 2016-8-3 10:09 | 只看该作者
哦,好复杂,确实有更简单的,定时查询就可以了。不用外部中断,不用什么查表(不理解为什么要查表,显得高级一点?)。

使用特权

评论回复
20
冬瓜le| | 2019-3-7 22:54 | 只看该作者
啊,我是菜鸟,觉得去抖原理好复杂

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

272

帖子

0

粉丝