微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于Mega128编码器控制步进电机的平衡系统

基于Mega128编码器控制步进电机的平衡系统

时间:11-29 来源:互联网 点击:
提起编码器,可能大家并不陌生,因为这东西真的很常用,现在的主流编码器一般精度都是比较高的,基本上都是基于光栅的。毕竟用硬件用电刷做到512精度以上是很困难的,而且成本也是很高的,这里我就不多说什么了。

编码器一般共有三个主通道,每个主通道有分为两个分支;一个VCC,一个GND,一条屏蔽线。前两个通道一般是比较精确的脉冲信号,且之间有四分之一左右的相位差用来判断正反转的,第三通道基本上是旋转一周才会有一个脉冲信号的那种。

提到步进电机,就一定要有一个合适的电机驱动,个人是比较喜欢用L298n这款芯片的,因为它价格低,操作比较简单。

对于这个系统,我是用128的外部中断的下降沿触发方式来捕捉编码器的脉冲的,硬件连接方面电机驱动和主控芯片一定要注意地线的连接。

下面是程序的完整代码下载地址:http://www.51hei.com/f/bmma.rar

这里是delay.h====================================================================//根据CPU时钟频率选择#ifndef F_CPU//#define F_CPU 7372800//#define F_CPU 8000000//#define F_CPU 11059200//#define F_CPU 12000000#define F_CPU 16000000#endif//------------------------------------------------------------------------------//1、2、3、5和10us的精确延时,用于需要精确时间的场合,比如DS18B20//------------------------------------------------------------------------------#if   F_CPU == 7372800#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP()#define DELAY_2US DELAY_1US;DELAY_1US#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US#define DELAY_5US DELAY_2US;DELAY_3US#define DELAY_10US DELAY_5US;DELAY_5US#elif F_CPU == 8000000#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP()#define DELAY_2US DELAY_1US;DELAY_1US#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US#define DELAY_5US DELAY_2US;DELAY_3US#define DELAY_10US DELAY_5US;DELAY_5US#elif F_CPU == 11059200#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP()#define DELAY_2US DELAY_1US;DELAY_1US#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US#define DELAY_5US DELAY_2US;DELAY_3US#define DELAY_10US DELAY_5US;DELAY_5US#elif F_CPU == 12000000#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP()#define DELAY_2US DELAY_1US;DELAY_1US#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US#define DELAY_5US DELAY_2US;DELAY_3US#define DELAY_10US DELAY_5US;DELAY_5US#elif F_CPU == 16000000#define DELAY_1US NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP()#define DELAY_2US DELAY_1US;DELAY_1US#define DELAY_3US DELAY_1US;DELAY_1US;DELAY_1US#define DELAY_5US DELAY_2US;DELAY_3US#define DELAY_10US DELAY_5US;DELAY_5US#endif//------------------------------------------------------------------------------//函数声明//------------------------------------------------------------------------------void delay_nus(unsigned int);//<10us时误差较大,用于无须精确延时的场合void delay_nms(unsigned int);#endif//__DELAY_H====================================================================这里是delay.c====================================================================//|文件名称|delay.c//|--------|--------------------------------------------------------------------//|描    述|延时文件//|--------|--------------------------------------------------------------------//|说    明|delay_us(unsigned int time)用于不需精确定时的场合,<10us时误差较大//|        |若要精确定时用delay.h里的宏//|--------|--------------------------------------------------------------------//|调用文件|delay.h//|--------|--------------------------------------------------------------------//|作    者|//|--------|--------------------------------------------------------------------//|版    本|//|--------|--------------------------------------------------------------------//|时    间|//|--------|--------------------------------------------------------------------//|E-mail  |//|--------|--------------------------------------------------------------------//|开发环境|ICCAVR6.31//==============================================================================#include "delay.h"#if F_CPU == 7372800void delay_nus(unsigned int time){unsigned int i;for(i=0;i/*步进电机旋转一周子函数*/void one_circle(void){unsigned int i;for(i=0;i<3200;i++){EN_1;delay_us(100);EN_0;delay_us(100);}}/*步进电机根据编码器计算的数值旋转任意角度子函数*/void circle(unsigned int xcircle){unsigned int i,j;for(j=0;j#include#include//一些变量的定义int k=0;unsigned int x=1,d=0,c=0,cir=0;unsigned int a,aa,q,angle=0,p=0;//595(数码管)显示数组unsigned char led[]={0x3F, // 00x06, // 10x5B, // 20x4F, // 30x66, // 40x6D, // 50x7D, // 60x07, // 70x7F, // 80x6F, // 9};//外部中断0~3向量号码#pragma interrupt_handler Zhongduan_0:2#pragma interrupt_handler Zhongduan_1:3#pragma interrupt_handler Zhongduan_2:4//端口输入输出初始化void init_xianshi(void){DDRA=0XFF;DDRB=0XFF;//595控制口DDRC=0XFF;//正反转提示LEDPORTC=0XFF;//LED初始化(暗)}//595串入一字节并处发送一字节子函数void send_595(unsigned char dat){unsigned char i;LCK_0;SDI_1;SCK_0;//上面的三条语句为了初始化端口状态for(i=0;i<8;i++){LCK_0;//时钟线拉低if(dat&0x80)SDI_1;else SDI_0;dat=dat<1;delay_us(100);  LCK_1;          //时钟线拉高将数据读入595的移位寄存器    delay_us(100); }SCK_1; //发送数据到并行端口SCK_0;   }void jiaoduzhuanhuan(void){init_xianshi();EIMSK=0X0F;EICRA=0XAA; while(1){ if(a!=aa) /*如果有角度变化就执行下面的程序*/{angle++;if(!(PING&0X04))cir++; while(cir){if(!k){delay_ms(800);if(d<=3)one_circle();d++;}}  if(!(PING&0X02)){while(PING&0X01){DIR_0;circle(1);p++;while(p==angle);}while(PING&0X01);if(q=-1)//正转DIR_1;circle(1);if(q==1)  //反转DIR_1;}aa=a;if(!x){PORTC=0X00;}}/*下面为数码管显示编码器当前计数的数值*/PORTA=0X08; send_595(0x00);send_595(led[abs(k)%10]);PORTA=0X01; send_595(0x00);send_595(led[(abs(k)%100)/10]);PORTA=0X02; send_595(0x00);send_595(led[(abs(k)%1000)/100]);PORTA=0X04; send_595(0x00);send_595(led[abs(k)/1000]);SEI(); /*使能中断*/} }void Zhongduan_0(void){CLI();x=0;////////////////// if(PIND&0X02)q=-1;if(!(PIND&0X02))q=1;////////////////k=k+q;SEI();}void Zhongduan_1(void){CLI();if(PIND&0X01)q=1;k=k+q;if(abs(k)==10000){k=0;}a=k;//EIMSK=0X0E;SEI();}void Zhongduan_2(void){CLI();k=0;SEI();}====================================================================这里是main.c====================================================================#include#include#include"delay.h"#include"caiji.h"#include"dianji.h"void init(void){DDRC=0X03;PORTC=0X00;}void main(void){init();     //初始化子函数jiaoduzhuanhuan(); //主程序的实现}====================================================================

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top