编码器与程序
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
飞思卡尔那些事之ECT方式检测速度
(2009-05-03 16:03:17)
转载
资源:
1、增量式旋转编码器。旋转编码器是测量速度的一种装置,旋转编码器每旋转一周,就会输出特定数目的脉冲。在单位时间内记录读取到旋转编码器输出的脉冲数,即可知道旋转编码器转动的圈数,即轮胎的转动速度。因为轮胎周长一定,所有可以求得在单位时间内小车行驶的路程,再通过计算即可得到小车的速度,如果单位时间足够小,则可以近似认为该速度位瞬时速度。
2、HCS12的ECT模块。在ECT模块中的输入捕捉定时器和脉冲累加器可以实现旋转编码器的脉冲计数。
方案:
1、输入捕捉(Intput Capture)计数方式。通过输入捕捉模块,进行脉冲输入捕捉,在中断程序中通过全局变量进行计数,每捕捉到一个脉冲进行一次计数,在单位时间内读取输入捕捉中断程序计数变量的计数值。
2、脉冲计数器(Modulus Counter)方式。通过脉冲累加器进行脉冲输入捕捉,模数计数器设定为单位时间中断,在模数计数器中断程序中读取脉冲累加器的计数数值。脉冲累加器可以选用16位脉冲累加器。也可以用8位的脉冲累加器。
3、模数计数器进行定时,每500MS读取一次脉冲数。读取这500MS中的脉冲数即可算出输出速度。
说明:
1、旋转编码器选用的是YZ30D-4S-2NA-200;该旋转编码器旋转一周,输出200个脉冲。
2、使用输入捕捉通道0进行脉冲的捕捉。设定位下降沿捕捉方式。开启输入捕捉中断,在中断程序中对全局变量iPulesNumAll进行计数,每进入一次中断程序,变量iPulesNumAll加1。
3、使用模数计数器进行定时,定时时间为500ms,当达到500MS后,读取iPulesNumAll中的数值,即可通过公式计算出速度。
定时过程中,既可以直接定时500MS,也可以定时1MS。在定时1MS的方案中,通过设定一个全局变量或静态变量iSpeedNum进行计数,当计数到500后再读取iPulesNumAll中的数值。
速度公式:
V=(车轮周长*总脉冲数)/(旋转编码器脉冲数*定时周期)
=(iWheelGirth*iPulesNumAll)/(iPulesNum*iSpeedTime)
=(iWheelGirth*iPulesNumAll)/(200*0.5)
4、BusClock:16Mhz
CODE:
#include
#include
#pragma LINK_INFO DERIVATIVE "mc9s12xs128"
//===========================================================//
//通道0输入捕捉测速程序,PT0输入旋转编码器输出脉冲
//16位模数递减计数器进行计数
//author: Yangtze
//time:2009/4/18/3:15:45
//===========================================================// #define iPulesNum 200//旋转编码器脉冲数
#define iSpeedNum 500//定时时间次数,一次为1MS
#define iWheelGirth 0.1//车轮周长
#define iSpeedTime 0.5//定时周期
int iPulesNumAll=0;//总脉冲数
int V=0;//速度变量
void pllclk(void) //16MHz
{
SYNR=0x01; //PLLCLK =2*OSCCLK*(SYNR + 1)/(REFDV + 1)
REFDV=0x01;
CLKSEL=0x80; //选定PLL时钟
}
void Init_PT0_ICapture(void)
{
TIOS=0xfe;//设定通道0为输入捕捉工作方式
TSCR2=0x87;//开启定时器中断
TFLG1=0xFF; //清除中断标志位
TCTL4=0x02; //设置输入捕捉方式的捕捉方式
TIE=0x01; //定时器中断使能
}
void Init_MDC(void)
{
MCCTL=0xDF;//设定模数计数器工作方式,中断使能,计数器使能
//分频系数为16
MCCNT=1000;//定时器赋初值 (1/16M)*16*1000= 1ms
}
void main(void)
{
pllclk();
Init_PT0_ICapture();
Init_MDC();
EnableInterrupts;
for(;;) {}
}
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 26 MDC_ISR(void)
{
static unsigned int count=0;
count++;
if(count==iSpeedNum) //400MS读取一次
{
V=(iPulesNumAll*iWheelGirth)/ (iPulesNum*iSpeedTime); //计算当前速度
iPulesNumAll=0;
count=0;
}
MCFLG = 0x80; //清中断标志位
}
#pragma CODE_SEG __NEAR_SEG NON_BANKED
void interrupt 9 PT4_Capture(void)
{
TFLG1=0x10; //清中断标志位
iPulesNumAll++; //脉冲计数
}
//后记:
//在编写这个程序当中,既有自己的思路,也参考了whut_wj的一些思路。感谢whut_wj。
//在检测速度程序中,我的想法是,通过脉冲累加器进行计数,当计数值达到200个脉冲时,触发中断,在脉冲累加器溢出中断中程序中,命令一个IO口想输入捕捉通道一个脉冲,去触发输入捕捉通道的输入捕捉中断,读取输入捕捉通道中寄存器中的数值,即可知道小车行走一圈的速度了。
//而whut_wj的程序体现的算法是,在单位时间内,读取捕捉到的所有脉冲数,因为时间一定,也可以计算出速度。这样的好处是电路和程序简单,而且需要的资源少,而且可选。在程序中,只需要一个全局变量或是静态变量,即可以实现参数的传递算出小车运行当中的速度。
//通过这两个思路的对比,让我了解了编程的一点点本质,虽然不过很透彻,不过却给我指明了一点方向:处理问题的算法又很多,程序员需要做到的就是在很多算法中选出最适合处理某一个问题的算法。因为哪怕是同一个问题,在不同的情况下,使用的同一中算法,可能执行结果也有很大的差距。用一个简单的词说就是具体问题具体分析。
//同时也找到了联系编程的一些方法,就是多看,多练,多想。