1 实验现象
通过ULN2003驱动模块控制28BYJ48步进电机运行方向及速度,当按下KEY1键可调节电机旋转方向;当按下KEY2键,电机加速(5档);当按下KEY3键,电机减速(5档);同时将电机转速档位显示在数码管上。
2 实验原理
(1)步进电机必须加驱动才可以运转,驱动信号必须为脉冲信号,没有脉冲的时候,步进电机禁止,加入适当的脉冲信号,就会以一定的角度(成为步角)转动。转动的速度和脉冲的频率成正比。
(2)步进电机具有瞬间启动和急速停止的优越特性;
(3)改变脉冲的顺序,可以方便的改变转动的方向。
3 系统框图
4 硬件设计
见《普中-2&普中-3&普中-4开发板原理图》:独立按键模块、单片机核心、动态数码管模块(包含74HC138)、五线四相步进电机模块。
5 软件设计
5.1 主函数
#include
#include "key.h"
#include "delayms.h"
#include "Nixie.h"
#include "stepmotor.h"
// 定义步进电机速度,值越小,速度越快
#define MAX 1 //延时时间,脉冲周期
#define MIN 5 //延时时间,脉冲周期
unsigned char key_num=0;
unsigned char dir=0; //默认逆时针方向
unsigned char step=0;
unsigned char speed=5;
void main()
{
while(1)
{
key_num=key();
if(key_num==1) //换向
{
dir=!dir;
}
else if(key_num==2) //加速,延时speed越小,速度越快
{
if(speed>MAX) speed-=1;
}
else if(key_num==3) //减速,延时speed越大,速度越慢
{
if(speed
Nixie(1,6-speed); //显示数值越大,转速越快
stepmotor_send_pulse(step++,dir);
if(step>8) step=0;
delayms(speed);
}
}
5.2 步进电机控制函数
#include
//定义ULN2003控制步进电机管脚
sbit IN_D=P1^0;
sbit IN_C=P1^1;
sbit IN_B=P1^2;
sbit IN_A=P1^3;
/**
* @brief 输出一个数据给ULN2003从而实现向步进电机发送一个脉冲
* @param step 指定步进序号,可选值0~7
* @param dir:方向选择,1:顺时针,0:逆时针
* @retval 无
*/
void stepmotor_send_pulse(unsigned char step,dir)
{
unsigned char temp;
if(dir==0) temp=7-step; //如果为逆时针旋转,调换节拍信号
else temp=step;
switch(temp) //8个节拍控制:A->AB->B->BC->C->CD->D->DA
{
case 0: IN_A=0;IN_B=0;IN_C=0;IN_D=1;break;
case 1: IN_A=0;IN_B=0;IN_C=1;IN_D=1;break;
case 2: IN_A=0;IN_B=0;IN_C=1;IN_D=0;break;
case 3: IN_A=0;IN_B=1;IN_C=1;IN_D=0;break;
case 4: IN_A=0;IN_B=1;IN_C=0;IN_D=0;break;
case 5: IN_A=1;IN_B=1;IN_C=0;IN_D=0;break;
case 6: IN_A=1;IN_B=0;IN_C=0;IN_D=0;break;
case 7: IN_A=1;IN_B=0;IN_C=0;IN_D=1;break;
default:IN_A=0;IN_B=0;IN_C=0;IN_D=0;break;//停止相序
}
}
#ifndef _stepmotor_h_
#define _stepmotor_h_
void stepmotor_send_pulse(unsigned char step,dir);
#endif
5.3 按键扫描函数
#include
#include "delayms.h"
sbit key1 = P3^1;
sbit key2 = P3^0;
sbit key3 = P3^2;
sbit key4 = P3^3;
/**
* @brief 获取独立按键键码
* @param 无
* @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
*/
unsigned char key()
{
unsigned char KeyNumber = 0;
if(key1==0){delayms(20);while(key1==0);delayms(20);KeyNumber=1;}
if(key2==0){delayms(20);while(key2==0);delayms(20);KeyNumber=2;}
if(key3==0){delayms(20);while(key3==0);delayms(20);KeyNumber=3;}
if(key4==0){delayms(20);while(key4==0);delayms(20);KeyNumber=4;}
return KeyNumber;
}
#ifndef _key_h_
#define _key_h_
unsigned char key();
#endif
5.4 数码管驱动函数
#include
#include "delayms.h"
sbit HC138_A=P2^2;
sbit HC138_B=P2^3;
sbit HC138_C=P2^4;
//数码管段码表,0-9
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
/**
* @brief 数码管显示
* @param Location 要显示的位置,范围:1~8
* @param Number 要显示的数字,范围:段码表索引范围
* @retval 无
*/
void Nixie(unsigned char Location,Number)
{
switch(Location) //位码输出
{
case 1:HC138_C=1;HC138_B=1;HC138_A=1;break;
case 2:HC138_C=1;HC138_B=1;HC138_A=0;break;
case 3:HC138_C=1;HC138_B=0;HC138_A=1;break;
case 4:HC138_C=1;HC138_B=0;HC138_A=0;break;
case 5:HC138_C=0;HC138_B=1;HC138_A=1;break;
case 6:HC138_C=0;HC138_B=1;HC138_A=0;break;
case 7:HC138_C=0;HC138_B=0;HC138_A=1;break;
case 8:HC138_C=0;HC138_B=0;HC138_A=0;break;
}
P0=NixieTable[Number]; //段码输出
delayms(1); //显示一段时间
P0=0x00; //段码清0,消影
}
#ifndef __NIXIE_H__
#define __NIXIE_H__
void Nixie(unsigned char Location,Number);
#endif
5.5 延时函数
#include
void delayms(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
while(xms--)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
#ifndef _delayms_h_
#define _delayms_h_
delayms(unsigned int xms);
#endif
相关文章