#include <reg52.h>
/********IO引脚定义***********************************************************/
sbit SW1=P1^0; //四个独立按键定义
sbit SW2=P1^1;
sbit SW3=P1^2;
sbit SW4=P1^3;
sbit SMG1 = P1^4; //数码管第一位定义
sbit SMG2 = P1^5; //数码管第二位定义
sbit SMG3 = P1^6; //数码管第三位定义
sbit SMG4 = P1^7; //数码管第四位定义
int table[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x40}; //共阴极数码管段值
unsigned char flag; //right(lhj[i+1],lhj[i+2]); //正转,两个参数代表步进量和转速
/********数据定义***********************************************************/
// 512个脉冲 90度
unsigned char dataout[8]={0xf1,0xf2,0xf4,0xf8};
//这里我们定义4组数,分别对应四拍:A-B-C-D 从板上设计来分配,选择P2口的低四位输出
//P2。0为A相,P2。1为B相,P2。2为C相,P2。3为D相,将高四位都置1,也就是F。
//我们用索引的方式输出,比如正转,元素由0到3这样的循环,反转则由3到0的循环
//程序中我们保存索引号,比如上次转在第2元素停下,则下次的正转由3开始向后计数,反转则由1开始向前计数
//这样,电机的转角度就会很精确
unsigned char datac=0; //存放索引号(元素号)
unsigned int gStep = 0;
unsigned long gMainchong = 0;
unsigned int gJd = 0;
unsigned int gKey_flag = 0;
unsigned int b1,b2,b3; //临时变量
void delayms(xms);
void Timer0_Init();
void Display();
void rightAll();
void leftAll();
void stepAll();
void Ang();
void KeyScan();
/********函数声明*************************************************************/
void right(unsigned int Speed,unsigned int road); //正转
void left(unsigned int Speed,unsigned int road); //反转
void mDelay(unsigned int DelayTime); //延时函数
/***********主函数开始********************************************************/
void main()
{
unsigned char i=0;
P2&=0XF0; //因ULN2003A直接驱动,为高电平输出,初始时为低电平,这里一定不能少了
mDelay(100);
Timer0_Init();
while(1)
{
KeyScan();
Ang();
}
}
/******************************************************************************
* 名称: Timer0_Init()
* 功能: 定时器0初始化
* 输入: 无
* 输出: 无
* 说明:
******************************************************************************/
void Timer0_Init()
{
TMOD=0x01; //定时器方式一
TH0=(65536-500)/256; //定义高字节
TL0=(65536-500)%256; //定义低字节
ET0=1; //计数器中断
EA=1; //开总中断
// TR0 = 1;
}
/******************************************************************************
/******************************************************************************
* 名称: Set_Display()
* 功能: 数码管显示函数
* 输入: 无
* 输出: 无
* 说明:
******************************************************************************/
void Display()
{ //以下把num值区分开 以便数码管显示
b1=gJd%1000/100; //百位
b2=gJd%1000%100/10; //十位
b3=gJd%1000%100%10; //个位
P0=0x40;
SMG1=0; //显示"-"
delayms(3);
SMG1=1;
P0=table[b1];
SMG2=0; //显示百位
delayms(3);
SMG2=1;
P0=table[b2];
SMG3=0; //显示十位
delayms(3);
SMG3=1;
P0=table[b3];
SMG4=0;
delayms(3); //显示个位
SMG4=1;
}
/***********左转,两个参数代表步进量和转速*************************************/
void right(unsigned int Speed,unsigned int road)
{
//步进节拍:A-B-C-D
do{
if(datac==3) //索引号超出3回到0
datac=0;
else
datac++;
P2=dataout[datac]; //这里就在P2口输出我们定义好的相序步进,P2。0为A相,P2。1为B相,P2。2为C相,P2。3为D相
//这里我们不考虑P2的高四位,直接赋值
mDelay(road); //这里的延时就可控制转速
Speed--;
}
while(Speed);
P2&=0XF0; //将四个脚复位0
}
/***********右转,两个参数代表步进量和转速*************************************/
void rightAll()
{
if(gStep == 3)
gStep = 0;
else
gStep++;
P2=dataout[gStep];
if(gMainchong == 2048)
gMainchong = 0;
else
gMainchong++;
}
/***********整体左转*************************************/
void leftAll()
{
if(gStep == 0)
gStep = 3;
else
gStep--;
P2=dataout[gStep];
if(gMainchong == 0)
// gMainchong = 4096;
gMainchong = 2048;
else
gMainchong--;
}
/***********固定动作*************************************/
void stepAll()
{
right(512, 50);
left(1024, 50);
right(215, 50);
}
/***********计算并显示角度*************************************/
void Ang() // 计算角度
{
unsigned int i;
// gJd = gMainchong*5.625/32.0;
gJd = gMainchong*11.25/64.0;
b1=gJd%1000/100; //将得到的数据拆分,以便数码管显示 百位
b2=gJd%1000%100/10; //十位4
b3=gJd%1000%100%10; //个位
for(i=0;i<20;i++) Display(); //显示20遍,防止显示数据抖动,变化太快
}
/***********反转,两个参数代表步进量和转速*************************************/
void left(unsigned int Speed,unsigned int road)
{
//步进节拍A-D-C-B
do{
if(datac==0) //索引号超出0回到3
datac=3;
else
datac--;
P2=dataout[datac]; //这里就在P2口输出我们定义好的相序步进,P2。0为A相,P2。1为B相,P2。2为C相,P2。3为D相
//这里我们不考虚P2的低四位,直接赋值
mDelay(road); //这里的延时就可控制转速
Speed--;
}
while(Speed);
P2&=0XF0; //将四个脚复位0
}
/***********延时函数*******************************************************/
void mDelay(unsigned int DelayTime) // 10ms
{
unsigned char j=0;
while(DelayTime--)
{
for(j=0;j<10;j++){}
}
}
// 延时函数
void delayms(xms)
{
unsigned int x,y;
for(x=xms;x>0;x--)
for(y=110;y>0;y--)
;
}
/***********按键扫描函数*************************************/
void KeyScan()
{
if(SW1 == 0)
{
delayms(10);
if(SW1 == 0) // 正传
{
TR0 = 0;
gKey_flag = 1; //
Timer0_Init();
TR0 = 1;
}
}
if(SW2 == 0)
{
delayms(10);
if(SW2 == 0) // 反传
{
TR0 = 0;
gKey_flag = 2;
Timer0_Init();
TR0 = 1;
}
}
if(SW3 == 0)
{
delayms(10);
if(SW3 == 0) // 自定义动作
{
TR0 = 0;
gKey_flag = 3;
Timer0_Init();
TR0 = 1;
}
}
if(SW4 == 0)
{
delayms(10);
if(SW4 == 0) // 停止
{
TR0 = 0;
gKey_flag = 0;
Timer0_Init();
TR0 = 1;
}
}
}
/******************************************************************************
* 名称: T0_int() interrupt 1
* 功能: 定时器0 中断函数
* 输入: 无
* 输出: 无
* 说明:
******************************************************************************/
void T0_int() interrupt 1
{
// flag=1; //标志位之一
TR0 = 0;
switch(gKey_flag)
{
case 0x00:
P2&=0XF0;
break;
case 0x01:
rightAll();
TH0=(65536-10000)/256; //定义高字节
TL0=(65536-10000)%256; //定义低字节
TR0 = 1;
break;
case 0x02:
leftAll();
TH0=(65536-10000)/256; //定义高字节
TL0=(65536-10000)%256; //定义低字节
TR0 = 1;
break;
case 0x03:
stepAll();
break;
default:
break;
}
}