步进电机驱动程序C语言

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了步进电机驱动程序C语言相关的知识,希望对你有一定的参考价值。

步进电机控制程序(c语言+51单片机)

#include<reg51.h>

#define uint unsigned int
#define uchar unsigned char
#define ms *77
// f = 12 M
#define LEDLen 4
#define Dj_star() IE=0x81; pri_dj=0;
#define Dj_stop() IE=0x00; pri_dj=1; P1=0xff; shache="0"; delay(800ms); delay(800ms);delay(400ms); shache = 1;
#define Chilun_Num 8
/* 齿轮数 8 个*/
#define set_display_num() LEDBuf[0] = tmp / 1000; LEDBuf[1] = tmp / 100 % 10; \
LEDBuf[2] = tmp / 10 % 10; LEDBuf[3] = tmp % 10;
uchar LEDBuf[LEDLen] = 0,0,0,0;
void read_num (); /* 读播码盘 到 set_round_num * 8 */
void display ();
void delay(uint delay_time) uint i; for (i=0; i < delay_time ; i++) ;
void run ();
void fx_run();

uint round_num = 0; /* 记录已转的 齿轮数 , 中断1次 加 1*/
uint set_round_num = 0; /* 播码盘设置 圈数 */
uint set_pwm_width = 0; /* 播码盘设置 步进电机 正向速度 */
bit one_round_flg = 0;
sbit led_1000 = P0^7; //use for display
sbit led_100 = P0^6; //use for display
sbit led_10 = P0^5; //use for display
sbit led_1 = P0^4; //use for display

sbit key_start = P3^0;
sbit key_puse = P3^0;
sbit key_clear = P3^1;
/* P3^2 接齿轮传感器 中断 */
sbit bujin_zx_stop = P3^3; /* 接步进电机 ,正向到位传感器 ,为 0 停机 */
sbit bujin_fx_stop = P3^4; /* 接步进电机 ,反向到位传感器 ,为 0 停机 */

sbit shache = P3^5; /* 接刹车控制继电器 0 电位有效 */
sbit pri_dj = P3^6; /* 接主电机控制继电器 0 电位有效 */

void main()
TCON = 0x01;
display();
while(1)
IE="0x00";
round_num = 0;
display();
if ( bujin_fx_stop ) fx_run();
while ( key_start );
delay ( 8ms );
if(!key_start)
read_num();
//set_round_num = 8;
while ( !key_start );
run ();
fx_run();




void run ()
#define Delay_time 180
/* 转一圈 50 次循环,每循环 4 步 ,50 * 4 = 200 , 200 * 1。8 = 360 */
uchar i ;
P1 = 0xff;
set_pwm_width = 15 + set_pwm_width / 10;
while ( 1 )

while( !shache | !key_start );
Dj_star();
for ( i="0" ; bujin_zx_stop & !pri_dj;i++ )
P1 = 0xf9;
delay ( Delay_time ); // bujin_zx_stop = P3^3;
P1 = 0xfc; // bujin_fx_stop = P3^4;
delay ( Delay_time); // key_puse = P3^0;
P1 = 0xf6; // key_clear = P3^1;
delay ( Delay_time ); // shache = P3^5;
P1 = 0xf3; // pri_dj = P3^6;
delay ( Delay_time );
if( i == set_pwm_width ) P1 = 0xff; i = 0; one_round_flg = 0; while ( !one_round_flg & key_puse );
if(!key_puse) delay(4ms); if(!key_puse) break;


P1 = 0xff;
if ( pri_dj ) break;

if ( !key_puse )
delay ( 8ms );
if ( !key_puse )
Dj_stop();
while ( !key_puse );
// next pree key
while( !shache );

while(1)
while ( key_puse & key_clear );
delay ( 8ms );
if ( !key_clear ) round_num = 0; display();
if ( !key_puse ) break;

while( !key_puse );
delay(8ms);
while( !key_puse );




void ext_int0(void) interrupt 0 /* 主电机 齿轮 中断 */
uint tmp;
EA = 0;
if( !pri_dj )
round_num ++;
if (round_num % Chilun_Num == 0 )
one_round_flg = 1;
tmp = round_num / Chilun_Num ;
set_display_num();
P0 = 0xf0;
P0 = P0 | LEDBuf[0] ;
led_1000 = 0;
P0 |= 0xf0;

P0 = 0xf0;
P0 = P0 | LEDBuf[1] ;
led_100 = 0;
P0 |= 0xf0;

P0 = 0xf0;
P0 = P0 | LEDBuf[2] ;
led_10 = 0;
P0 |= 0xf0;

P0 = 0xf0;
P0 = P0 | LEDBuf[3] ;
led_1 = 0;
P0 |= 0xf0;

P0 = 0xf0;

if ( round_num >= set_round_num ) Dj_stop();

EA = 0x81;


void display()
uchar i;
uint tmp = 0;
tmp = round_num / Chilun_Num ;
set_display_num();
for(i = 0; i < LEDLen ; i ++)
P0 = 0xf0;
P0 = P0 | LEDBuf[i] ;
if(i==0) led_1000 = 0; //P0^4
if(i==1) led_100 = 0; //P0^5
if(i==2) led_10 = 0; //P0^6
if(i==3) led_1 = 0; //P0^7
P0 |= 0xf0;

P0 = 0xf0;


void read_num()
/* 读播码盘 到 set_round_num ,set_pwm_width */
uchar tmp;
P2 = 0xFF;
P2 = 0xEF; // 1110 1111
delay ( 1ms );
tmp = ~(P2 | 0xF0);

P2 = 0xDF; // 1101 1111
delay ( 1ms );
tmp = (~(P2 | 0xF0 )) * 10 + tmp;
set_round_num = tmp;

P2 = 0xBF; // 1011 1111
delay ( 1ms );
tmp = (~(P2 | 0xF0));

P2 = 0x7F; // 0111 1111
delay ( 1ms );
tmp = (~(P2 | 0xF0)) * 10 + tmp;

set_round_num = set_round_num + tmp * 100;
set_round_num = set_round_num * Chilun_Num;

P2 = 0xFF;
P1 = 0xbF; // 0111 1111
delay ( 1ms );
tmp = ~(P2 | 0xF0) ;

P1 = 0xFF;
P2 = 0xFF;
P1 &= 0x7F; // 1011 1111
delay ( 1ms );
tmp = (~(P2 | 0xF0)) * 10 + tmp ;
set_pwm_width = tmp ;

P1 = 0xFF;
P2 = 0xFF;


void fx_run()
#define f_Delay_time 180
while ( bujin_fx_stop ) /* 反向 回车 直到 传感器 动作*/
P1 = 0xf3; //0011
delay ( f_Delay_time );
P1 = 0xf6; //0110
delay ( f_Delay_time );
P1 = 0xfc; //1100
delay ( f_Delay_time );
P1 = 0xf9; //1001
delay ( f_Delay_time );

P1 = 0xff;
参考技术A 您好,这样的情况建议您下载最新版本的驱动精灵,或是直接在线升级一下驱动精灵。希望可以帮到您。

步进电机S曲线加减速控制生成器-VB6.0实现

程序功能:生成步进电机S曲线运动数组代码
程序语言:VB6.0

对应硬件线路连接见上章:
https://blog.csdn.net/LuDanTongXue/article/details/87869557
对应单片机程序见上章(PC端程序显示正常,手机端程序后半段显示不出来):
https://blog.csdn.net/LuDanTongXue/article/details/87869806
程序详细使用方法请见:
https://blog.csdn.net/LuDanTongXue/article/details/87886580
程序下载地址:
https://download.csdn.net/download/ludantongxue/11114203

程序界面如下:

S曲线算法参照该博文:
https://blog.csdn.net/pengzhihui2012/article/details/52228822
源码如下:

Option Explicit
    Dim BuJuJiao As Double '步进电机步距角
    Dim F0 As Double '硬件频率
    Dim Nf As Double '定时器分频
    Dim v0 As Double '加速段启动速度
    Dim vt As Double '加速段最大速度
    Dim JSBuShu As Long '加速步数
    Dim JSJiaoDu As Double '加速段角度
    Dim XiFen As Double '驱动器细分
    Dim JSKuaiMan As Double '加速快慢,数值越大越慢
    Dim JSshijian As Double '加速时间
    Dim FenDuan As Double '将曲线分成梯形图
    Dim MCCiShu As Long '每个速断段脉冲次数
    Dim MCYuShu As Integer '分段不整除时最后的余数
    
    Dim Fmin As Double 'V0对应的脉冲频率
    Dim Fmax As Double 'Vt对应的脉冲频率
    Dim Fcurrent As Double '实时频率
    
    Dim DSChuZhi As Long '定时器1初值,采用溢出中断
    Dim i As Integer '计数
    Dim a0 As Long 'A0第一个脉冲的初值
    Dim DingShiQiFenPing As Integer '定时器1预分频数
    Dim ZhuanXiang As String '电机转动方向
    Public Function Max(a As Double, b As Double) As Double '求最大值
        If a < b Then
            Max = b
        ElseIf a >= b Then
            Max = a
        End If
    End Function
    Public Function ST(ax As Double, ay As Double, n As Double, m As Double) '图框初始化
    '图框初始化
        Dim Kuandanwei As Double
        Picture1.ScaleMode = 6 '设置图片框单位
        Kuandanwei = Picture1.Width / 400
        Picture1.ScaleTop = -Picture1.Height / 2 '定义坐标原点x
        Picture1.ScaleLeft = -Picture1.Width / 2 '-10 * Kuandanwei '定义坐标原点y
        Picture1.Circle (0, 0), 1000
    'X轴
        Picture1.Line (-8 * Kuandanwei, 0)-(380 * Kuandanwei, 0)
        Picture1.Line (380 * Kuandanwei, 0)-(370 * Kuandanwei, 10 * Kuandanwei)
        Picture1.Line (380 * Kuandanwei, 0)-(370 * Kuandanwei, -10 * Kuandanwei)
        Picture1.CurrentX = 380 * Kuandanwei
        Picture1.CurrentY = 0
        Picture1.Print "t"
    'Y轴
        Picture1.Line (0, 0.45 * Picture1.Height)-(0, -0.45 * Picture1.Height)
        Picture1.Line (0, -0.45 * Picture1.Height)-(-10 * Kuandanwei, -0.45 * Picture1.Height + 10 * Kuandanwei)
        Picture1.Line (0, -0.45 * Picture1.Height)-(10 * Kuandanwei, -0.45 * Picture1.Height + 10 * Kuandanwei)
        Picture1.CurrentX = 0
        Picture1.CurrentY = -0.5 * Picture1.Height
        Picture1.Print "S"
    '绘制坐标点
        Picture1.PSet (n * Kuandanwei, -ax * m / 3), vbRed
        Picture1.PSet (n * Kuandanwei, -ay * m / 3), vbBlue
        n = n + 1
        If n >= 360 Then
            n = n - 360
            Picture1.Cls
        End If
    End Function
    Public Function QuXian() '曲线图框初始化,BS步进电机步数为x轴,vt为Y轴
    '图框初始化
        
        Picture1.Cls
        Picture1.DrawWidth = 1
        Dim Bili As Double '绘图比例
        Bili = 0.7
        Dim Kuandanwei As Double 'x方向图片放缩比例
        Dim Gaodanwei As Double 'y方向图片放缩比例
        Form1.ScaleMode = 6 '设置FORM框单位
        Picture1.ScaleMode = 6 '设置图片框单位
        Kuandanwei = Picture1.Width / (JSBuShu) '根据步进电机总时间计算图片放缩比例
        Gaodanwei = Picture1.Height / Max(v0, vt)
        Picture1.ScaleTop = -Picture1.Height + 5 * Kuandanwei '定义坐标原点y
        Picture1.ScaleLeft = -5 * Kuandanwei '定义坐标原点x
        Picture1.CurrentX = 0
        Picture1.CurrentY = 0
        Picture1.Print "0"
    'X轴
        Dim x1 As Double
        Dim y1 As Double
        Dim x2 As Double
        Dim y2 As Double
        Dim x3 As Double
        Dim y3 As Double
        x1 = Bili * (JSBuShu * Kuandanwei)
        y1 = Bili * 0
        x2 = Bili * (x1 - 3) ' 5 * Kuandanwei)
        y2 = Bili * (y1 + 3) '5 * Kuandanwei)
        x3 = x2
        y3 = -y2
        Picture1.Line (0, 0)-(x1, y1)
        Picture1.Line (x1, y1)-(x2, y2)
        Picture1.Line (x1, y1)-(x3, y3)
        Picture1.CurrentX = x1
        Picture1.CurrentY = y1
        Picture1.Print Int(JSshijian * 1000) & "ms"
    'Y轴
        Dim x4 As Double
        Dim y4 As Double
        Dim x5 As Double
        Dim y5 As Double
        Dim x6 As Double
        Dim y6 As Double
        x4 = Bili * 0
        y4 = Bili * (-Max(v0, vt) * Gaodanwei)
        x5 = Bili * (x4 - 3) '-5* Kuandanwei)
        y5 = Bili * (y4 - 3) '-5* Kuandanwei)
        x6 = -x5
        y6 = y5
        Picture1.Line (0, 0)-(x4, y4)
        Picture1.Line (x4, y4)-(x5, y5)
        Picture1.Line (x4, y4)-(x6, y6)
        Picture1.CurrentX = x4 + Kuandanwei
        Picture1.CurrentY = y4
        Picture1.Print Max(v0, vt) & "r/s"
        
    '绘制坐标点
        Picture1.DrawWidth = 5
        Dim i As Integer
        For i = 1 To JSBuShu
            Picture1.PSet (Bili * i * Kuandanwei, Bili * -Gaodanwei * (v0 + (vt - v0) / (1 + Exp(-JSKuaiMan * (i - JSBuShu / 2) / (JSBuShu / 2))))), vbRed
        Next
    End Function
    Private Sub Command1_Click()
    BuJuJiao = Text2.Text
    F0 = Text3.Text
    Nf = Text4.Text
    v0 = Text5.Text
    vt = Text6.Text
    JSJiaoDu = Text7.Text
    XiFen = Text8.Text
    JSKuaiMan = Text9.Text
    If Text4.Text = 1 Then
    DingShiQiFenPing = 1
    ElseIf Text4.Text = 8 Then
    DingShiQiFenPing = 2
    ElseIf Text4.Text = 64 Then
    DingShiQiFenPing = 3
    ElseIf Text4.Text = 256 Then
    DingShiQiFenPing = 4
    ElseIf Text4.Text = 1024 Then
    DingShiQiFenPing = 5
    End If
    
    JSBuShu = JSJiaoDu / (BuJuJiao / XiFen)
    Fmin = v0 * 360 / (BuJuJiao / XiFen)
    Fmax = vt * 360 / (BuJuJiao / XiFen)
    
    Text1 = ""
    JSshijian = 0
    
    ''''''''''''''''''''''''''''加速段A0数组生成'''''''''''
        For i = 1 To JSBuShu
            Fcurrent = Fmin + (Fmax - Fmin) / (1 + Exp(-JSKuaiMan * (i - JSBuShu / 2) / (JSBuShu / 2)))
            DSChuZhi = 65535 - 1 / (Fcurrent * 2) * F0 / Nf '16位定时器
            If i <> JSBuShu Then
                Text1 = Text1 & "0X" & Hex(DSChuZhi) & ","
            Else
                Text1 = Text1 & "0X" & Hex(DSChuZhi)
            End If
            JSshijian = JSshijian + 1 / Fcurrent
        Next
    
    a0 = 65535 - 1 / ((Fmin + (Fmax - Fmin) / (1 + Exp(-JSKuaiMan * (1 - JSBuShu / 2) / (JSBuShu / 2)))) * 2) * F0 / Nf
    Text10 = JSBuShu
    Text12 = JSshijian * 1000
    Text1 = "A[" & JSBuShu & "]=" & Text1 & ";" & vbCrLf & vbCrLf
    
    ''''''''''''''''''''''''''''
    Text11.Text = (2 * F0 * BuJuJiao) / (65535 * Nf * 360 * XiFen) '计算最小启动速度
    
    QuXian '绘制速度曲线
    End Sub

微信/QQ:pph846375164

以上是关于步进电机驱动程序C语言的主要内容,如果未能解决你的问题,请参考以下文章

51单片机-步进电机控速正反转(原理图+源码+仿真+论文)

STM32F103+步进电机28BYJ-48+ULN2003 实现简单的正反转demo

步进电机S曲线加减速控制生成器-VB6.0实现

STM32F4驱动42步进电机(采用驱动器)

超声波+红外线避障小车(Arduino + L298P电机驱动扩展板)

Proteus仿真Arduino UNO利用Stepper库实现uln2003驱动步进电机转动