#include
unsigned long beats=0;
void TurnMotor(unsigned long angle); //函数声明
void main()
{
EA=1; //使能总中断
TMOD=0x01; //设置T0模式
TH0=0xF8; //高低位初值(2ms)
TL0=0xCD;
TR0=1; //计数器to启动
ET0=1; //T0中断开关
TurnMotor(360*2); //转动2圈,传入角度
while(1);
}
void TurnMotor(unsigned long angle) //计算所需要的拍数
{
EA=0;
beats=(angle*4076)/360; //计算所需要的拍数
EA=1;
}
/*中断服务函数*/
void interrupttimer0() interrupt 1
{
unsigned char tmp;
static unsigned char index=0;
unsigned char code BeatCode[8]={ //步进电机节拍对应的io控制代码
0xE,0xC,0xD,0x9,0xB,0x3,0x7,0x6
};
TH0=0xF8; //重新赋初值
TL0=0xCD;
while(beats--) //拍数结束循环结束
{
tmp=P1;
tmp=tmp&0xF0;
tmp=tmp | BeatCode[index]; //节拍低四位赋值
P1=tmp;
index++;
index=index&0x07; //到8置0
}
P1=P1|0x0F; //电机停止工作
}
在代码中,我发现 while(beats--) 循环中对 beats 的判断是通过减一的方式实现的,这个方式在理论上是可以实现电机转动两圈的功能的。但是,由于这个循环执行的次数非常大,如果电机转动的速度过快,就有可能出现循环次数过多,导致电机无法正常转动的情况。
可以尝试在循环中添加延时等待电机转动完成,以确保电机能够转动到指定角度。
不知道你这个问题是否已经解决, 如果还没有解决的话:有时候会遇到这样一种情况,当上层人员将一个功能交给下层程序员完成时,上层程序员和下层程序员同步工作,这个时候该功能函数并未完成,这个时候上层程序员可以定义一个API来交给下层程序员,而上层程序员只要关心该API就可以了而无需关心具体实现,具体实现交给下层程序员完成即可(这里的上层和下层程序员不指等级关系,而是项目的分工关系)。这种情况下就会用到回调函数(Callback Function),现在假设程序员A需要一个FFT算法,这个时候程序员A将FFT算法交给程序员B来完成,现在来让实现这个过程:
#include <stdio.h>
int InputData[100]={0};
int OutputData[100]={0};
/*定义回调函数*/
void CallBack_FFT_Function(int *inputData,int *outputData,int num)
{
while(num--)
{
printf("www.zhiguoxin.cn\r\n");
}
}
/*用来注册回调函数的功能函数*/
void TaskA(void (*fft)(int*,int*,int))
{
fft(InputData,OutputData,5);
}
int main(void)
{
/*注册FFT_Function作为回调*/
TaskA(CallBack_FFT_Function);
return 0;
}
这个例子是不是跟上面的那个例子是相同的,只是我们在这里换了一种说法而已。也就是我们硬件层实现的某个功能,当然可以在应用层直接调用,但是这种做法太low了,一看就是小学生的水平,或者说硬件层的东西应用层根本不需要关心,这就是分层的思想。硬件的东西就给硬件工程师做,应用工程师只关心自己的需要实现的任务。这也就是驱动工程师和应用工程师的区别,我硬件工程师只需要写好对应的API函数,你应用层直接调用就好了,你不需要关心这个API函数的内部是怎么实现的。而这两者之间的桥梁就是回调函数。而回调函数的形参就是函数指针,所以本篇最开始讲的是函数指针,只要你函数指针明白了,你就会写回调函数,也就理解了这其中到底只一个什么原理。
上面的代码中CallBack_FFT_Function
是回调函数,该函数的形参为一个函数指针,TaskA
是用来注册回调函数的功能函数。可以看到用来注册回调函数的功能函数中申明的函数指针必须和回调函数的类型完全相同。