爱折腾的孩纸

旋转编码器解码程序(查表法)

查表法,AVR 单片机

#define  ROTARY_STOP  0
#define  ROTARY_CW    1
#define  ROTARY_CCW  -1

#define  ROTARY_MODE_HALF  0
#define  ROTARY_MODE_FULL  1
#define  ROTARY_MODE  ROTARY_MODE_HALF
uint8_t _rotary_stats;

const char _rotary_value_table[16] PROGMEM = {
	ROTARY_STOP,  // 00: 00 -> 00
	ROTARY_CW,    // 01: 01 -> 00
	ROTARY_CCW,   // 02: 10 -> 00
	ROTARY_STOP,  // 03: 11 -> 00
#if ROTARY_MODE == ROTARY_MODE_HALF
	ROTARY_STOP,  // 04: 00 -> 01
	ROTARY_STOP,  // 05: 01 -> 01
	ROTARY_STOP,  // 06: 10 -> 01
	ROTARY_STOP,  // 07: 11 -> 01
	ROTARY_STOP,  // 08: 00 -> 10
	ROTARY_STOP,  // 09: 01 -> 10
	ROTARY_STOP,  // 10: 10 -> 10
	ROTARY_STOP,  // 11: 11 -> 10	
#else
	ROTARY_CCW,   // 04: 00 -> 01
	ROTARY_STOP,  // 05: 01 -> 01
	ROTARY_STOP,  // 06: 10 -> 01
	ROTARY_CW,    // 07: 11 -> 01
	ROTARY_CW,    // 08: 00 -> 10
	ROTARY_STOP,  // 09: 01 -> 10
	ROTARY_STOP,  // 10: 10 -> 10
	ROTARY_CCW,   // 11: 11 -> 10
#endif
	ROTARY_STOP,  // 12: 00 -> 11#
	ROTARY_CCW,   // 13: 01 -> 11
	ROTARY_CW,    // 14: 10 -> 11
	ROTARY_STOP   // 15: 11 -> 11
};

char read_rotary() {
	char rtnval;
	// 0000aabb
	// aa: current stats
	// bb: last stats
	if (_READ_PIN(ROTARY_HW_A)) _rotary_stats |= 0x04;
	if (_READ_PIN(ROTARY_HW_B)) _rotary_stats |= 0x08;
	rtnval = pgm_read_byte(_rotary_value_table + _rotary_stats);
	_rotary_stats = _rotary_stats >> 2;
	return rtnval;
}

解读:

  1. read_rotary 函数中,_READ_PIN 宏用于读取 IO 状态,并将当前状态保存于 _rotary_stats 变量的第 2、3 位
  2. 此时 _rotary_stats 变量第 2、3 位为当前状态,第 1、0 位为上次检查状态,这 4 位共同作为索引进行查表
  3. 表的编制:上次状态与当前状态共有 16 种组合,分别对应 16 个索引,每个索引值对应一种状态变化过程,根据正交编码原理,可以得知对应的动作,据此打表
  4. 查表后,将当前 _rotary_stats 右移 2 位,待下次进入 read_rotary 后,当前状态已变为上次状态。

评论