STM32 + AMIS-30542 + 2相步进电机(二)

本文介绍如何使用STM32微控制器通过SPI接口配置AMIS-30542驱动芯片来控制2相步进电机的方法。包括SPI接口初始化、AMIS-30542寄存器配置、电机调速等功能实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要粘贴些 使用STM32 控制AMIS-30542 来驱动2相步进电机 的关键程序段。。。


环境说明:

控制器:STM32F101R8T6    STM32固件库版本:V3.5    驱动芯片:AMIS-30542      步进电机:2相步进电机   


原理图:





AMIS-30542寄存器地址宏定义:

#define MOTOR_WR    0x00
#define MOTOR_CR0   0x01
#define MOTOR_CR1   0x02
#define MOTOR_CR2   0x03
#define MOTOR_SR0   0x04
#define MOTOR_SR1   0x05
#define MOTOR_SR2   0x06
#define MOTOR_SR3   0x07
#define MOTOR_CR3   0x08

SPI接口及 DIR/STEP 初始:

/*********************************************************************************************************
** 函数名称: SPI_Init_Enable
** 功能描述: SPI1初始化
** 输 入: 无
** 输 出: 无
** 全局变量: 无
** 调用模块: SPI_InitStructure,GPIO_InitTypeDef,SPI_Cmd
**
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void SPI1_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
   
  /* Enable SPI1 GPIO clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO |
                         RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
  
  /* Configure SPI1 pins: NSS, SCK, MISO and MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 ;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);		  
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_SetBits(GPIOA,GPIO_Pin_0);

  //DIR/Step 管脚
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3<span style="font-family: Arial, Helvetica, sans-serif;">;</span>
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_SetBits(GPIOA,GPIO_Pin_2);
  
  //CLR 置低
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  
  
  SPI_Cmd(SPI1, DISABLE);  
  /* Configure PB.02 as Output push-pull, used as Chip select */

  /* SPI1 configuration */ 
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI1, &SPI_InitStructure);
//  SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE | SPI_I2S_IT_TXE, ENABLE);

  SPI_Cmd(SPI1, ENABLE);  
}


void Write_SPI_One_Byte(unsigned char addr,unsigned char data)
{  
    GPIO_ResetBits(GPIOA,GPIO_Pin_4);
    //SPI_delay (500);
    SPI_I2S_SendData(SPI1,0x80|addr);
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET);
    SPI_I2S_ReceiveData(SPI1);
    SPI_I2S_SendData(SPI1,data);
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET);
    SPI_I2S_ReceiveData(SPI1);
    GPIO_SetBits(GPIOA,GPIO_Pin_4);
    //SPI_delay (500);
}


AMIS-30542 初始化配置:参数配置仅供参考.......详见其数据手册

这里设置了细分刻度为1/8 ,则电机转动360度需要脉冲数:200 * 8 = 1600,其中200为步进电机的固定参数:整步运行一周需要200个脉冲..................

工作电流大小设置..........等等................

void MotordevInit(void)
{
    //CLR 复位 
    GPIO_SetBits(GPIOC,GPIO_Pin_3);
    SPI_delay(1000);
    GPIO_ResetBits(GPIOC,GPIO_Pin_3);
    Write_SPI_One_Byte(MOTOR_WR,0x00);//关闭看门狗
    SPI_delay (1000);
    Write_SPI_One_Byte(MOTOR_CR0,0x40);//1/8Micro-Step,Current = 1.39A
    SPI_delay (1000);
    Write_SPI_One_Byte(MOTOR_CR1,0x84);//DIRCTRL = 1,NXTP = 0,PWMF = 0,PWMJ = 1, EMC = VERY FAST
    SPI_delay (1000);
    Write_SPI_One_Byte(MOTOR_CR2,0xA0);//MOTEN = ENABLE MOTOR DRIVER,SLP = disable sleep mode,Gain = 0.25,SLA is transparent
    SPI_delay (1000);
    Write_SPI_One_Byte(MOTOR_CR3,0x84);  //模式1’  4 个PWM 周期   75%占空比  4 个PWM 周期
    SPI_delay (1000);
}


TIMER1定时器初始化:中断模式,用于NXT引脚的脉冲输出

void TIM_Configuration1(void)//TIM初始化函数
{
  
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; 	//TIM 基本事件结构体
    TIM_OCInitTypeDef  TIM_OCInitStructure;            //TIM 输出控制结构体
    NVIC_InitTypeDef  NVIC_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //使能TIM 时钟
  
    TIM_DeInit(TIM1); 
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
    TIM_OCStructInit(&TIM_OCInitStructure); 
    TIM_TimeBaseStructure.TIM_Prescaler = 449; 		//TIM 预分频  160KHz
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 计数模式
    TIM_TimeBaseStructure.TIM_Period = 799; 			//TIM 计数周期
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 	//TIM 时钟分频
    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure); 
    
  //  TIM_SelectOnePulseMode(TIM1,TIM_OPMode_Repetitive);		//连续输出
    
    TIM_ARRPreloadConfig(TIM1, ENABLE);				//PWM周期预加载
    
    TIM_Cmd(TIM1,DISABLE); 					//使能TIM1
    
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQChannel;    //更新事件
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;   //抢占优先级0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;          //响应优先级1
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允许中断
    NVIC_Init(&NVIC_InitStructure);                             //写入设置
    TIM_ITConfig(TIM1,TIM_IT_Update,DISABLE);
    
}


其他I/O初始化配置,略过......


电机部分函数:

使能:

void EnableMotor(void)
{
    //ResetEN;
    Write_SPI_One_Byte(MOTOR_CR2,0xA0);
}

调速:

void MotorChangeFreq(float freq)
{
    TIM1->ARR=  给个值.... 
}

运行:

void MotorRun(unsigned char Dir,u16 freq)
{
    EnableMotor();
    TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);  //使能中断

    TIM1->ARR = freq;
    TIM_Cmd(TIM1,ENABLE);
    ......
    ......
}

停止:

将TIM中断禁止了就完了..............



................

中断函数:

/******************************************************************************/
/*            STM32F10x Peripherals Interrupt Handlers                        */
/******************************************************************************/

/**
  * @brief  This function handles TIM1 global interrupt request.
  * @param  None
  * @retval None
  */ 
void TIM1_UP_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM1,TIM_IT_Update)!= RESET)
    {
        if (GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_3)==0)
        {
            GPIO_SetBits(GPIOA,GPIO_Pin_3);
			.......	
			......
	}
        else 
        {
          GPIO_ResetBits(GPIOA,GPIO_Pin_3);
        }
    }
    TIM_ClearFlag(TIM1,TIM_FLAG_Update); 
    TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
}

测试函数:

略过............


~~~~~~~~~~~~~凌乱了··~~~~~~~~~~~~~~··




















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值