单片机的应用特别地多,其用途非常广泛,我们这些案例只是涉及其基本部分,没有深究,但是也是要作为一个了解的,今天就学习一下步进电机和可控步进电机
步进电机
实验现象
发现步进电机按照一定速度逆时针旋转,同时发现SM接口处左侧的led灯以一定频率闪烁
(PS:在没有步进电机的情况下,可以通过查看led的闪烁来判断步进电机是否处于工作状态下)
工作原理
步进电机
电脉冲信号转变为角位移或线位移的开环控制元步进电机件
(在非超载的情况下,电机的转速、停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,)
- 当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度,称为“步距角”,它的旋转是以固定的角度一步一步运行的。
- 可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;
- 同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的
励磁方式是一相励磁,励磁表在程序中为0111、1011、1101、1110,程序连续不停地在不同口送入脉冲信号,即可使步进电机旋转,通过设定定时器的定时时间减慢步进电机的旋转速度
电路原理图:
扩展:
步进电机的励磁方式有三种:
-
一相励磁
在每一瞬间,步进电机只有一个线圈导通。每送一个励磁信号,步进电机旋转5.625°,这是三种励磁方式中最简单的一种
顺序表如下:
-
二相励磁
在每一瞬间,步进电机有两个线圈同时导通。每送一个励磁信号,步进电机旋转5.625°
顺序表如下:
-
一-二相励磁
为一相励磁与二相励磁交替导通的方式。每送一个励磁信号,步进电机旋转2.8125°
顺序表如下:
代码解析
设计流程图如下:
设置其励磁的顺序表的元素,通过中断实现
void time0() interrupt 1
{
switch(i++)//控制步进电机不同IO脉冲电平
{
case 1: s1=1;s2=0;s3=0;s4=0;break;
case 2: s1=0;s2=1;s3=0;s4=0;break;
case 3: s1=0;s2=0;s3=1;s4=0;break;
case 4: s1=0;s2=0;s3=0;s4=1;break;
}
if(i==5)
i=1;
}
初始化
void init_sys()
{
P4M0=0Xff; //P4口推挽输出
P4M1=0X00;
// LED =0; //数码管显示
P4 =0X00; //P4口设置低电平,避免复位时对接口造成影响
TMOD = 0x00; //设置定时器0,16位
TH0 = (65536-10000)/256; //设定5ms
TL0 = (65536-10000)%256;
TCON = 0X10; //定时器开始计时
IE = 0x82; //开启CPU中断,定时器0中断
}
最后主函数中设置永真循环即可
可控步进电机
实验现象
现象与步进电机相同,只是增加了控制功能
即:
K2键可控制步进电机的旋转方向
K3键控制步进电机的旋转与停止
工作原理
通过在P4.1、P4.2、P4.3、P4.4口每隔5ms*sudu的时间输入高电平(sudu值由Key1键进行确定,并在数码管最右端显示,分别为1-12这12个档位,数值越大,转速越慢)
并结合Key2键确认旋转方向(按下按键则按相反方向进行旋转)
再结合Key3键控制步进电机旋转还是停止
代码解析
工程设计流程图如下:
- 反转部分代码
(只需要判断按键是否按下,包含按键消抖,就利用条件语句,选择不同的顺序,原来1 2 3 4对应的顺序表,现在反过来对应即可)
void Xstep_Process()
{
static uchar i = 1;
if( btRotationFlag == 0 )
{
switch( i++ )
{
case 1:
sbtS1 = 1; sbtS2 = 0; sbtS3 = 0; sbtS4 = 0; break;
case 2:
sbtS1 = 0; sbtS2 = 1; sbtS3 = 0; sbtS4 = 0; break;
case 3:
sbtS1 = 0; sbtS2 = 0; sbtS3 = 1; sbtS4 = 0; break;
case 4:
sbtS1 = 0; sbtS2 = 0; sbtS3 = 0; sbtS4 = 1; break;
default:
sbtS1 = 0; sbtS2 = 0; sbtS3 = 0; sbtS4 = 0; break;
}
if( i == 5 )
i = 1;
}
else
{
switch( i++ )
{
case 1:
sbtS1 = 0; sbtS2 = 0; sbtS3 = 0; sbtS4 = 1; break;
case 2:
sbtS1 = 0; sbtS2 = 0; sbtS3 = 1; sbtS4 = 0; break;
case 3:
sbtS1 = 0; sbtS2 = 1; sbtS3 = 0; sbtS4 = 0; break;
case 4:
sbtS1 = 1; sbtS2 = 0; sbtS3 = 0; sbtS4 = 0; break;
default:
sbtS1 = 0; sbtS2 = 0; sbtS3 = 0; sbtS4 = 0; break;
}
if( i == 5 )
i = 1;
}
}
- 数码管显示部分
设定其初始值为一定的档数,改变一个数字改变一下频率,得到不同的部分,再利用数码管部分的知识成功显示即可
void Seg7LedDisplay( uchar s, uchar e )
{
unsigned char arrSegSelect[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x40, 0x00};
static int i;
P2 = ( P2 & 0xf0 ) | i;
switch( i )
{
case 0:
P0 = arrSegSelect[cstDig0]; break;
case 1:
P0 = arrSegSelect[cstDig1]; break;
case 2:
P0 = arrSegSelect[cstDig2]; break;
case 3:
P0 = arrSegSelect[cstDig3]; break;
case 4:
P0 = arrSegSelect[cstDig4]; break;
case 5:
P0 = arrSegSelect[cstDig5]; break;
case 6:
P0 = arrSegSelect[cstDig6]; break;
case 7:
P0 = arrSegSelect[cstDig7]; break;
case 8:
P0 = cstDig8; break;
default:
P0 = 0x00; break;
}
if( ++i > e ) i = s;
}
- 主函数部分
包含其判断使能是否有效,即步进电机能否工作
以及是什么挡位的使能有效,从而得到多长时间的间隔改变转动频率
void main()
{
Init();
ucLedTmp = 0x00;
while( 1 )
{
if( btT10usFlag )
{
btT10usFlag = 0; T10us_Process();
}
if( btT100usFlag )
{
btT100usFlag = 0; T100us_Process();
}
if( btT1msFlag )
{
btT1msFlag = 0; T1ms_Process();
}
if( btT10msFlag )
{
btT10msFlag = 0; T10ms_Process();
}
if( btT100msFlag )
{
btT100msFlag = 0; T100ms_Process();
}
if( ( btTXmsFlag && btTXmsFlag_en ) )
{
btTXmsFlag = 0; TXms_Process();
}
}
}
-
中断服务处理部分
中断为10次,即计数10次,就会开启一种新状态 -
初始化部分
与步进电机类似,增加部分统计变量的初值 -
各节拍的处理函数
不同地方的显示,选择不同的频率
void T10us_Process()
{
}
void T100us_Process()
{
ucClockXms++;
if ( ucClockXms == ( cstClockXmsMaxNum ) )
{
ucClockXms = 0; btTXmsFlag = 1;
}
}
void T1ms_Process()
{
Seg7LedDisplay( cstDigBegin, cstDigEnd );
}
void T10ms_Process()
{
Key_Scan();
}
void TXms_Process()
{
Xstep_Process();
}
void T100ms_Process()
{
ucSpeed_Seg = ucSpeed;
}
- 按键扫描即消抖部分
参照按键消抖代码即可