logo
 
首页-> 应用方案
8位单片机应用方案
16位单片机应用方案
SPMC75增量编码器接口应用
文章来源:凌阳单片机推广中心  发布时间:2006-2-23 14:41:13

摘  要:增量式编码器是直接利用光电转换原理输出三组方波脉冲A、B和Z相;A、B两组脉冲相位差90o,从而可方便地判断出旋转方向,而Z相为每转一个脉冲,用于基准点定位。它的优点是原理构造简单,机械平均寿命可在几万小时以上,抗干扰能力强,可靠性高,适合于长距离传输。其缺点是无法输出轴转动的绝对位置信息。增量式编码器是一种测量设备转动的传感器,在电机驱动控制中得到广泛应用。
关键词:SPMC75  增量编码器

1 引言

  本文主要是讲解SPMC75F2413A的PDC定时器模块的增量码盘接口功能,用这个接口可以测量增量码盘转轴的角位移,同时还可根据单位时间的角位移计算出增量码盘转轴的角速度,进而得到转轴的转速。本例使用的增量码盘接口模式1,这是四倍频接口模式,适合图2-1中所示类型的波形。

2 系统框图

  系统结构如图2-1所示,主要由信源模拟发生模块和速度测量模块组成。两个模块均由SPMC75F2413A构成。信源模拟发生模块产生如中A、B所示的信号波形,A、B信号相差90度,图中只示出了B超前A的情况,信号的频率由电位器调整。


图 2-1 系统结构图
 
3 增量编码盘接口原理

3.1 设计原理

  增量编码盘是一种测量角位移增量的传感器,根据其工作方式的不同可分为光电式、磁电式和纯机械式等几种,光电式和磁电式是现今最常用的方式。其中光电式用得最多是光电透射式,而磁电式主要是利用类式磁带的原理在一个圆周上均布了N、S的磁信号,利用磁敏组件检出信号。
SPMC75F2413A的增量编码盘接口模式1工作原理如图3-1所示:外部输入信号TCLKA、TCLKB频率相同但相位互差90度,其频率与其转速成正比,比例为增量编码的细分数(每转1转所输出的脉冲个数)。而两路信号的相位关系则代表了转向信息。当TCLKA超前TCLKB时为正转,反之当TCLKA滞后TCLKB时为反转。同时,由于这两路信号是互差90度的,为了提高测量的精度,计数器是在两路信号的跳变沿都计数,而计数的方向则由两路信号的相位关系确定。TCLKA超前时计数器增计数,TCLKA滞后时计数器减计数。如此,用户便可以得到从计数器开始计数后增量编码转轴的角位移量(如当增量编码盘的细分数为N时,增量编码盘的每一个脉冲代表的角位移为由于为四倍频计数,因此,当计数器的值为K时,所代表的角位移为)。同时,用户可以通过测量单位时间内的角位移而得到当前转轴的转速。其转速为:
        ------(式3-1)
式中:为转轴角速度;
为测量时间;
内的计数器增量;
N为码盘的细分数;

图2-1 相位计数模式1
 
4 硬件说明

4.1 信号模拟发生电路

  这部分电路如图4-1所示,使用SPMC75F2413A的MCP3实现双线增量码盘输出信号的模拟,并根据AD采集的数据设置信号的频率和方向,以满足系统测试的需要。

图4-1信号模拟发生电路


4.2 测量接口电路

  电路如图4-2所示,这部分是本例的主体部分,它主要是利用SPMC75F2413A的PDC定时计数器的相位计数(码盘接口)模式1完成位置信号的采集、速度的测量。为了提高测量精度,使用了四倍频技术。

图4-2测量接口电路
 
5 软件说明

5.1 软件说明

  系统的软件部分主要是系统所用到的硬件的初始化,并在硬件中断时进行相应的的处理。同时利用DMC的通信软体库完成与PC的通信,以便对系统状态和结果进行监控。
5.2 软件流程

5.2.1 主程序流程

  主程序在完成系统初始化以后,就不断检测有没有来自PC的控制信息,如果有便完成相应的控制功能,没有就继续检测。同时将当前系统测得数据送入DMC接口区,以便系统状态的监示。

图5-1 主程序流程图

5.2.2 中断流程

  中断服务主要有三个,一个是系统通信中断服务,主要是在DMC库中完成;一个是PDC定时器的溢出中断服务,在这里主要完成位置计数溢出的处理,以保证位置单元的正确性;最后一个是定时器的周期中断服务,这里主要完成当前位置信息的采集,同时根据位置增量计算当前的转速。

5.3 程序代码

  使用SPMC75F2413A的PDC0的相位计数模式(即两线增量码盘接口)实现使用两线增量码盘测量电机转速。

#include "Spmc75_regs.h"

#include "mcMACRO.h"

#include "Spmc75_dmc_uart_ext.h"

#define Samp_Time 8 // 采样定时器 , 单位 ms

void Daly_Time(int Time);

void PDC0_Init(void);

void Time2_Init(void);

static int Moto_Speed = 0; // 电机转速

static int Over_flag = 0; // 位置计数器溢出标志

static int Encoder_Data = 256*4; // 编码盘的细分常数

// 电机绝对位置 ( 长整数 , 为了计算方便 , 高低分开定义 )

static unsigned int Position_Count[2] = {0,0};

static unsigned int Old_Position_Count = 0; // 上一次电机位置 ( 低 16 位 )

//=====================================================================

// ----Function: main(void);

// -Description: 主函数

// --Parameters: None

// -----Returns: None

// -------Notes:

//=====================================================================

main()

{

PDC0_Init();

Time2_Init();

MC75_DMC_UART_Setup(9600);

INT_IRQ();

while(1)

{

MC75_DMC_UART_Service();

if(SPMC_DMC_Load_SpdCmd(1) > 0)

Encoder_Data = SPMC_DMC_Load_SpdCmd(1)*4;

SPMC_DMC_Save_SpdNow(1,Moto_Speed);

}

}

//=====================================================================

// ----Function: void PDC0_Init(void);

// -Description: 定时器初始化

// --Parameters: None

// -----Returns: None

// -------Notes:

//=====================================================================

void PDC0_Init(void)

{

P_IOA_Dir->W &= 0xe7ff; // 设置用到的 IO 口

P_IOA_Attrib->W &= 0xe7ff;

P_IOA_Buffer->W |= 0x1800;

P_IOA_SPE->W |= 0x1800;

P_TMR0_Ctrl->B.SPCK = CB_TMR0_SPCK_FCKdiv1; // 设置采样时钟为主系统时钟

// 设置定时计数器模式为四倍频增量码盘接口

P_TMR0_Ctrl->B.MODE = CB_TMR0_MODE_Mode1;

P_TMR0_Ctrl->B.CCLS = CB_TMR0_CCLS_Disabled; // 禁止计数器清除

P_TMR0_Ctrl->B.CKEGS = CB_TMR0_CKEGS_Rising; // 设定计数边沿为上升沿

P_TMR0_Ctrl->B.TMRPS = CB_TMR0_TMRPS_FCKdiv1; // 设置时钟 , 这是必需的

// 使能计数器的上溢下溢中断

P_TMR0_INT->W |= CW_TMR0_TCUIE_Enable + CW_TMR0_TCVIE_Enable;

P_TMR_Start->B.TMR0ST = 1; // 启动定时器

}

//=====================================================================

// ----Function: void Time2_Init(void);

// -Description: TMR2_module initialize function

// --Parameters: None

// -----Returns: None

// -------Notes:

//=====================================================================

void Time2_Init(void)

{

P_TMR2_Ctrl->B.MODE = CB_TMR2_MODE_Normal; // 工作模式初始化为连续增计数

P_TMR2_Ctrl->B.CCLS = CB_TMR2_CCLS_TPR; // 计数器清零源为周期匹配信号

P_TMR2_Ctrl->B.CKEGS = CB_TMR2_CKEGS_Rising; // 计数边沿为上升沿

P_TMR2_Ctrl->B.TMRPS = CB_TMR2_TMRPS_FCKdiv4;// 计数时钟为主时钟的 1/4

P_TMR2_TPR->W = 6000*Samp_Time; // 定时周期设为 48000---8ms

P_TMR2_INT->B.TPRIE = CB_TMR2_TPRIE_Enable; // 使能定时器的周期中断

P_TMR_Start->B.TMR2ST = CB_TMR_TMR2ST_Start; // 启动定时器

}

//=====================================================================

// Description: IRQ1 interrupt source is XXX,used to XXX

// Notes:

//=====================================================================

void IRQ1(void) __attribute__ ((ISR));

void IRQ1(void)

{

if(P_TMR0_Status->B.TCUIF)

{

P_TMR0_Status->B.TCUIF = 1; //Clear TCUIF flag

(int)Position_Count[1] --; // 位置计数下溢出

Over_flag = 1;

}

if(P_TMR0_Status->B.TCVIF)

{

P_TMR0_Status->B.TCVIF = 1; //Clear TCVIF flag

(int)Position_Count[1] ++; // 位置计数上溢出

Over_flag = 1;

}

}

//=====================================================================

// Description: IRQ4 interrupt source is XXX,used to XXX

// Notes:

//=====================================================================

void IRQ4(void) __attribute__ ((ISR));

void IRQ4(void)

{

long Temp;

if(P_TMR2_Status->B.TPRIF)

{

P_TMR2_Status->B.TPRIF = 1;

Position_Count[0] = P_TMR0_TCNT->W;

if(Position_Count[0] < Old_Position_Count) // 计算位置增量

{

if(Over_flag > 0) //1 正转 , 上溢

Temp = (0xffff - Old_Position_Count) + Position_Count[0] + 1;

else //0 反转 , 没有溢出

{

Temp = Old_Position_Count - Position_Count[0];

Temp = -Temp;

}

}

else

{

if(Over_flag > 0) // 反转 , 溢出

{

Temp = (0xffff - Position_Count[0]) + Old_Position_Count + 1;

Temp = - Temp;

}

else // 正转 , 没有溢出

Temp = Position_Count[0] - Old_Position_Count;

}

Over_flag = 0;

Old_Position_Count = Position_Count[0];

Moto_Speed = (int)((Temp*7500)/Encoder_Data);// 速度计算

}

}

//=====================================================================

// Description: IRQ6 interrupt source is XXX,used to XXX

// Notes:

//=====================================================================

void IRQ6(void) __attribute__ ((ISR));

void IRQ6(void)

{

if(P_UART_Status->B.RXIF && P_UART_Ctrl->B.RXIE)

MC75_DMC_RcvStream();

}

6 参考文献

【1】SUNPLUS       SPMC75编程指南            www.sunplusmcu.com
【2】SUNPLUS       SPMC75F2413A数据手册         www.sunplusmcu.com

                            
 相关文章                                                      [top]
 ·凌阳DMC工具的使用 [2006-11-14]
版权所有:北京凌阳爱普科技有限公司 京ICP备05061966号 未经许可网站内容严禁复制、转载,任何人不得擅自使用
友情链接:凌阳爱普 嵌入式培训 安卓培训 凌阳大学计划 北京嵌入式培训 深圳嵌入式培训 成都嵌入式培训