OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8280|回复: 6

stm32103c8t6驱动的42步进电机,带有tb6600驱动器,实现正反转的驱动问题急急急

[复制链接]

1

主题

5

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2021-2-21
在线时间
16 小时
发表于 2021-4-10 10:47:31 | 显示全部楼层 |阅读模式
10金钱
楼主的程序有一个按键控制步进电机的正反转,程序同时带有两个直流电机的驱动模块,直流电机的程序基本没影响,但因程序是之前写的,现在回过头来重新改进发现之前的程序已经不能驱动步进电机了,修改不当后程序彻底瘫痪,求助大神帮忙查查问题和改进方法,主要代码如下:
main.c:

#define a                0.8 //步进电机转动360度丝杠运动的距离
#define X                200 //上位机传输十进制数值坐标
#define max 500 //最大有效距离
/*
细分:4                        脉冲/转:800                        开关关
细分:8                        脉冲/转:1600                        关开关
细分:16                脉冲/转:3200                        关关开
细分:32                脉冲/转:6400                        关关关
*/


int main(void)
{
        int N;

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        Motor_12_Config(); //298电机驱动初始化  Motor_Init();//直线电机的初使化
        //Motor_3_Config();
  Key_GPIO_Config();//按键端口初始化
        delay_init();  //延时函数初始化
//        uart_init(115200);                //串口初始化为115200
        delay_ms(10000);
        KEY_Init();//按键初始化      Key1_GPIO_Config();  //按键初始化
        //Motor_Init();                //电机IO初始化
        N=(X/a)*1600;       
        while(1)
        {
         Motor_1_PRun(); //正转
        Motor_2_PRun();       
        delay_ms(10000); //转五秒
        delay_ms(10000);
        delay_ms(10000);
               
        Motor_1_STOP();  //停止
        Motor_2_STOP();
       
        delay_ms(10000);  //停三秒
        delay_ms(10000);
        delay_ms(10000);
               
                Cycle1(N);
                delay_ms(100);
                Cycle2(N);
                delay_ms(100);

        }
       
}
       
bsp_tb6600.c:

#include "bsp_tb6600.h"
#include "timer.h"

/* 共阴极接法,高电平有效
         A9为脉冲输出,脉冲频率控制步进电机转动速度;
         A10为高低电平输出,高电平为正转,低电平为反转;
         A11为使能,高电平脉冲和方向不受控制,低电平受控制*/
         
#define time 25



/********** 驱动器 端口定义 **************
//ENA+(DRIVER_OE)   PA11        (TIM1_CH1)                                                使能
//DRIVER_DIR                    PA10                 (TIM1_CH2)                                                方向
//STEP_PULSE                           PA9         (TIM1_CH2)                                                        脉冲
******************************************/

static void TB6600_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;                //端口配置结构体
       
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);                //使能PA端口时钟
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                //翻转速度为50Mhz
        GPIO_Init(GPIOA, &GPIO_InitStructure);                //根据设定参数初始化GPIOA
       
        GPIO_ResetBits(GPIOA,GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11); //A9、A10、A11置0
}

//控制步进电机正转
void Cycle1(int N)//X为到达指定位置需要多少个脉冲
{
        TB6600_Config();
        GPIO_SetBits(GPIOA,GPIO_Pin_10);
        while(N!=0)
        {
                GPIO_SetBits(GPIOA,GPIO_Pin_9);
                SysTick_Delay_Us(100);
                GPIO_ResetBits(GPIOA,GPIO_Pin_9);
                SysTick_Delay_Us(100);
                N--;
        }
}

//控制步进电机反转
void Cycle2(int N)//X为到达指定位置需要多少个脉冲
{
        TB6600_Config();
        GPIO_ResetBits(GPIOA,GPIO_Pin_10);
        while(N!=0)
        {
                GPIO_SetBits(GPIOA,GPIO_Pin_9);
                SysTick_Delay_Us(100);
                GPIO_ResetBits(GPIOA,GPIO_Pin_9);
                        SysTick_Delay_Us(100);
                N--;
        }
}


bsp_systick.c:
#include "bsp_SysTick.h"
#include "core_cm3.h"
#include "misc.h"

static __IO u32 TimingDelay;

/**
  * @brief  启动系统滴答定时器 SysTick
  * @param  无
  * @retval 无
  */
void SysTick_Init(void)
{
        /* SystemFrequency / 1000    1ms中断一次
         * SystemFrequency / 100000         10us中断一次
         * SystemFrequency / 1000000 1us中断一次
         */
//        if (SysTick_Config(SystemFrequency / 100000))        // ST3.0.0库版本
        if (SysTick_Config(SystemCoreClock / 100000))        // ST3.5.0库版本
        {
                /* Capture error */
                while (1);
        }
}

/**
  * @brief   us延时程序,10us为一个单位
  * @param  
  *                @arg nTime: Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us
  * @retval  无
  */
void Delay_us(__IO u32 nTime)
{
        TimingDelay = nTime;       

        // 使能滴答定时器  
        SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;

        while(TimingDelay != 0);
}

/**
  * @brief  获取节拍程序
  * @param  无
  * @retval 无
  * @attention  在 SysTick 中断函数 SysTick_Handler()调用
  */
void TimingDelay_Decrement(void)
{
        if (TimingDelay != 0x00)
        {
                TimingDelay--;
        }
}

#if 0
// 这个 固件库函数 在 core_cm3.h中
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  // reload 寄存器为24bit,最大值为2^24
        if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);

  // 配置 reload 寄存器的初始值       
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
       
        // 配置中断优先级为 1<<4-1 = 15,优先级为最低
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
       
        // 配置 counter 计数器的值
  SysTick->VAL   = 0;
       
        // 配置systick 的时钟为 72M
        // 使能中断
        // 使能systick
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                    
  return (0);
}
#endif

// couter 减1的时间 等于 1/systick_clk
// 当counter 从 reload 的值减小到0的时候,为一个循环,如果开启了中断则执行中断服务程序,
// 同时 CTRL 的 countflag 位会置1
// 这一个循环的时间为 reload * (1/systick_clk)

void SysTick_Delay_Us( __IO uint32_t us)
{
        uint32_t i;
        SysTick_Config(SystemCoreClock/1000000);
       
        for(i=0;i<us;i++)
        {
                // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1       
                while( !((SysTick->CTRL)&(1<<16)) );
        }
        // 关闭SysTick定时器
        SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}

void SysTick_Delay_Ms( __IO uint32_t ms)
{
        uint32_t i;       
        SysTick_Config(SystemCoreClock/1000);
       
        for(i=0;i<ms;i++)
        {
                // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
                // 当置1时,读取该位会清0
                while( !((SysTick->CTRL)&(1<<16)) );
        }
        // 关闭SysTick定时器
        SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}


/*********************************************END OF FILE**********************/


timer.c:
#include "timer.h"
#include "usart.h"

//通用定时器1中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器1!
void TIM1_Int_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //时钟使能

        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

        TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能指定的TIM1中断,允许更新中断

        //设置优先级
        NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;  //TIM1中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

        TIM_Cmd(TIM1, ENABLE);  //使能TIMx外设
                                                         
}
//定时器1中断服务程序
void TIM1_UP_IRQHandler(void)    //TIM1中断
{
        if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
                {
                TIM_ClearITPendingBit(TIM1, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
                }
}




//TIM1 PWM部分初始化
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM1_PWM_Init(u16 arr,u16 psc)
{  
        GPIO_InitTypeDef GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef                          TIM_OCInitStructure;
       

        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);         //使能定时器1时钟
//        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
       
        //GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射  TIM3_CH2->PB5   

   //设置该引脚为复用输出功能,输出TIM1 CH2的PWM脉冲波形        GPIOA.9
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //TIM_CH2
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //复用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO

   //初始化TIM1
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;    //高级定时器特有
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
       
        //初始化TIM1 Channel2 PWM模式         
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
       
        TIM_OC2Init(TIM1, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM1         OC2
        TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);  //使能TIM1在CCR2上的预装载寄存器

   TIM_ARRPreloadConfig(TIM1, ENABLE);
   TIM_CtrlPWMOutputs(TIM1, ENABLE);                //高级定时器必须有的一句,使能PWM输出

        TIM_Cmd(TIM1, ENABLE);  //使能TIM1
       

}
如需要查看其他部分的代码,评论我补充,谢谢各位大神!!!

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165475
金钱
165475
注册时间
2010-12-1
在线时间
2115 小时
发表于 2021-4-11 02:31:19 | 显示全部楼层
回复

使用道具 举报

13

主题

271

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5387
金钱
5387
注册时间
2017-8-14
在线时间
248 小时
发表于 2021-4-12 15:06:50 | 显示全部楼层
详细资料扣扣群204408503自行下载
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2021-2-21
在线时间
16 小时
 楼主| 发表于 2021-5-16 19:09:59 | 显示全部楼层
zml13917492379 发表于 2021-4-12 15:06
可参考 下我们的 程序:
http://www.openedv.com/forum.php?mod=viewthread&tid=315059&highlight=%B2%BD% ...

看过了,但是依旧没法解决问题,步进电机依旧不能驱动
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165475
金钱
165475
注册时间
2010-12-1
在线时间
2115 小时
发表于 2021-5-17 01:28:57 | 显示全部楼层
所幸南风知我意 发表于 2021-5-16 19:09
看过了,但是依旧没法解决问题,步进电机依旧不能驱动

继续努力,测试下信号吧,有驱动器的情况下,驱动起来转是比较简单的。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2021-5-27
在线时间
1 小时
发表于 2021-5-27 20:50:43 | 显示全部楼层
请问能把你的驱动42步进电机的程序发我一份吗?谢谢了
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
43
金钱
43
注册时间
2021-2-21
在线时间
16 小时
 楼主| 发表于 2021-6-2 09:58:55 | 显示全部楼层
LLRLDC 发表于 2021-5-27 20:50
请问能把你的驱动42步进电机的程序发我一份吗?谢谢了

我的程序现在跑不出结果
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-10 22:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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