对于光耦编码器的原理,请参考上面的文章《基于C语言的编码器(光耦)编程之编码器原理(一)》,点击地址!!
代码需要一个.c文档和一个.h文档。
.h文档主要配置编码器相关参数
#define OptoKnobNumber 2 /* 旋钮个数配置 */
#define _01_SHIFT_BIT_ 0x01 /* 移动位数值 */
#define _02_SHIFT_BIT_ 0x02 /* 移动位数值 */
#define _01_GET_BIT_ 0x01 /* 获取位数值 */
#define _034b_OptoKnob_CW_WAVE_ 0x034b /*11 01 00 10 11 正向旋转波形*/
#define _0387_OptoKnob_CCW_WAVE_ 0x0387 /*11 10 00 01 11 反向旋转波形*/
#define _3f_Knob_MaxValue_ 0x3f /* 最大档位配置 */
#define _00_Knob_MinValue_ 0x00 /* 最小档位配置 */
/* 旋钮名称配置 */
enum Opto_name
{
optoname_AC = 0,
optoname_WIND = 1,
};
/* 旋钮参数结构体配置 */
typedef struct
{
enum Opto_name name;
uint16 OptoE1_Value; /* E1脚电平缓存字节 */
uint16 OptoE2_Value; /* E2脚电平缓存字节*/
uint16 OptoGroup_PreValue; /* 当前E1、E2脚电平组合缓存字节*/
uint16 OptoGroup_OldValue; /* 上一次E1、E2脚电平组合缓存字节*/
uint16 OptoShift_Value; /* 多次E1、E2脚电平组合缓存字节 */
sint8 Opto_Value; /* 旋钮档位字节 */
uint8 Opto_Sync; /* 旋钮同步字节 */
}Opto_Struct;
.c文档主要设计相关函数
1、初始化旋钮结构体函数void OptoKnob_ParaInit(void);
void OptoKnob_ParaInit(void)
{
enum Opto_name Opto_id;
for(Opto_id = 0u; Opto_id < OptoKnobNumber; Opto_id++)
{
OptoKnob_Struct[Opto_id].name = Opto_id;
OptoKnob_Struct[Opto_id].OptoE1_Value = 0x0000;
OptoKnob_Struct[Opto_id].OptoE2_Value = 0x0000;
OptoKnob_Struct[Opto_id].OptoGroup_PreValue = 0x0000;
OptoKnob_Struct[Opto_id].OptoGroup_OldValue = 0x0000;
OptoKnob_Struct[Opto_id].OptoShift_Value = 0x0000;
OptoKnob_Struct[Opto_id].Opto_Value = 0x00;
OptoKnob_Struct[Opto_id].Opto_Sync = 0x00;
}
}
2、所有旋钮服务函数void OptoKnob_ServiceAll(void);
void OptoKnob_ServiceAll(void)
{
enum Opto_name Opto_id;
for(Opto_id = 0u; Opto_id < OptoKnobNumber; Opto_id++)
{
OptoKnob_Service(Opto_id);
}
}
3、单个旋钮处理函数static void OptoKnob_Service(enum Opto_name name);
static void OptoKnob_Service(enum Opto_name name)
{
Opto_Struct* StructP = &OptoKnob_Struct[name];
StructP->OptoE1_Value <<= _01_SHIFT_BIT_; /* 产生最低位缓存当前E1电平 */
StructP->OptoE2_Value <<= _01_SHIFT_BIT_; /* 产生最低位缓存当前E2电平 */
OptoKnob_GetPort[StructP->name](StructP); /* 获取电平值*/
/* 组合E1、E2电平 E1、E2的前后关系会影响旋钮转动的波形序列 这里注意一下*/
StructP->OptoGroup_PreValue = ((StructP->OptoE1_Value&0x01)<<_01_GET_BIT_ ) | (StructP->OptoE2_Value&_01_GET_BIT_ );
/* 电平组合发生改变 */
if(StructP->OptoGroup_PreValue != StructP->OptoGroup_OldValue)
{
/* 上一次电平组合更新为当前的电平组合*/
StructP->OptoGroup_OldValue = StructP->OptoGroup_PreValue;
/* 记录电平组合序列 */
StructP->OptoShift_Value |= StructP->OptoGroup_PreValue;
switch(StructP->OptoShift_Value & 0x03ff) /* 取10位数据 */
{
case _034b_OptoKnob_CW_WAVE_:
StructP->Opto_Value++;
if(StructP->Opto_Value > _3f_Knob_MaxValue_ )
{
StructP->Opto_Value = _00_Knob_MinValue_;
}
StructP->Opto_Sync = 1;
break;
case _0387_OptoKnob_CCW_WAVE_:
StructP->Opto_Value--;
if(StructP->Opto_Value < _00_Knob_MinValue_)
{
StructP->Opto_Value = _3f_Knob_MaxValue_;
}
StructP->Opto_Sync = 1;
break;
default:
break;
}
/* 产生最低2位记录下一次改变电平组合 */
StructP->OptoShift_Value <<= _02_SHIFT_BIT_;
}
}
4、电平获取函数 static void OptoKnob_AC(Opto_Struct* Knob); static void OptoKnob_WIND(Opto_Struct* Knob);
/*这段代码看不懂就算了,我为了方便才这么做,这代码就是多个旋钮时的选择函数,总之这些函数功能就是获取2个端口的电平值,你自己写个可以返回端口电平的函数就可以了*/
static void OptoKnob_AC(Opto_Struct* Knob);
static void OptoKnob_WIND(Opto_Struct* Knob);
typedef void (*OptoKnob_getport)(Opto_Struct*);
OptoKnob_getport OptoKnob_GetPort[]=
{
OptoKnob_AC,
OptoKnob_WIND,
};
static void OptoKnob_AC(Opto_Struct* StructP)
{
if(((P1&BIT7) >> 7) != 0x00)
{
StructP->OptoE1_Value |= 0x01;
}
else
{
StructP->OptoE1_Value &= ~0x01;
}
if(((P1&BIT6) >> 6) != 0x00)
{
StructP->OptoE2_Value |= 0x01;
}
else
{
StructP->OptoE2_Value &= ~0x01;
}
}
static void OptoKnob_WIND(Opto_Struct* StructP)
{
if(((P9&BIT6) >> 6) != 0x00)
{
StructP->OptoE1_Value |= 0x01;
}
else
{
StructP->OptoE1_Value &= ~0x01;
}
if(((P9&BIT4) >> 4) != 0x00)
{
StructP->OptoE2_Value |= 0x01;
}
else
{
StructP->OptoE2_Value &= ~0x01;
}
}