DRV8711的通用步进电机驱动器和直流电机驱动器

时间:2025-02-12 07:27:40
#include "drv8711_driver.h" #include <> #include <> /* * 说 明: * 本参数为默认属性赋值,基本上只需更改OFF 寄存器就可驱动直流或步进 * 如需改动需要配合DRV8711产品说明文档调配 页面P25 * */ //变量定义区 //CTRL 寄存器 u16 RDIR = 0x0001 | (1<<1); //1为顺时针方向旋转 u16 DTIME = 0x0001 | (3<<10); //死区时间设置 //TORQUE 寄存器 u16 TORQUE = 0x0000 | 0xFF; //输出电流比例,用于计算设置电流的参数 u16 SMPLTH = 0x0000 | (1<<8); //反电动势采样时间 //OFF 寄存器 u16 TOFF = 0x0000; //设置MOS管固定关闭时间------------衰减模式下可用到,可保持默认状态 u16 PWMMODE = 0x0000 | (1<<8); //0为步进电机模式 或 1为直流电机模式 //BLANK 寄存器 u16 TBLANK = 0x0040; //设置MOS管固定打开时间------------衰减模式下可用到,可保持默认状态 u16 ABT = 0x0000 | (0<<8); //blanjing时间自适应 //DECAY 寄存器 u16 TDECAY = 0x0010; //混合衰减模式转换时间------------衰减模式下可用到,可保持默认状态 u16 DECMOD = 0x0000 | (5<<8); //电流衰减模式,此处使用自动混合衰减 //DRIVE 寄存器 u16 OCPTH = 0x0000| (0<<0); //过流检测门限 u16 OCPDEG = 0x0000| (1<<2); //过流误动作防止时间 u16 TDRIVEN = 0x0000| (1<<4); //低侧棚极驱动时间 u16 TDRIVEP = 0x0000| (1<<6); //高侧棚极驱动时间 u16 IDRIVEN = 0x0000| (1<<8); //低侧棚极驱动峰值电流 u16 IDRIVEP = 0x0000| (1<<10); //高侧棚极驱动峰值电流 //STATUS 寄存器 u16 STATUS_Register = 0x0000; //清除所有异常故障包括过温、过流 u16 Ctrl_register = 0xFFFF; //CTRL集合 u16 Torque_register = 0xFFFF; //TORQUE集合 u16 Off_register = 0xFFFF; //OFF集合 u16 Blank_register = 0xFFFF; //BLANK集合 u16 Decay_register = 0xFFFF; //DECAY集合 u16 Drive_register = 0xFFFF; //DRIVE集合 u16 Drv8711_model = 0x0001 | (5<<3); //步进细分设置为32 u16 Drv8711_isgain = 0x0001 | (0<<8); //电流采样增益,用于计算设置电流的参数 //APP函数 /** * 函数功能: Drv8711芯片初始化,完成spi接口配置和参数初始化,调用初始化之前先修改.h文件使用的硬件管脚宏 * 输入参数1: mode 驱动器模式选择 ; 0=直流电机;1=步进电机; * 输入参数2: Microstep 步进电机细分;4~256细分,在.h里面宏定义 * 输入参数3: Stepper_current 步进电机电流;//最大值要补充上 * 输入参数4: Attenuation 步进电机衰减模式 //衰减模式宏也要加上去 * 返 回 值: >0正确;<0错误 * 说 明:无 */ int Drv8711_init(u8 Mode,u8 Microstep,float Stepper_current,u8 Attenuation) { if(Mode>1) { return -1; } if(Stepper_current>CURRENT_MAX) { Stepper_current = CURRENT_MAX; } Spi_configuration(); Drv8711mode_mots(Mode,Microstep,Stepper_current,Attenuation); } /** * 函数功能: DRV8711驱动器设置电流大小 * 输入参数: current;步进电机电流 * 返 回 值: 无 * 说 明:无 */ void Drv8711set_current(float Current) { unsigned int Set_current =255; Set_current =(unsigned int)((256*5*R_ISGAIN)*Current)/2.75; Torque_register = Set_current; //输出电流比例,用于计算设置电流的参数 Spi_drv8711_write(0x01,Torque_register); //TORQUE Spi_drv8711_write(0x00,Ctrl_register); //CTRL } /** * 函数功能: DRV8711驱动器读取电流大小 * 输入参数: current;返回当前步进电机电流 * 返 回 值: 无 * 说 明:无 */ void Drv8711read_current(float Current) { float data = 0; data= (float)(Spi_drv8711_read(0x01) & 0xFF); Current =(unsigned int) ((data*2.75)/(256*5*R_ISGAIN)); } /** * 函数功能: 配置SPI通讯协议初始化 * 输入参数: 无 * 返 回 值: 无 * 说 明:无 */ void Spi_configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //PORTB时钟使能 RCC_APB1PeriphClockCmd( DRV8711_SPI_CLK, ENABLE ); //SPI2时钟使能 GPIO_InitStructure.GPIO_Pin = DRV8711_SPI_SCK_PIN | DRV8711_SPI_MISO_PIN | DRV8711_SPI_MISO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DRV8711_SPI_GPIO, &GPIO_InitStructure); //初始化DRV8711_SPI_GPIO GPIO_SetBits(DRV8711_SPI_GPIO,DRV8711_SPI_SCK_PIN|DRV8711_SPI_MISO_PIN|DRV8711_SPI_MISO_PIN); //PB13/14/15上拉 GPIO_InitStructure.GPIO_Pin = DRV8711_SPI_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //PB13/14/15复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DRV8711_SPI_GPIO, &GPIO_InitStructure); //初始化DRV8711_SPI_GPIO SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; //STM32的SPI1用APB2的72MHz,TMC5130手册里P23指出TMC5130的SPI时钟不能超过4MHz和8MHz,所以注意此处的分频值 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 // SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(DRV8711_SPI, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器 SPI_Cmd(DRV8711_SPI, ENABLE); //使能SPI外设 } /** * 函数功能: DRV8711驱动器设置为直流电机或步进电机模式 * 输入参数: mode;驱动器模式选择 step;步进电机细分;步进电机电流 attenuation;步进电机衰减模式 * 返 回 值: 无 * 说 明: * 选择直流电机模式时后面参数克忽略 * 步进电机电流的幅值为:(2.75*ISGAIN[取值0~FF])/(255*ISGAIN[电流增益为5]*0.22[采样电阻值])用采样电阻0.22R最大电流为2.5A * 衰减模式有六种选择:1.一直慢衰减 2.电流增加时使用慢衰减,电流减少时使用混合衰减 3.一直快衰减 4.开始为快衰减,TDECAY时间后转为慢衰减 * 5.电流增加时使用慢衰减,电流减少时使用自动混合衰减 6.。。。。. */ void Drv8711mode_mots(u8 Mode,u8 Step,float Current,u8 Attenuation) { unsigned int Set_current =255; if (Mode == DC_MOTOR) { PWMMODE = 0x0000 | (1<<8); } else if(Mode ==STEPPER_MOTOR) { PWMMODE = 0x0000 | (0<<8); //步进电机细分 switch(Step) { case STEP_4 : Drv8711_model = 0x0001 | (2<<3); break; //细分4 case STEP_8 : Drv8711_model = 0x0001 | (3<<3); break; //细分8 case STEP_16 : Drv8711_model = 0x0001 | (4<<3); break; //细分16 case STEP_32 : Drv8711_model = 0x0001 | (5<<3); break; //细分32 case STEP_64 : Drv8711_model = 0x0001 | (6<<3); break; //细64 case STEP_128 : Drv8711_model = 0x0001 | (7<<3); break; //细分128 case STEP_256 : Drv8711_model = 0x0001 | (8<<3); break; //细分256 default: break; } //步进电机电流 Set_current =(unsigned int)((256*5*R_ISGAIN)*Current)/2.75; Drv8711_isgain = 0x0001 | (0<<8); //电流采样增益,用于计算设置电流的参数 //TORQUE = Set_current; //输出电流比例,用于计算设置电流的参数 //步进电机衰减模式 //DECMOD = 0x0000 | (Attenuation<<8); //电流衰减模式,此处使用自动混合衰减 } Ctrl_register = Drv8711_model | Drv8711_isgain | DTIME |RDIR ; //CTRL集合 Torque_register = Set_current|SMPLTH; Off_register = PWMMODE | TOFF; //OFF集合 Blank_register = TBLANK | ABT; //BLANK集合 Decay_register = TDECAY | 0x0000 | (Attenuation<<8); //DECAY集合 Drive_register = OCPTH | OCPDEG | TDRIVEN | TDRIVEP | IDRIVEN | IDRIVEP; //DRIVE集合 Spi_drv8711_write(STATUS_ADDR,STATUS_Register); //STATUS Spi_drv8711_write(DRIVE_ADDR,Drive_register); //DRIVE Spi_drv8711_write(DECAY_ADDR,Decay_register); //DECAY Spi_drv8711_write(BLANK_ADDR,Blank_register); //BLANK Spi_drv8711_write(OFF_ADDR,Off_register); //OFF Spi_drv8711_write(TORQUE_ADDR,Torque_register); //TORQUE Spi_drv8711_write(CTRL_ADDR,Ctrl_register); //CTRL } /** * 函数功能: SPI2外设发送与接收数据 * 输入参数: 要发送的数据 * 返 回 值: 接收的数据 * 说 明:无 */ u8 Spi_flash_sendbyte(u8 Byte) { /* 检测发送数据通道是否空闲状态,一直等待中 */ while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); /* 发送一个数据 */ SPI_I2S_SendData(SPI2, Byte); /* 检测接收数据通道是否空闲状态,一直等待中 */ while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); /* 返回最近接收的数据 */ return SPI_I2S_ReceiveData(SPI2); } /** * 函数功能: DRV8711读取数据 * 输入参数: 无 * 返 回 值: 无 * 说 明:DRV8711驱动器以低11位数据结构、高4位地址结构格式进行访问 */ u16 Spi_drv8711_read(u8 Addr) { u8 Temp = 0, Temp0 = 0, Temp1 = 0; u16 Temp2; //使能DRV8711的SPI通讯引脚 SPI_FLASH_CS0_HIGH(); Temp=(0x08|Addr)<<4; /* Read a byte from the FLASH */ Temp0 = Spi_flash_sendbyte(Temp); /* Read a byte from the FLASH */ Temp1 = Spi_flash_sendbyte(0xff); /* 失能DRV8711的SPI通讯引脚 */ SPI_FLASH_CS0_LOW(); Temp2 = ( (Temp0&0x0f)<<8 ) | Temp1; return Temp2; } /** * 函数功能: DRV8711写入数据 * 输入参数: 无 * 返 回 值: 无 * 说 明:DRV8711驱动器以低11位数据结构、高4位地址结构格式进行访问 */ void Spi_drv8711_write(u8 Addr,u16 Data) { u8 Temp = 0; /* 使能DRV8711的SPI通讯引脚 */ SPI_FLASH_CS0_HIGH(); // SPI_FLASH_CS1_HIGH(); Temp=((Data>>8)&0x0f) | (Addr<<4); Spi_flash_sendbyte(Temp); Temp=(u8)(Data&0x00ff); Spi_flash_sendbyte(Temp); /* 失能DRV8711的SPI通讯引脚 */ SPI_FLASH_CS0_LOW(); }