逐飞科技对于STC8H1K系列的单片机正交解码的资料以及相关实验

■ 背景介绍


使用STC8H1K的高级PWM的正交编码器计数方式 实验中,开始对于基于STC8H1K28单片机的高级PWM功能对于正交编码信号进行计数解调的过程中,通过对于STC8H1K28单片机的数据手册相关内容阅读,并进行实验,最终没有能够获得相应的结果。

今天(2020-7-15)收到了来自于逐飞科技 给出的范例(他们的合伙人叫做范兵,感谢他们的帮助),通过实验来验证一下相应的范例的效果。

01.STC8H系列正交解码示例


1.背景简介

受STC委托,本文意在分享使用STC8H系列单片机的增强型PWM模块实现正交解码功能,以进一步实现对正交编码信号输出的编码器进行双向速度测量。
硬件平台:逐飞STC8H8K 64脚核心板+逐飞1024线mini正交编码器**
编译环境:keil V9.60
上位机:串口助手
演示视频BiliBili

2.原理分析

逐飞科技 之前的开源库中我们可以了解到,开源库里没有正交解码例程,主要原因是因为STC8H只有两个PWM模块,假如我们推荐使用正交编码编码器,就意味着一个编码器就需要占用一个PWM模块,然而今年节能组要求制作平衡小车,就意味着有两个电机,这样就需要两个编码器,那么单片机的两个PWM模块就会都被占用,然而小车的电机控制也需要PWM功能,所以并没有推荐大家用PWM模块来实现正交解码,而是推荐大家使用带方向输出的编码器,这样PWM模块就可以留给电机使用。

当然也可以有另一种设想,使用一个PWM模块去实现对一个正交编码的编码器进行测速,另一个电机使用带方向信号的编码器,用普通定时器去捕获脉冲,这种方案是可行的,但没必要这么麻烦。

还有一点需要注意,使用PWM模块计数和使用定时器模块捕获脉冲计数的方式是不一样的。PWM模块去捕获编码器数据是通过边沿计数,也就是说这个模块的是在发生上升沿或者下降沿的时候都会计数,而定时器捕获脉冲,是获取高低电平翻转的次数。这里我们通过实验就会发现,用同一个的正交编码编码器转动360°,PWM模块采集编码器数据是定时器捕获脉冲数据的两倍,但这个数据并不是精度变高,只是单片机的计数方式导致了结果翻倍。

3.实现程序

下面是使用STC8H8K64x采集正交编码信号输出编码器的示例程序:

#include "headfile.h"
int16 encoder_data;
//-------------------------------------------------------------------
// @brief PWM1模块正交解码初始化
// @param void
// @return void
// @since v1.0
// Sample usage: pwm1_encoder_init(); //初始化正交解码
// @note
//-------------------------------------------------------------------
void pwm1_encoder_init(void)

{
	P_SW2 |= 1<<7; //使能访问 XFR
	PWM1_ARR = 0xFFFF; //设置自动重装载值,当自动重装载的值为0时,计数器不工作。
	PWM1_CCMR1 |= 1<<0; //IC1 映射在 TI1FP1 上,即使用P10引脚获取方向
	PWM1_CCMR2 |= 1<<0; //IC2 映射在 TI2FP2 上,即使用P22引脚捕获边沿跳
	PWM1_SMCR |= 1<<0; //编码器模式 1 根据 TI1FP1 的电平,计数器在TI2FP2的边沿向上/下计数
	PWM1_CR1 |= 1<<0; //使能PWM1计数器
	PWM1_PS |= 1<<2; //PWM1的通道1使用P10,PWM2的通道2使用P22。
}
//-------------------------------------------------------------------
// @brief PWM1模块获取正交解码数值
// @param void
// @return void
// @since v1.0
// Sample usage: encoder_data = pwm1_get_encoder(); //获取正交解码数值
// @note
//-------------------------------------------------------------------
int16 pwm1_get_encoder(void)
{
	int16 res;
	res = PWM1_CNTR; //保存当前计数器的值
	PWM1_CNTR = 0; //清空计数器
	return res;
}
//-------------------------------------------------------------------
// @brief 定时器0 5ms中断服务函数
// @param void
// @return void
// @since v1.0
// Sample usage:
// @note
//-------------------------------------------------------------------
void TM0_Isr() interrupt 1
{
	encoder_data = pwm1_get_encoder(); //获取正交解码编码器数值
}
void main()
{
	DisableGlobalIRQ(); //关闭总中断
	board_init(); //初始化内部寄存器,勿删除此句代码。
	pit_timer_ms(TIM_0, 5); //初始化定时器,5ms执行一次
	pwm1_encoder_init(); //PWM1模块初始化为正交解码功能
	EnableGlobalIRQ(); //开启总中断
	while(1)
	{
		delay_ms(100); //每100ms输出一次打印信息
		printf("encoder_data = %d \r\n" ,encoder_data); //串口1打印编码器数据
	}
}

4.视频说明

我们将编写好的例程编译,然后下载到单片机,打开串口助手接收单片机的打印数据,旋转编码器观察数据变化,我们发现当编码器不旋转时输出数据为0,当编码器朝不同方向旋转时可以输出正负两种数值,旋转越快,数值的绝对值越大,正负用来表示两个旋转方向,其中哪个方向为正,哪个方向为负是可以自己定义的。

同时我们从程序示例中也看到打印数据是100ms一次,而数据采集是5ms一次,所以打印出来的数据相当于是间断的,同时因为编码器是1024线的高精度,所以观察到数据变化比较大,但如果是使用电机空载固定PWM占空比驱动,可以看到编码器的数据输出是十分稳定的。

5.串口助手接收数据截图

下面左图是正交编码的编码器顺时针旋转且角速度逐渐增大的数据,右图是正交编码的编码器逆时针旋转且角速度逐渐增大时的数据:

02实验测试


1.基本方案

依然使用 使用STC8H1K的高级PWM的正交编码器计数方式 中的方法和程序,对于PWM1的初始化进行修改。

▲ 实验电路

▲ 实验电路

重新设置EncodeInit()函数。对比 上次实验过程 的初始化部分,主要在PWM1_PS的设置,PWM1_SMCR的模式设置上出现了问题。

//------------------------------------------------------------------------------
#if ENCODER_EN
void EncoderInit(void) {
    _push_(P_SW2);
    P_SW2 = 0x80;                           // Enable to access XFR
    //--------------------------------------------------------------------------
    PWM1_ARR = 0xffff;                      // Auroreload register value must not be 0
    PWM1_CCMR1 |= 1 << 0;                   // IC1 map to TI1FP1, P2.0 as the direction 
    PWM1_CCMR2 |= 1 << 0;                   // I2C map to I2FP2 
    PWM1_SMCR |= 1<<0;                      // Encoder Mode 1
    PWM1_CR1 |= 1<<0;                       // Enable PWM1
    PWM1_PS |= 0x5;                         // PWM1 Channel1 using P2.0, PWM2 Channel2 using P2.2
    
    //==========================================================================
    
    //--------------------------------------------------------------------------
    
    _pop_(P_SW2);
}

2.测试结果

使用在实验 两款旋转编码器测量LDP3806,BH60 中的LPD3806-400BW-5G编码器输出两路正交脉冲波形,施加在STC8H1K28的P2.0,P2.2输入管脚。
通过软件周期显示读取的 PWM1_CNTRH,PWM1_CNTRL的数值。

▲ 测试所使用的旋转编码器输出正交脉冲

▲ 测试所使用的旋转编码器输出正交脉冲

int EncoderRead(void) {
    unsigned int nNumber;
    
    _push_(P_SW2);
    P_SW2 = 0x80;

    nNumber = PWM1_CNTRH;
    nNumber = (nNumber << 8) + PWM1_CNTRL;
    
    _pop_(P_SW2);
    
    return (int)nNumber;
}

通过不断显示读出的结果,可以看到PWM的寄存器能够正确的反映出编码器旋转的方向和大小。

▲ 旋转编码器与读出的结果

▲ 旋转编码器与读出的结果

※ 结论


本文参照来自于 逐飞科技 给出的PWM高级编码器设置代码,初步实验了使用STC8H1K28读取正交编码的功能。

对于编码的数值与脉冲个数之间的精确关系,将会通过之后的应用试验来进行验证。

猜你喜欢

转载自blog.csdn.net/zhuoqingjoking97298/article/details/107381003