找回密码
 立即注册
楼主: 梁工

51开源,步进电机驱动 程序, 直接驱动, 或驱动步进电机驱动器 一共8个程序

  [复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:502
  • 最近打卡:2025-05-01 08:01:38
已绑定手机

1

主题

833

回帖

1441

积分

金牌会员

积分
1441
发表于 2024-9-29 12:26:48 | 显示全部楼层
感谢分享
靡不有初,鲜克有终
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:15
  • 最近打卡:2025-03-26 09:09:59

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-9-30 13:35:44 | 显示全部楼层
梁*** 发表于 2024-9-29 12:00
这要自己调试哦!
第一步:先确定Timer0的1ms中断正常(取反一个IO示波器观察)。
第二步:示波器观察4个 ...

梁工,您好,现在第一步 第二步 第三步都实现了,但是请问一个脉冲,电机转动多少角度?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:15
  • 最近打卡:2025-03-26 09:09:59

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-9-30 15:57:46 | 显示全部楼层
梁工,我现在移植后有几个不明白的地方,请您指点:

1.脉冲和电机角度或者圈数对应关系;(我发现目标频率改了也会影响角度,因为我希望得到的效果,按下按键电机旋转90度)
2.我加了一个按键,但是发现按键按了之后会先卡顿几下然后在转,并且卡顿时电流很大,电机发烫;(如视频1,频率2400,脉冲数800)
3.去掉按键后,直接转很丝滑;(如视频2,频率2400,脉冲数800)

1.MP4

23.21 MB, 下载次数: 161

2.MP4

3.99 MB, 下载次数: 158

点评

只要不失步,改变频率不会改变角度。  详情 回复 发表于 2024-10-6 15:17
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:418
  • 最近打卡:2025-05-01 08:48:18

24

主题

108

回帖

448

积分

中级会员

积分
448
发表于 2024-9-30 23:19:39 | 显示全部楼层
谢谢,明天打板试验一下
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:233
  • 最近打卡:2025-05-01 21:41:37

0

主题

62

回帖

642

积分

高级会员

积分
642
发表于 2024-10-1 19:05:25 | 显示全部楼层
感谢楼主分享,给楼主点赞!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:50
  • 最近打卡:2025-04-30 22:59:03

73

主题

5882

回帖

1万

积分

超级版主

积分
12073
发表于 2024-10-6 15:17:49 | 显示全部楼层
huatl*** 发表于 2024-9-30 15:57
梁工,我现在移植后有几个不明白的地方,请您指点:

1.脉冲和电机角度或者圈数对应关系;(我发现目标频率 ...

只要不失步,改变频率不会改变角度。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:455
  • 最近打卡:2025-05-01 00:44:09

6

主题

81

回帖

2118

积分

金牌会员

积分
2118
发表于 2024-10-7 12:41:44 | 显示全部楼层
正在准备用STC8G1K08-20P做一个驱动两个步进电机的功能,不过我要转转72度,看看能不能参考
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:15
  • 最近打卡:2025-03-26 09:09:59

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-10-8 10:56:47 | 显示全部楼层
梁*** 发表于 2024-10-6 15:17
只要不失步,改变频率不会改变角度。

好的,梁工,那请问下失步的原因呢?还有问题2和3出现的原因是什么呢?
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:15
  • 最近打卡:2025-03-26 09:09:59

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-10-9 08:46:34 | 显示全部楼层
梁工好,您好,能麻烦您帮我看看嘛?我希望得到的是按下按键转一圈,转到一圈即使按着按键也不动了,松开按键,回到原点。但是现在实际情况是这样,按着按键转一圈后,不停下 还会缓慢转动,但是释放按键后,回到原点,不在转动,这是怎么回事呢。并且调用StopMotor1后电机怎么都不动了

#include "STC8Hxxx.h"       //包含此头文件后,不需要再包含"reg51.h"头文件
#include "test.h"
#include        "SineTable-256.h"
#define     MAIN_Fosc       24000000L   //定义主时钟

/*************  功能说明    **************
程序使用
AIN1-P1.1
AIN2-P1.2
BIN1-P1.5
BIN2-P3.4
驱动步进电机
******************************************/
#include "intrins.h"
sfr VRTRIM = 0xA6;
#define CLKSEL (*(unsigned char volatile xdata *)0xfe00)
#define CLKDIV (*(unsigned char volatile xdata *)0xfe01)
//下表为 STC8H1K08-20Pin 的参数列表
#define ID_ROMADDR ((unsigned char code *)0x1ff9)
#define VREF_ROMADDR (*(unsigned int code *)0x1ff7)
#define F32K_ROMADDR (*(unsigned int code *)0x1ff5)
#define T22M_ROMADDR (*(unsigned char code *)0x1ff4) //22.1184MHz
#define T24M_ROMADDR (*(unsigned char code *)0x1ff3) //24MHz
#define T20M_ROMADDR (*(unsigned char code *)0x1ff2) //20MHz
#define T27M_ROMADDR (*(unsigned char code *)0x1ff1) //27MHz
#define T30M_ROMADDR (*(unsigned char code *)0x1ff0) //30MHz
#define T33M_ROMADDR (*(unsigned char code *)0x1fef) //33.1776MHz
#define T35M_ROMADDR (*(unsigned char code *)0x1fee) //35MHz
#define T36M_ROMADDR (*(unsigned char code *)0x1fed) //36.864MHz
#define VRT20M_ROMADDR (*(unsigned char code *)0x1fea) //VRTRIM_20M
#define VRT35M_ROMADDR (*(unsigned char code *)0x1fe9) //VRTRIM_35M

//================== 步进电机相关变量定义 ===================

bit                B_M1_RunEn;                //运行允许
bit                B_M1_RunEnTmp;        //用于检测电机从运行到停止的事件
bit                B_M1_DIR;                //运行方向, 0:顺时针(正转), 1:逆时针(反转)
bit                B_f1_update;        //请求刷新频率值
bit                B_TIMER1_12T;        //定时器1时钟模式
u16                f1_period;                //当前频率对应的周期
u16                f1;                                //当前频率
u16                f1_set;                        //目标频率
u16                f1_step;                //加减速频率变化的步长
u16                M1_UpPulse;                //加(减)速脉冲数
u16                M1_PulseCnt;        //电机运行总脉冲数, 为0则连续运行
u16                M1_DownCnt;                //运行到要减速输出的脉冲数
u8                M1_StepCnt;                //步数计数
u8                M1_devide;                //细分数  1, 2, 4, 8, 16, 32, 64
u8                M1_step;                //步距, M1_step = 64 / M1_devide.
//===========================================================
sbit A1F = P1^1;
sbit A2F = P1^2;
sbit B1F = P1^5;
sbit B2F = P3^4;
sbit SLEEP = P1^4;
sbit DECAY = P1^0;
sbit up = P3^2;
sbit down = P3^3;
sbit slow_down = P3^5;
sbit test_flag = P3^6;
sbit nFAULT = P1^3;
bit        B_1ms;        //1ms时隙标志

unsigned int speed;
unsigned char STEP;
unsigned char LOOP;
unsigned int temp;
unsigned int flag_up;
unsigned int flag_down;
unsigned int flag_slow_down;
unsigned int flag_up_N = 1;
unsigned int flag_down_N = 1;
unsigned int flag_slow_down_N = 1;
unsigned char up_press_number;
unsigned char down_press_number;
unsigned char slow_down_press_number;
unsigned char up_no_press_number;
unsigned char down_no_press_number;
unsigned char slow_down_no_press_number;
unsigned char up_locked;
unsigned char down_locked;
unsigned char slow_down_locked;
unsigned int ms_cnt;
unsigned int P_CNT;
unsigned int p_flag = 0;
unsigned int ms_flag;
unsigned int f_pl;//频率
unsigned char pwm_duty;//占空比
unsigned char Flag_jushengState = 0;//进入举升标志位  =1进入举升  =0举升回转结束
unsigned char Flag_xiajiangState = 0;//进入下降标志位  =1进入下降  =0下降回转结束
unsigned char Flag_huanjiangState = 0;//进入缓降标志位  =1进入缓降  =0缓降回转结束
unsigned char Flag_jushengState_N = 0;//进入举升标志位  =1进入举升  =0举升回转结束
unsigned char Flag_xiajiangState_N = 0;//进入下降标志位  =1进入下降  =0下降回转结束
unsigned char Flag_huanjiangState_N = 0;//进入缓降标志位  =1进入缓降  =0缓降回转结束
unsigned char guzhang_number;
unsigned char jusheng_enable = 0;
unsigned char jusheng_back_enable = 0;
unsigned char xiajiang_enable = 0;
unsigned char xiajiang_back_enable = 0;
unsigned char huanjiang_enable = 0;
unsigned char huanjiang_back_enable = 0;
unsigned char DIR;


/*************        本地函数声明        **************/
void delay_ms(unsigned int ms);
void Delay10ms(void);
void Driver();
void fDriver();
void STEP_MOTOR_Driver(unsigned char RL);
void STEP_MOTOR_NUM(unsigned char RL, unsigned int num);
void STEP_MOTOR_LOOP(unsigned char RL,unsigned char LOOP);
void         PWMA_config(void);
u8                Timer1_Config(u8 t, u32 reload);        //t=0: reload值是主时钟周期数,  t=1: reload值是时间(单位us)
u8                Timer0_Config(u8 t, u32 reload);        //t=0: reload值是主时钟周期数,  t=1: reload值是时间(单位us), 返回0正确, 返回1装载值过大错误.
void        UART1_config(u32 brt, u8 timer, u8 io);        // brt: 通信波特率,  timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1,  =1: 切换到P3.6 P3.7,  =2: 切换到P1.6 P1.7,  =3: 切换到P4.3 P4.4
void         UART1_PrintString(u8 *puts);
void         UART1_TxByte(u8 dat);                // 串口1发送一个字节      
void         RX1_process(void);                        // 串口1处理函数
u16                GetStep(u16 f, u16 f_set);        // 计算速度变化步进长度
void        GetDownPulse(void);                        // 由M1_PulseCnt(总脉冲数) 和 M1_UpPulse(加速脉冲数) 计算开始减速的脉冲数, .
void        LoadTimer1(void);                        // 计算更新频率的时间参数
void        GetFreq1(void);                                // 计算加减速频率
void        StopMotor1(void);                        // 停止运行一个电机
void        RunMotor1(void);                        // 启动运行一个电机
void        LockMotor1(void);                        //电机停止时减小电流锁转子
/******************** 主函数 **************************/
void main(void)
{
        P_SW2 |= 0x80;  //扩展寄存器(XFR)访问使能

    //选择 24MHz
        CLKDIV = 0x04;
        IRTRIM = T24M_ROMADDR;
        VRTRIM = VRT20M_ROMADDR;
        IRCBAND = 0x00;
        CLKDIV = 0x00;
        MCLKOCR = 0x04;
        ms_cnt = 0;
        P_CNT = 0;
        ms_flag = 0;
        p_flag = 0;
           P1M1 = 0x08;   
        P1M0 = 0xf7;   //设置P1推挽输出         //P1^3设置为高阻输入
    P3M1 = 0x2c;                                           //           0 0 1 0 1 1 0 0
        P3M0 = 0xd3;   //设置P3推挽输出和高阻输入           1 1 0 1 0 0 1 1
        DECAY = 0;
        SLEEP = 1;
    PWMA_config();
        Timer0_Config(0, MAIN_Fosc / 1000);        //t=0: reload值是主时钟周期数,  t=1: reload值是时间(单位us)
        Timer1_Config(1, 20000);                        //t=0: reload值是主时钟周期数,  t=1: reload值是时间(单位us, 这里随便给个值)
        EA = 1;
        B_M1_RunEn    = 0;
        B_M1_RunEnTmp = 0;
        M1_StepCnt = 0;
        M1_devide = 64;                                 //细分数  1, 2, 4, 8, 16, 32, 64
        M1_step = 64 / M1_devide;         //倒数关系.
      
        while (1)
        {
                if(B_1ms)        //1ms时隙
                {
                        B_1ms = 0;
                       
                        if(B_M1_RunEn)        //加减速处理
                        {
                                GetFreq1();
                                if(f1 < 100)      
                                {
                                        B_M1_RunEn = 0;        //停止

                                }      

                        }

//                        F0 = B_M1_RunEnTmp;
//                        B_M1_RunEnTmp = B_M1_RunEn;
//                        if(F0 && !B_M1_RunEnTmp)        LockMotor1();        //检测到电机停止, 则锁转子, 减小电流

                if((flag_up == 0)&&(flag_down == 1)&&(flag_slow_down == 1)&&(Flag_xiajiangState == 0)&&(Flag_huanjiangState == 0)) //正转
                        {  
                                Flag_jushengState=1;//进入举升标志位  =1进入举升  =0举升回转结束
                                if(!B_M1_RunEn)         f1 = 200;
                                M1_PulseCnt = 12800;
                                B_M1_DIR = 0;
                                if(P_CNT < 1)
                                {
                                        f1_set = 65000;
                                        RunMotor1();
                                        P_CNT++;
                                }
                                else if (P_CNT >= 1)
                                {
                                        P_CNT = 1;
                                }
                                       
                       
               
                        }
                else if((flag_up == 1)&&(Flag_jushengState==1)&&(Flag_xiajiangState == 0)&&(Flag_huanjiangState == 0))        //举升松开
                        {
                                if(!B_M1_RunEn)         f1 = 200;
                                M1_PulseCnt = 12800;
                                B_M1_DIR = 1;

                                if(P_CNT == 0)
                                {
                                        Flag_jushengState=0;      
                                }
                                else
                                {
                                        if(P_CNT == 0)
                                        {
                                                Flag_jushengState=0;
                                        }
                                        else
                                        {
                                                if(P_CNT>0)
                                                {
                                                        f1_set = 65000;
                                                        RunMotor1();
                                                        P_CNT --;
                                                }
                                        }
                                }                              
                        }//end  else
                else if((flag_down == 0)&&(flag_up == 1)&&(flag_slow_down == 1)&&(Flag_jushengState == 0)&&(Flag_huanjiangState == 0))
               
                        {
                                Flag_xiajiangState=1;//进入下降标志位  =1进入下降  =0下降回转结束
                                if(!B_M1_RunEn)         f1 = 200;
                                M1_PulseCnt = 12800;
                                B_M1_DIR = 1;
                                if(P_CNT < 1)
                                {
                                        f1_set = 65000;
                                        RunMotor1();
                                        P_CNT++;
                                }
                                else if(P_CNT >= 1)
                                {      
                                        P_CNT = 1;
                                }
                        }//        end  if(flag_down == 0) //下降
                       
                        //下降松开执行程序      
                        else if((flag_down == 1)&&(Flag_xiajiangState==1)&&(Flag_jushengState == 0)&&(Flag_huanjiangState == 0))        //下降松开
                        {
                                if(!B_M1_RunEn)         f1 = 200;
                                M1_PulseCnt = 12800;
                                B_M1_DIR = 0;
                                if(P_CNT == 0)
                                {
                                        Flag_xiajiangState=0;;      
                                }
                                else
                                {
                                        if(P_CNT == 0)
                                        {
                                                Flag_xiajiangState=0;
                                        }
                                        else
                                        {
                                                if(P_CNT>0)
                                                {
                                                        f1_set = 65000;
                                                        RunMotor1();
                                                        P_CNT --;
                                                }
                                        }                       
                                }
                        }//end  else
                                //缓降45°执行程序
                        else if((flag_slow_down == 0)&&(flag_up == 1)&&(flag_down == 1)&&(Flag_jushengState == 0)&&(Flag_xiajiangState == 0))
                        {
                                Flag_huanjiangState=1;//进入缓降45°标志位  =1进入缓降45°  =0缓降45°回转结束
                                if(!B_M1_RunEn)         f1 = 200;
                                M1_PulseCnt = 6400;
                                B_M1_DIR = 1;
                                if(P_CNT < 1)
                                {
                                        f1_set = 65000;
                                        RunMotor1();
                                           P_CNT++;
                                        }
                                else if(P_CNT >= 1)
                                {
                                        P_CNT = 1;
                                }
                        }//        end  if(flag_slow_down == 0) //缓降45°
                       
                        //缓降45°松开执行程序      
                        else if((flag_slow_down == 1)&&(Flag_huanjiangState==1)&&(Flag_jushengState == 0)&&(Flag_xiajiangState == 0))        //缓降45°松开
                        {
                                if(!B_M1_RunEn)         f1 = 200;
                                M1_PulseCnt = 6400;
                                B_M1_DIR = 0;
                                if(P_CNT == 0)
                                {
                                        Flag_huanjiangState=0;
                                }
                                else
                                {
                                        if(P_CNT == 0)
                                        {
                                                Flag_huanjiangState=0;
                                        }
                                        else
                                        {
                                                if(P_CNT>0)
                                                {
                                                        f1_set = 65000;
                                                        RunMotor1();
                                                        P_CNT --;
                                                }
                                        }                       
                                }//end  else
                        }                                       
                }      
        }
}
#define        UpTime        100                //加(减)速时间(ms)

u16        GetStep(u16 f, u16 f_set)        //计算速度变化步进长度
{
        u16        i;
        M1_UpPulse = (u16)((u32)(f + f_set)*UpTime / 2000);        // 理论加速脉冲数
        if(f_set >= f)        f_set = f_set - f;                //计算频率差
        else                        f_set = f - f_set;                //计算频率差
        i = f_set / UpTime;                                // 加(减)速步进
        if(i == 0)        i = 1;        //步进不能为0
        return        i;                        //返回加减速步进值
}

void        GetDownPulse(void)        // 由M1_PulseCnt(总脉冲数) 和 M1_UpPulse(加速脉冲数) 计算开始减速的脉冲数, .
{
        u16 pulse;
        if(M1_PulseCnt != 0)        //运行总脉冲数非0才有开始减速脉冲数
        {
                pulse = M1_UpPulse * 2;                //加减速脉冲数之和 = M1_UpPulse * 2
                if(M1_PulseCnt >= pulse)        pulse = M1_UpPulse;                        //脉冲数 >= 加减速脉冲数之和, 则减速脉冲数按理论计算值
                else                                                pulse = M1_PulseCnt / 2;        //脉冲数 <  加减速脉冲数之和, 则平分脉冲
                M1_DownCnt = M1_PulseCnt - pulse;                                                // 电机开始减速需要走过的脉冲数;
        }
}

void        LoadTimer1(void)        //计算更新频率的时间参数
{
        if(f1 < 100)        f1 = 90;
        if(f1 < 800)        //频率太低用12T模式
        {
                B_TIMER1_12T = 1;
                f1_period = 65536UL - MAIN_Fosc/12/f1;
        }
        else
        {
                B_TIMER1_12T = 0;
                f1_period = 65536UL - MAIN_Fosc/f1;
        }

        B_f1_update = 1;        //请求刷新
}

/************************************/
void                GetFreq1(void)        // 计算加减速频率
{
        if(f1 < f1_set)                //加速
        {
                f1 += f1_step;
                if(f1 > f1_set)        f1 = f1_set;                //目标频率已到
                LoadTimer1();
        }
        else if(f1 > f1_set)                //减速
        {
                if(f1 < f1_step)        f1 = 0;
                else                                f1 -= f1_step;
                if(f1 < f1_set)                f1 = f1_set;        //目标频率已到
                LoadTimer1();
        }
}

void        StopMotor1(void)                //停止运行一个电机
{
        f1_set  = 90;        //小于100Hz则停止
        f1_step = GetStep(f1, f1_set);

//        A1F = 0; PWMA_ENO &= ~0x02;
//        A2F = 0; PWMA_ENO &= ~0x04;
//        B1F = 0; PWMA_ENO &= ~0x20;
//        B2F = 0; PWMA_ENO &= ~0x40;      
}

void        RunMotor1()                //启动运行一个电机
{
//        PWMA_ENO   |= 0x02;
//        PWMA_ENO   |= 0x04;
//        PWMA_ENO   |= 0x20;
//        PWMA_ENO   |= 0x40;

        f1_step = GetStep(f1, f1_set);
        GetDownPulse();
               
        if(!TR1 || !B_M1_RunEn)
        {
                PWMA_ENO   |= 0x02;
                PWMA_ENO   |= 0x04;
                PWMA_ENO   |= 0x20;
                PWMA_ENO   |= 0x40;
                B_M1_RunEn = 1;
                TR1 = 0;
                LoadTimer1();
                TL1 = (u8)(f1_period % 256);
                TH1 = (u8)(f1_period / 256);
                TR1 = 1;
        }
}

//========================================================================
// 函数: void delay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2021-3-9
// 备注:
//========================================================================
void delay_ms(unsigned int ms)
{
     unsigned int i;
     do{
          i = MAIN_Fosc / 10000;
          while(--i);   //10T per loop
     }while(--ms);
}
void Delay1ms(void)        //@24.000MHz
{
        unsigned char data i, j;

        _nop_();
        i = 32;
        j = 40;
        do
        {
                while (--j);
        } while (--i);
}

void Delay10ms(void)        //@24.000MHz
{
        unsigned char data i, j;

        i = 234;
        j = 115;
        do
        {
                while (--j);
        } while (--i);
}
/******************** PWM配置函数 **************************/
void PWMA_config()
{
        P_SW2 |= 0x80;                //SFR enable   

        PWMA_PSCR = 0;        // 预分频寄存器, 分频 Fck_cnt = Fck_psc/(PSCR[15:0}+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)), 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
        PWMA_DTR  = 24;                // 死区时间配置, n=0~127: DTR= n T,   0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T,  
                                                //                                0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T,   0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T,
        PWMA_ARR = 400;        // 自动重装载寄存器,  控制PWM周期
        PWMA_CCER1  = 0;
        PWMA_CCER2  = 0;
        PWMA_SR1    = 0;
        PWMA_SR2    = 0;
        PWMA_ENO    = 0;
        PWMA_PS     = 0;
        PWMA_IER    = 0;
//        PWMA_ISR_En = 0;

        PWMA_CCMR1  = 0x68;                // 通道模式配置, PWM模式1, 预装载允许
        PWMA_CCR1   = 4;                // 比较值, 控制占空比(高电平时钟数)
        PWMA_CCER1 |= 0x05;                // 开启比较输出, 高电平有效
        PWMA_PS    |= 0;                // 选择IO, 0:选择P1.0 P1.1, 1:选择P2.0 P2.1, 2:选择P6.0 P6.1,
        PWMA_ENO   |= 0x02;                // IO输出允许,  bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P,  bit3: ENO2N,  bit2: ENO2P,  bit1: ENO1N,  bit0: ENO1P
//        PWMA_IER   |= 0x02;                // 使能中断

        PWMA_CCMR2  = 0x68;                // 通道模式配置, PWM模式1, 预装载允许
        PWMA_CCR2   = 0;                // 比较值, 控制占空比(高电平时钟数)
        PWMA_CCER1 |= 0x50;                // 开启比较输出, 高电平有效
        PWMA_PS    |= (0<<2);        // 选择IO, 0:选择P1.2 P1.3, 1:选择P2.2 P2.3, 2:选择P6.2 P6.3,
        PWMA_ENO   |= 0x04;                // IO输出允许,  bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P,  bit3: ENO2N,  bit2: ENO2P,  bit1: ENO1N,  bit0: ENO1P
//        PWMA_IER   |= 0x04;                // 使能中断

        PWMA_CCMR3  = 0x68;                // 通道模式配置, PWM模式1, 预装载允许
        PWMA_CCR3   = 0;                // 比较值, 控制占空比(高电平时钟数)
        PWMA_CCER2 |= 0x05;                // 开启比较输出, 高电平有效
        PWMA_PS    |= (0<<4);        // 选择IO, 0:选择P1.4 P1.5, 1:选择P2.4 P2.5, 2:选择P6.4 P6.5,
        PWMA_ENO   |= 0x20;                // IO输出允许,  bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P,  bit3: ENO2N,  bit2: ENO2P,  bit1: ENO1N,  bit0: ENO1P
//        PWMA_IER   |= 0x08;                // 使能中断

        PWMA_CCMR4  = 0x68;                // 通道模式配置, PWM模式1, 预装载允许
        PWMA_CCR4   = 0;                // 比较值, 控制占空比(高电平时钟数)
        PWMA_CCER2 |= 0x50;                // 开启比较输出, 高电平有效
        PWMA_PS    |= (3<<6);        // 选择IO, 0:选择P1.6 P1.7, 1:选择P2.6 P2.7, 2:选择P6.6 P6.7, 3:选择P3.3 P3.4
        PWMA_ENO   |= 0x40;                // IO输出允许,  bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P,  bit3: ENO2N,  bit2: ENO2P,  bit1: ENO1N,  bit0: ENO1P
//        PWMA_IER   |= 0x10;                // 使能中断

        PWMA_BKR    = 0x80;                // 主输出使能 相当于总开关
        PWMA_CR1    = 0x81;                // 使能计数器, 允许自动重装载寄存器缓冲, 边沿对齐模式, 向上计数,  bit7=1:写自动重装载寄存器缓冲(本周期不会被打扰), =0:直接写自动重装载寄存器本(周期可能会乱掉)
        PWMA_EGR    = 0x01;                //产生一次更新事件, 清除计数器和预分频计数器, 装载预分频寄存器的值
//        PWMA_ISR_En = PWMA_IER;        //设置标志允许通道1~4中断处理
}

//        PWMA_PS   = (0<<6)+(0<<4)+(0<<2)+0;        //选择IO, 4项从高到低(从左到右)对应PWM1 PWM2 PWM3 PWM4, 0:选择P1.x, 1:选择P2.x, 2:选择P6.x,
//  PWMA_PS    PWM4N PWM4P    PWM3N PWM3P    PWM2N PWM2P    PWM1N PWM1P
//    00       P1.7  P1.6     P1.5  P1.4     P1.3  P1.2     P1.1  P1.0
//    01       P2.7  P2.6     P2.5  P2.4     P2.3  P2.2     P2.1  P2.0
//    02       P6.7  P6.6     P6.5  P6.4     P6.3  P6.2     P6.1  P6.0
//    03       P3.3  P3.4      --    --       --    --       --    --

/******************** 按键函数 **************************/
void Key_scan()
{      

        if(up == 0)         //举升按键按下
        {
                        up_press_number+=1;
                        up_no_press_number = 0;
                        if( up_press_number >= 4)
                        {
                                flag_up = 0;
                            up_press_number = 0;      
                        }
        }
      
        else                 //举升按键松开
        {
                up_press_number = 0;
                up_no_press_number++;
                if(up_no_press_number >= 4)
                {
                        flag_up = 1;
                        up_no_press_number = 0;
                }
        }
        if(down == 0)//下降按键按下
        {
                        down_press_number+=1;
                        down_no_press_number = 0;
                        if( down_press_number >= 4)
                        {
                                flag_down = 0;
                                down_press_number = 0;
                        }
        }
        else           //下降按键松开
        {
                down_press_number = 0;
                down_no_press_number++;
                if(down_no_press_number >= 4)
                {
                        flag_down = 1;
                        down_no_press_number = 0;      
                }
        }
        if(slow_down == 0)//缓降按键按下
        {
                slow_down_press_number+=1;
                slow_down_no_press_number = 0;
                if( slow_down_press_number >= 4)
                {
                        flag_slow_down = 0;
                        slow_down_press_number = 0;
                }               
        }
        else                         //缓降按键松开
        {
                slow_down_press_number = 0;
                slow_down_no_press_number++;
                if(slow_down_no_press_number >= 4)
                {
                        flag_slow_down = 1;
                        slow_down_no_press_number = 0;
                }
        }
      
}

//========================================================================
// 函数: u8        Timer1_Config(u8 t, u32 reload)
// 描述: timer1初始化函数.
// 参数:      t: 重装值类型, 0表示重装的是系统时钟数, 其余值表示重装的是时间(us).
//       reload: 重装值.
// 返回: 0: 初始化正确,  1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-3-5
//========================================================================
u8        Timer1_Config(u8 t, u32 reload)        //t=0: reload值是主时钟周期数,  t=1: reload值是时间(单位us)
{
        TR1 = 0;        //停止计数

        if(t != 0)        reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL);        //重装的是时间(us), 计算所需要的系统时钟数.
        if(reload >= (65536UL * 12))        return 1;        //值过大, 返回错误
        if(reload < 65536UL)        AUXR |= 0x40;                //1T mode
        else
        {
                AUXR &= ~0x40;        //12T mode
                reload = reload / 12;
        }
        reload = 65536UL - reload;
        TH1 = (u8)(reload >> 8);
        TL1 = (u8)(reload);

        ET1 = 1;        //允许中断
        PT1 = 1;        //高优先级中断
        TMOD = (TMOD & ~0x30) | (0 << 4);        //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装
        TR1 = 1;        //开始运行
        return 0;
}






//========================================================================
// 函数: void timer1_ISR (void) interrupt TIMER1_VECTOR
// 描述:  timer1中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void timer1_ISR (void) interrupt TIMER1_VECTOR
{
        u8                area;                //区间0~3
        u8                pwm_A;                //A相spwm
        u8                pwm_B;                //B相spwm


        if(B_M1_RunEn)        //电机允许运转
        {
                pwm_A = M1_StepCnt * M1_step;        // A相步数计数, M1_step为细分对应的步距
                area  = pwm_A / 64;                                // 区间0~3
                pwm_B = pwm_A + 64;                                // B相步数计数
                pwm_A = T_SIN[pwm_A];                        // A相sPWM值
                pwm_B = T_SIN[pwm_B];                        // A相sPWM值
               
                if(area == 0)                        //0区间
                {
                        PWMA_CCR1L = pwm_A;                // A+ = sin(A)
                        PWMA_CCR2L = 0;                        // A- = 0
                        PWMA_CCR3L = pwm_B;                // B+ = cos(A) = sin(A+64)
                        PWMA_CCR4L = 0;                        // B- = 0
                }
                else if(area == 1)                //1区间
                {
                        PWMA_CCR1L = pwm_A;                // A+ = sin(A)
                        PWMA_CCR2L = 0;                        // A- = 0
                        PWMA_CCR3L = 0;                        // B+ = 0
                        PWMA_CCR4L = pwm_B;                // B- = cos(A) = sin(A+64)
                }
                else if(area == 2)                //2区间
                {
                        PWMA_CCR1L = 0;                        // A+ = sin(A)
                        PWMA_CCR2L = pwm_A;                // A- = 0
                        PWMA_CCR3L = 0;                        // B+ = 0
                        PWMA_CCR4L = pwm_B;                // B- = cos(A) = sin(A+64)
                }
                else                                        //3区间
                {
                        PWMA_CCR1L = 0;                        // A+ = sin(A)
                        PWMA_CCR2L = pwm_A;                // A- = 0
                        PWMA_CCR3L = pwm_B;                // B+ = cos(A) = sin(A+64)
                        PWMA_CCR4L = 0;                        // B- = 0
                }

                if(B_M1_DIR == 0)        M1_StepCnt++;        //正转, 下一步, M1_step为细分对应的步距
                else                                M1_StepCnt--;        //反转, 下一步, M1_step为细分对应的步距

                if(M1_PulseCnt != 0)        //总脉冲数非0减1
                {
                        if(--M1_PulseCnt == 0)        B_M1_RunEn = 0;
                }
                if(M1_DownCnt  != 0)        //减速时刻脉冲数减1
                {
                        if(--M1_DownCnt  == 0)        f1_set  = 200;
                }
        }

        if(B_f1_update)        //刷新频率数据
        {
                B_f1_update = 0;
                TR1 = 0;
                TL1 = (u8)(f1_period % 256);
                TH1 = (u8)(f1_period / 256);
                if(B_TIMER1_12T)        AUXR &= ~0x40;        //12T mode
                else                                AUXR |=  0x40;        //1T mode
                TR1 = 1;
        }
}

void        LockMotor1(void)        //电机停止时减小电流锁转子
{
        u8                area;                //区间0~3
        u8                pwm_A;                //A相spwm
        u8                pwm_B;                //B相spwm
      
        pwm_A = M1_StepCnt * M1_step;        // A相步数计数
        area  = pwm_A / 64;                                // 区间0~3
        pwm_B = pwm_A + 64;                                // B相步数计数
        pwm_A = T_SIN[pwm_A]/2;                        // A相sPWM值
        pwm_B = T_SIN[pwm_B]/2;                        // A相sPWM值

        if(area == 0)                        //0区间
        {
                PWMA_CCR1L = pwm_A;                // A+ = sin(A)
                PWMA_CCR2L = 0;                        // A- = 0
                PWMA_CCR3L = pwm_B;                // B+ = cos(A) = sin(A+64)
                PWMA_CCR4L = 0;                        // B- = 0
        }
        else if(area == 1)                //1区间
        {
                PWMA_CCR1L = pwm_A;                // A+ = sin(A)
                PWMA_CCR2L = 0;                        // A- = 0
                PWMA_CCR3L = 0;                        // B+ = 0
                PWMA_CCR4L = pwm_B;                // B- = cos(A) = sin(A+64)
        }
        else if(area == 2)                //2区间
        {
                PWMA_CCR1L = 0;                        // A+ = sin(A)
                PWMA_CCR2L = pwm_A;                // A- = 0
                PWMA_CCR3L = 0;                        // B+ = 0
                PWMA_CCR4L = pwm_B;                // B- = cos(A) = sin(A+64)
        }
        else                                        //3区间
        {
                PWMA_CCR1L = 0;                        // A+ = sin(A)
                PWMA_CCR2L = pwm_A;                // A- = 0
                PWMA_CCR3L = pwm_B;                // B+ = cos(A) = sin(A+64)
                PWMA_CCR4L = 0;                        // B- = 0
        }
}
u8        Timer0_Config(u8 t, u32 reload)        //t=0: reload值是主时钟周期数,  t=1: reload值是时间(单位us)
{
        TR0 = 0;        //停止计数

        if(t != 0)        reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL);        //重装的是时间(us), 计算所需要的系统时钟数.
        if(reload >= (65536UL * 12))        return 1;        //值过大, 返回错误
        if(reload < 65536UL)        AUXR |= 0x80;                //1T mode
        else
        {
                AUXR &= ~0x80;        //12T mode
                reload = reload / 12;
        }
        reload = 65536UL - reload;
        TH0 = (u8)(reload >> 8);
        TL0 = (u8)(reload);

        ET0 = 1;        //允许中断
        TMOD = (TMOD & ~0x03) | 0;        //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
        TR0 = 1;        //开始运行
        return 0;
}

//========================================================================
// 函数: void timer0_ISR(void) interrupt TIMER0_VECTOR
// 描述:  timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2018-12-20
//========================================================================
void timer0_ISR(void) interrupt TIMER0_VECTOR
{
      
        B_1ms = 1;        //标志1ms时隙
        ms_flag++;
        Key_scan();


}

IMG_8854.MP4

20.72 MB, 下载次数: 150

点评

应该是按键重复执行了吧?按键使用下降沿、上升沿检测,就不会出现重复执行的情况。  详情 回复 发表于 2024-10-10 18:16
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:455
  • 最近打卡:2025-05-01 00:44:09

6

主题

81

回帖

2118

积分

金牌会员

积分
2118
发表于 2024-10-10 08:09:58 | 显示全部楼层
控制步进电机这么麻烦吗,要写这么长的程序,正好也在学这个,看的有点头皮发麻
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:35 , Processed in 0.254143 second(s), 108 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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