逐飞科技对于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打印编码器数据
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
通过不断显示读出的结果,可以看到PWM的寄存器能够正确的反映出编码器旋转的方向和大小。
▲ 旋转编码器与读出的结果
※ 结论
本文参照来自于 逐飞科技 给出的PWM高级编码器设置代码,初步实验了使用STC8H1K28读取正交编码的功能。
对于编码的数值与脉冲个数之间的精确关系,将会通过之后的应用试验来进行验证。
文章来源: zhuoqing.blog.csdn.net,作者:卓晴,版权归原作者所有,如需转载,请联系作者。
原文链接:zhuoqing.blog.csdn.net/article/details/107381003
- 点赞
- 收藏
- 关注作者
评论(0)