用单片机控制步进电机正转 反转 加速 减速;
由LCD1602实时显示步进电机的状态;F-正转 B-反转;数字越大,转速越大;
仿真原理图如下:
MCU和LCD1602显示模块:
ULN2803驱动和步进电机模块:
C语言代码如下:
/*----------------------------- FileName: StepperMotor.h Function: 函数头文件 Author: Zhang Kaizhou Date: 2019-6-6 17:59:39 ------------------------------*/ #include <reg52.h> #include <string.h> #define uchar unsigned char #define uint unsigned int #define Factor 5 // 转速控制常数 /*LCD1602端口设置*/ sbit lcdrs = P1^0; sbit lcdrw = P1^1; sbit lcden = P1^2; /*步进电机驱动器端口设置*/ sbit direcChange = P1^3; // 方向翻转 sbit speedUp = P1^4; // 加速 sbit slowDown = P1^5; // 减速 /*主函数声明*/ void keyScan(); void execute(); /*LCD1602显示相关函数声明*/ void LCDInit(); void displayInit(); void display(uchar oper, uchar dat); void writeCommand(uchar command); void writeData(uchar dat); void delay(uchar xms);
/*------------------------------------------- FileName:main.c Function: MCU控制步进电机 Description:控制步进电机正转 反转 加速 减速; 由LCD1602实时显示步进电机的状态; F-正转 B-反转;数字越大,转速越大; --------------------------------------------- Author: Zhang Kaizhou Date: 2019-6-6 17:56:41 -------------------------------------------*/ #include "StepperMotor.h" uchar code pulseTable0[] = {0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x04, 0x08}; // 一相励磁(同一时刻只有一个线圈通电,旋转角1.8度) uchar code pulseTable1[] = {0x0c, 0x06, 0x03, 0x09, 0x09, 0x03, 0x06, 0x0c}; // 二相励磁(同一时刻有两个线圈通电,旋转角1.8度) uchar code pulseTable2[] = {0x08, 0x0c, 0x04, 0x06, 0x02, 0x03, 0x01, 0x09, 0x09, 0x01, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08}; // 一-二相励磁场(一二相交替励磁,旋转角0.9度) uchar speed = 0, startPos = 0; // 默认正转 bit oper = 0/*操作数*/, direcFlag = 0; // 初始状态为正向 void main(){ LCDInit(); // LCD1602显示初始化 displayInit(); while(1){ keyScan(); // 按键扫描 display(0, direcFlag); display(1, speed); execute(); } } /*按键扫描*/ void keyScan(){ if(!speedUp){ // 加速 delay(5); if(!speedUp){ if(speed < 4){ while(!speedUp); speed++; }else{ while(!speedUp); speed = 3; } } } if(!slowDown){ // 减速 delay(5); if(!slowDown){ if(speed != 0){ speed--; }else{ while(!slowDown); speed = 0; } } } if(!direcChange){ // 方向翻转 delay(5); if(!direcChange){ while(!direcChange); direcFlag = ~direcFlag; } } } /*步进电机控制执行函数*/ void execute(){ uchar i, j; startPos = (direcFlag == 0) ? 0 : 4; // 方向控制 for(i = startPos; i <= (startPos + 4); i++){ P2 = pulseTable0[i]; for(j = 0; j < (speed + 1) * Factor; j++){ // 用延时来控制脉冲输出的频率,从而控制步进电机转速 delay(10); } } }
/*----------------------------- FileName:display.c Function: LCD1602显示函数 Author: Zhang Kaizhou Date: 2019-6-6 17:58:42 ------------------------------*/ #include "StepperMotor.h" uchar code table0[] = {"Direction:"}; // 每行的字符数据 uchar code table1[] = {"Speed:"}; uchar code table2[] = {"1234"}; uchar code table3[] = {"FB"}; // F-正向 B-反向 /*初始化LCD1602的设置*/ void LCDInit(){ lcden = 0; // 拉低使能端,准备产生使能高脉冲信号 writeCommand(0x38); // 显示模式设置(16x2, 5x7点阵,8位数据接口) writeCommand(0x0c); // 开显示,不显示光标 writeCommand(0x06); // 写一个字符后地址指针自动加1 writeCommand(0x01); // 显示清零,数据指针清零 } /*LCD上电界面*/ void displayInit(){ uchar i; writeCommand(0x80); // 将数据指针定位到第一行首 for(i = 0; i < strlen(table0); i++){ writeData(table0[i]); delay(5); } writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首 for(i = 0; i < strlen(table1); i++){ writeData(table1[i]); delay(5); } } /*LCD显示函数*/ void display(uchar oper, uchar dat){ if(oper == 0){ // 方向显示 if(dat == 0){ // 正向 writeCommand(0x80 + strlen(table0)); // 数据指针定位到第一行空闲处 writeData(table3[0]); }else if(dat == 1){ // 反向 writeCommand(0x80 + strlen(table0)); // 数据指针定位到第一行空闲处 writeData(table3[1]); } } if(oper == 1){ // 速度显示 writeCommand(0x80 + 0x40 + strlen(table1)); // 数据指针定位到第二行空闲处 writeData(table2[dat]); } } /*写指令函数*/ void writeCommand(uchar command){ lcdrs = 0; // 命令选择 lcdrw = 0; P0 = command; delay(5); lcden = 1; // 产生一个正脉冲使能信号 delay(5); lcden = 0; } /*写数据函数*/ void writeData(uchar dat){ lcdrs = 1; // 数据选择 lcdrw = 0; P0 = dat; delay(5); lcden = 1; delay(5); lcden = 0; } /*延时函数*/ void delay(uchar xms){ uint i, j; for(i = xms; i > 0; i--) for(j = 110; j > 0; j--); }