驱动步进电机有点像点流水灯,看似简单,真的是要控制好,还是需要花一番功夫。 应广单片机+两个H桥驱动就可以把两相4线的步进电机驱动起来。不多说,先驱动电机转起来再说,上代码了。
#include "extern.h"
/*调试输出开关,关闭之后测试端口不输出了*/
//#define DEBUG
/*1m 标记*/
bit msFlag;
/*us计数*/
byte ucUsCnt;
/*ms 计数*/
byte ucMsCnt;
Word Reload_T16;
byte usStep;
byte ucDat;
/*可以用示波器观察对应端口*/
#ifdef DEBUG
bit US100_OUT :pa.7
bit MS_OUT :pa.6
bit MS10_OUT :pa.0
#endif
bit MOTO_AP : PB.2
bit MOTO_AN : PB.4
bit MOTO_BP :pb.5
bit MOTO_BN :pb.6
/*中断服务程序*/
void Interrupt(void)
{
pushaf;
if(Intrq.T16)
{
STT16 Reload_T16;
Intrq.T16 = 0;
ucUsCnt++;
if(ucUsCnt>9)
{
ucUsCnt=0;
/*100us*10=1ms*/
msFlag=1;
}
/*100u task,紧急任务放这边,但这里的任务尽量少,
心脏部位,尽量减少干扰,需要保证tick精准*/
#ifdef DEBUG
if(US100_OUT)
{
US100_OUT=0;
}
else
{
US100_OUT=1;
}
#endif
}
popaf;
}
/*T16设置*/
Void Timer16_Init(void)
{
/*向上计数 1600就发生中断 1600/16M=0.0001s=100us,理论设计*/
//Reload_T16 = 32768 - 1600;
/*根据测算(示波器校准),除去误差(约为20个sysclk周期),设置1580这个值可能更准确,
SYSCLK越快,误差越小.从进入中断开始,到重新设置计数器,中间大概需要20个sysclk周期*/
Reload_T16 = 32768 - 1580;
/*设置计数器值*/
STT16 Reload_T16;
/*配置T16 控制寄存器*/
$ T16M IHRC,/1,BIT15;
INTRQ.T16 = 0;
INTEN.T16 = 1;
msFlag=0;
ucUsCnt=0;
}
void MotoDrvUd(byte usdat)
{
byte ucIoSet=usdat;
if(ucIoSet&0x08)
{
MOTO_BP=1;
}
else
{
MOTO_BP=0;
}
if(ucIoSet&0x04)
{
MOTO_BN=1;
}
else
{
MOTO_BN=0;
}
if(ucIoSet&0x02)
{
MOTO_AP=1;
}
else
{
MOTO_AP=0;
}
if(ucIoSet&0x01)
{
MOTO_AN=1;
}
else
{
MOTO_AN=0;
}
}
void FPPA0 (void)
{
/*注意,修改了sysclk,Reload_T16要做细微调整,可以试着改动sysclk,
会发现Reload_T16误差变大*/
.ADJUST_IC SYSCLK=IHRC/2,IHRC=16MHz,init_ram,vdd=5V;
/*开启看门狗*/
CLKMD.En_WatchDog = 1;
wdreset;
/*初始化T16*/
Timer16_Init();
$ MOTO_AP out,low;
$ MOTO_AN out,low;
$ MOTO_BP out,low;
$ MOTO_BN out,low;
#ifdef DEBUG
$ US100_OUT out,low;
$ MS_OUT out,low;
$ MS10_OUT out,low;
#endif
usStep=7;
Engint;
while (1)
{
/*喂狗*/
wdreset;
/*1ms标记*/
if(msFlag)
{
ucMsCnt++;
if(ucMsCnt>9)
{
/*1ms*10=10ms*/
ucMsCnt=0;
/*10mstask 放这里*/
#ifdef DEBUG
if(MS10_OUT)
{
MS10_OUT=0;
}
else
{
MS10_OUT=1;
}
#endif
}
/*1ms task*/
#ifdef DEBUG
if(MS_OUT)
{
MS_OUT=0;
}
else
{
MS_OUT=1;
}
#endif
usStep++;
if(usStep>7)
{
usStep=0;
}
switch(usStep)
{
case 0:
ucDat=0B0000_1000;
break;
case 1:
ucDat=0B0000_1010;
break;
case 2:
ucDat=0B0000_0010;
break;
case 3:
ucDat=0B0000_0110;
break;
case 4:
ucDat=0B0000_0100;
break;
case 5:
ucDat=0B0000_0101;
break;
case 6:
ucDat=0B0000_0001;
break;
case 7:
ucDat=0B0000_1001;
break;
}
MotoDrvUd(ucDat);
msFlag=0;
}
}
}
/*creat by zhongvv QQ85547259*/