问题困扰了我几天了,有好的办法,在文档里给我解答,谢谢、
方案一: 1、谁能提供一个思路:用一个固定的中断时间,中断一次,变量加一次。变量每加一次,刷新的数据更新一次,这个变量的作用是:改变中断的频率的。比如说:一开始定时1ms中断一次,刷新一次数据,然后又中断一次,变量在之前的基础上加一,即2ms后数据跟着刷新一次,再中断一次,3ms后数据刷新一次,依次往下进行,即想实现匀减速。之所以用固定时间中断是因为我还需要一个脉冲(这个可以实现,但是实现不了匀减速)。 我现在这程序,你们看下,步进电机设置了3个速度,一圈一个固定速度,不是我想要的。我想要的是总共转3圈的话,速度慢慢降下来,减速的等级设多点,平滑点就好了。 方案二: 2、当然你们要说改变定时器的初值的话,这样行,我实现了电机的匀减速,我还需要一个固定的脉冲,定时的初值又是变化的,又实现不了固定脉冲了。这两个方案,问题相互交叉,很是烦恼。 方案三: 3、你们会想使用2个定时器,一个定时器给电机做匀减速运动,一个定时器做固定脉冲输出,我试了,匀减速没问题,但是固定脉冲会受影响,不是一个稳定的脉冲占空比。
- #include<reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- volatile unsigned long beats1=0;//电机1转动节拍总数
- void startmotor1(unsigned long angle1);//电机1函数
- static unsigned char index1 =0;//节拍输出索引1
- unsigned char code beatcode1[8]={0x1,0x3,0x2,0x6,0x4,0xc,0x8,0x9};//步进电机1、3节拍控制码
- uchar temp1=0;//临时变量
- uchar n=0;//小电机中断频率计数变量
- uint k=0;//小电机刷新节拍计数
- void delay(unsigned char i)
- {
- unsigned x,y;
- for(x=i;x>0;x--)
- for(y=50;y>0;y--);
- }
- bit flag1=0,flag2=0,flag3=0,flag4=0;
- unsigned char dir=0;
- sbit k1=P3^5;//按键1--启动电机/正转
- sbit k2=P3^6;//按键2--电机反转
- sbit k3=P3^7;//按键3--暂停/开始
- sbit PWM=P2^0;//42步进电机脉冲引脚
- sbit buffer=P2^5;//蜂鸣器
- sbit fangxiang=P2^6;//电机正反转控制线
- sbit EN=P2^7; //使能停止线
- sbit P1_0=P1^0;
- sbit P1_1=P1^1;
- sbit P1_2=P1^2;
- sbit P1_3=P1^3;
- sbit P1_4=P1^4;
- sbit P1_5=P1^5;
- sbit P1_6=P1^6;
- sbit P1_7=P1^7;
- void di() //蜂鸣器函数
- {
- unsigned char a;
- for(a=0;a<100;a++)
- {
- delay(1);
- buffer=0;
- delay(1);
- buffer=1;
- }
- }
- void keyscan() //按键扫描程序
- {
- if(k1==0)
- delay(10); //消抖
- if(k1==0) //启动电机
- {
- while(!k1); //等待按键1松手
- TR0=1;
- // EN=1;
- // fangxiang=0;
- startmotor1(360*5); //调用电机1函数
- }
- }
- void startmotor1(unsigned long angle1) //步进电机1启动函数,angle1为所转动角度
- {
- EA=0;
- beats1=(angle1*4076)/360;
- EA=1;
- }
- void motor1() //电机函数;固定格式,调用就行。
- {
- if(beats1!=0)
- {
- temp1=P1;
- temp1=temp1&0xf0; //清零P1口低4位 11110000
- temp1=temp1|beatcode1[index1];
- P1=temp1;
- index1++;
- index1=index1&0x07;
- beats1--;
- }
- else
- {
- P1_0=0;
- P1_1=0;
- P1_2=0;
- P1_3=0;
- }
- }
- void main()
- {
- TMOD=0x01;//设置T0为模式1
- TH0=0xfc; //1ms中断一次
- TL0=0x18;
- ET0=1;
- while(1)
- {
- keyscan(); //按键扫描
- if(flag1==1)
- {
- flag1=0;
- if(flag3==1) //进入第3圈速度;
- {
- if(n==8) //第3圈速度,3ms刷新一次节拍;
- {
- n=5;
- k++; //第3圈节拍计数;
- if(k==4076) //第3圈以3ms的速度刷新4076个节拍后(即转了一圈),停止转动。
- {
- k=0;
- beats1=0;//停止转动
- flag3=0;//标志3清楚,以便再次启动定时器;
- n=0; //n清零
- TR0=0;//关定时器
- }
- motor1();
- }
- }
- if(flag2==1) //进入第2圈速度;
- {
- if(n==4) //第2圈速度,2ms刷新一次节拍;
- {
- n=2;
- k++; //第2圈节拍计数;
- if(k==4076) //第2圈以2ms的速度刷新4076个节拍后(即转了一圈),重新设置速度n=5,进入标志3判断;
- {
- k=0;
- n=5;
- flag3=1; //速度3标志,进入速度3,3ms刷新一次;
- }
- motor1();
- }
- }
- if(n==1) //进入第1圈速度,1ms刷新一次节拍;
- {
- n=0;
- k++; //第1圈节拍计数;
- if(k==4076) //第1圈以1ms的速度刷新4076个节拍后(即转了一圈),重新设置速度n=2,进入标志2判断;
- {
- k=0;
- n=2;
- flag2=1;//速度2标志,进入速度2,2ms刷新一次;
- }
- motor1();
- }
- }
- }
- }
- void timer0() interrupt 1
- {
- TH0=0xfc; //重新赋值,1ms中断一次
- TL0=0x18;
- n++; //小电机中断刷新频率计数
- flag1=1;//标志的作用是跳至主函数中,以节省中断时间。
- }
复制代码
|