步进电机控制+普中51单片机+普中官方
1 实验现象
通过ULN2003驱动模块控制28BYJ48步进电机运行方向及速度,当按下KEY1键可调节电机旋转方向;当按下KEY2键,电机加速(5档);当按下KEY3键,电机减速(5档);同时将电机转速档位显示在数码管上。
2 实验原理
(1)步进电机必须加驱动才可以运转,驱动信号必须为脉冲信号,没有脉冲的时候,步进电机禁止,加入适当的脉冲信号,就会以一定的角度(成为步角)转动。转动的速度和脉冲的频率成正比。
(2)步进电机具有瞬间启动和急速停止的优越特性;
(3)改变脉冲的顺序,可以方便的改变转动的方向。
3 系统框图
4 硬件设计
见《普中-2&普中-3&普中-4开发板原理图》:独立按键模块、单片机核心、动态数码管模块(包含74HC138)、五线四相步进电机模块。
5 软件设计
5.1 主函数
#include <REGX52.H> #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<MIN) speed+=1; } Nixie(1,6-speed); //显示数值越大,转速越快 stepmotor_send_pulse(step++,dir); if(step>8) step=0; delayms(speed); } }
5.2 步进电机控制函数
#include <REGX52.H> //定义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 <reg52.h> #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 <REGX52.H> #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 <intrins.h> 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
6 参考资料