发 帖  
原厂入驻New
[经验]

单片机控制步进电机

2020-10-17 10:44:31  365 单片机 c语言 嵌入式
分享
1
file:///C:\Users\ADMINI~1.MS-\AppData\Local\Temp\ksohtml4180\wps9.jpg
单片机控制步进电机正转 反转 加速 减速;
LCD1602实时显示步进电机的状态;F-正转 B-反转;数字越大,转速越大;
仿真原理图如下:
MCU和LCD1602显示模块:
file:///C:\Users\ADMINI~1.MS-\AppData\Local\Temp\ksohtml4180\wps10.jpg
ULN2803驱动和步进电机模块:
file:///C:\Users\ADMINI~1.MS-\AppData\Local\Temp\ksohtml4180\wps11.jpg
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;
                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);
                delay(5);
        }
       
        writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首
        for(i = 0; i < strlen(table1); i++){
                writeData(table1);
                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--);
}


评论

高级模式
您需要登录后才可以回帖 登录 | 注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
发经验
关闭

站长推荐 上一条 /9 下一条

快速回复 返回顶部 返回列表