基于C语言的编码器(光耦)编程之C代码解析(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_22520215/article/details/82971854

对于光耦编码器的原理,请参考上面的文章《基于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;
	}
}

以上代码完成后,在main初始化阶段调用void OptoKnob_ParaInit(void)函数,大概500us一次调用void OptoKnob_ServiceAll(void)就可以了,建议不要太久,500us到1ms之间差不多了。

猜你喜欢

转载自blog.csdn.net/qq_22520215/article/details/82971854