DRV8711的通用步进电机驱动器和直流电机驱动器
#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();
}