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

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

  [复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:15
  • 最近打卡:2025-03-26 09:09:59

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-8-29 11:00:37 | 显示全部楼层
huatl*** 发表于 2024-8-29 11:00
两相步进电机-细分驱动-STC8H-高级PWMB输出

并且我发现1ms中断也不工作
回复 支持 反对

使用道具 举报 送花

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

73

主题

5882

回帖

1万

积分

超级版主

积分
12073
发表于 2024-8-29 13:53:28 | 显示全部楼层
huatl*** 发表于 2024-8-29 11:00
两相步进电机-细分驱动-STC8H-高级PWMB输出

这些都是严格测试过的程序,无数用户验证过的程序,没有问题:

截图202408291353236056.jpg

回复 支持 反对

使用道具 举报 送花

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

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-8-29 14:58:55 | 显示全部楼层
梁*** 发表于 2024-8-29 13:53
这些都是严格测试过的程序,无数用户验证过的程序,没有问题:

梁工,您的程序我知道肯定没有问题,但是造成这样原因会是什么呢?我只是在PWM配置中更改了PWM引脚
回复 支持 反对

使用道具 举报 送花

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

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-8-29 15:21:06 | 显示全部楼层
huatl*** 发表于 2024-8-29 14:58
梁工,您的程序我知道肯定没有问题,但是造成这样原因会是什么呢?我只是在PWM配置中更改了PWM引脚 ...

梁工,我能接受数据了,但是发送指令后电机仍然不转
回复 支持 反对

使用道具 举报 送花

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

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-8-29 15:33:37 | 显示全部楼层
huatl*** 发表于 2024-8-29 15:21
梁工,我能接受数据了,但是发送指令后电机仍然不转

UART1_PrintString("2相步进电机细分驱动程序\r\n");
QQ截图20240829153302.png
回复 支持 反对

使用道具 举报 送花

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

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-8-29 15:34:22 | 显示全部楼层
huatl*** 发表于 2024-8-29 15:33
UART1_PrintString("2相步进电机细分驱动程序\r\n");

UART1_PrintString("2相步进电机细分驱动程序\r\n");
        UART1_PrintString("L1,500,1000   --> 马达1以500Hz正转1000个脉冲\r\n");
        UART1_PrintString("R1,500,1000   --> 马达1以500Hz反转1000个脉冲\r\n");
        UART1_PrintString("s  --> 停止所有电机\r\n");
但是这几行打印输出的仍然没有,电机给了指令也不动作

点评

你示波器看看PWM输出,就算单单一个MCU,也能运行的,PWM会有输出的。  详情 回复 发表于 2024-9-28 19:18
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:307
  • 最近打卡:2025-05-02 07:14:07

0

主题

46

回帖

1016

积分

金牌会员

积分
1016
发表于 2024-9-28 15:30:34 | 显示全部楼层
回复

使用道具 举报 送花

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

73

主题

5882

回帖

1万

积分

超级版主

积分
12073
发表于 2024-9-28 19:18:58 | 显示全部楼层
huatl*** 发表于 2024-8-29 15:34
UART1_PrintString("2相步进电机细分驱动程序\r\n");
        UART1_PrintString("L1,500,1000   --> 马达1以500 ...

你示波器看看PWM输出,就算单单一个MCU,也能运行的,PWM会有输出的。
回复 支持 反对

使用道具 举报 送花

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

6

主题

104

回帖

351

积分

中级会员

积分
351
发表于 2024-9-29 10:58:59 | 显示全部楼层
梁工您好,这是我移植您的程序到STC8H1K08  20PIN单片机,希望按键按下后旋转,但是怎么都实现不了,请您帮忙看下
#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 PWMA_config();
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);
u8        Timer0_Config(u8 t, u32 reload);        //t=0: reload值是主时钟周期数,  t=1: reload值是时间(单位us), 返回0正确, 返回1装载值过大错误.
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装载值过大错误.
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)访问使能
//        P0M0 = 0x00;P0M1 = 0x00;P1M0 = 0x00;P1M1 = 0x00;P2M0 = 0x00;P2M1 = 0x00;P3M0 = 0x00;P3M1 = 0x00;P4M0 = 0x00;P4M1 = 0x00;P5M0 = 0x00;P5M1 = 0x00;
           //选择24MHz
    //选择 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;
//        f_pl =24000;//55000 500hz
//        f_pl = 400;
//        pwm_duty=5;

           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
//        P3M1 = 0x2c;                                           //           0 0 1 0 1 1 0 0
//        P3M0 = 0xd0;   //设置P3推挽输出和高阻输入           1 1 0 1 0 0 1 1
//        P_SW1 = 0x00;
        speed = 1; //调整速度        1900-                 2000 2200 2400 较快 有抖动2500较慢
        DECAY = 0;
        SLEEP = 1;
//        PWMA_config(f_pl,pwm_duty);       
    PWMA_config();

//        PWMA_ENO &= ~0x02;
//        PWMA_ENO &= ~0x04;
//        PWMA_ENO &= ~0x20;
//        PWMA_ENO &= ~0x40;
        //        Timer0_Init();
        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 = 4;                                 //细分数  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)
                        {
                                while(flag_up == 0)
                                {
                                        if(!B_M1_RunEn)         f1 = 200;
                                        B_M1_DIR = 0;
                                        f1_set = 1000;
                                        M1_PulseCnt = 2000;
                                        RunMotor1();
                                }
                                        if(!B_M1_RunEn)         f1 = 200;
                                        B_M1_DIR = 1;
                                        f1_set = 1000;
                                        M1_PulseCnt = 2000;
                                        RunMotor1();
                        }
                }
        }
}
#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);
}

void        RunMotor1()                //启动运行一个电机
{
       
        f1_step = GetStep(f1, f1_set);
        GetDownPulse();
               
        if(!TR1 || !B_M1_RunEn)
        {
                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 = 0x0000;        // 预分频寄存器, 分频 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   = 200;                // 比较值, 控制占空比(高电平时钟数)
        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
        }
}
//========================================================================
// 函数: 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();

}

点评

这要自己调试哦! 第一步:先确定Timer0的1ms中断正常(取反一个IO示波器观察)。 第二步:示波器观察4个PWM能正常输出。 第三步:让PWM按给定的速度改变占空比。  详情 回复 发表于 2024-9-29 12:00
回复 支持 反对

使用道具 举报 送花

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

73

主题

5882

回帖

1万

积分

超级版主

积分
12073
发表于 2024-9-29 12:00:19 | 显示全部楼层
huatl*** 发表于 2024-9-29 10:58
梁工您好,这是我移植您的程序到STC8H1K08  20PIN单片机,希望按键按下后旋转,但是怎么都实现不了,请您帮 ...

这要自己调试哦!
第一步:先确定Timer0的1ms中断正常(取反一个IO示波器观察)。
第二步:示波器观察4个PWM能正常输出。
第三步:让PWM按给定的速度改变占空比。
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 09:02 , Processed in 0.154310 second(s), 110 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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