#include "tmc5160.h" #include "app.h" // CS2置于 “低电平” 使能SPI // 写的时候高位地址要加上 0x80 // 手册第5章是寄存器表,5.3.1是斜坡相关寄存器;第11章有实际单位换算表;第20章 图20.3 有运动控制流程图 // 寄存器 "RAMPMODE"->"0x20" 斜坡运动模式: 0->位置模式;1->速度模式至正VMAMX;2->速度模式至负VMAX;3->速度保持不变,最多使用2位 // 寄存器 "VSTART"->"0x23" 电机起动速度,最多使用18位,VSTART<=VSTOP // 寄存器 "A1"->"0x24" VSTART->V1的加速度,最多使用16位 // 寄存器 "V1"->"0x25" 第一加/减速阶段速度阈值,最多使用20位;取0时禁用A1和D1,仅用AMAX和DMAX // 寄存器 "AMAX"->"0x26" V1->VMAX的加速度,最多使用16位 // 寄存器 "DMAX"->"0x28" VMAX->V1的减速度,最多使用16位 // 寄存器 "VMAX"->"0x27" 斜坡运动目标速度,最多使用23位 // 寄存器 "D1"->"0x2A" V1->VSTOP的减速度,最多使用16位,不要在位置模式下置0 // 寄存器 "VSTOP"->"0x2B" 电机停止速度,最多使用18位,VSTART<=VSTOP,位置模式下>=10 // 一圈 200*256 微步,即每步转动 9/1280 度, 1 微步/秒 = 1.953e-5 转/秒 #define TMC5160A_CS2_L HAL_GPIO_WritePin(GPIOC,CS2_Pin,GPIO_PIN_RESET) //CS2低电平 #define TMC5160A_CS2_H HAL_GPIO_WritePin(GPIOC,CS2_Pin,GPIO_PIN_SET) //CS2高电平 #define TMC5160A_MOSI_L HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_RESET) //MOSI低电平 #define TMC5160A_MOSI_H HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15,GPIO_PIN_SET) //MOSI高电平 #define TMC5160A_CLK_L HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_RESET) //CLK低电平 #define TMC5160A_CLK_H HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13,GPIO_PIN_SET) //CLK高电平 #define TMC5160A_ReadVal HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14) //MISO void TMC5160A_Init_Gpio(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); /**SPI2 GPIO Configuration PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } /*************常用参数配置***************/ uint32_t rampmode = 0x00000000; //斜坡运动模式 0-位置;1-速度 int xtarget = 0x00000000; //位置模式的目标位置,51200/圈 uint32_t speed_1 = 0x00004E20; //V1 过渡阶段的目标速度 uint32_t speed_max = 0x00009C40; //VMAX 目标速度 uint32_t acc_1 = 0x00000FA0; //A1 过渡阶段的加速度 uint32_t acc_max = 0x00000BB8; //AMAX 最大加速度 uint32_t dcr_1 = 0x00000FA0; //D1 过渡阶段的减速度 uint32_t dcr_max = 0x00000BB8; //DMAX 最大减速度 /*************常用参数配置***************/ void tmc5160_init(void) { // 纯SPI模式 TMC5160_SPIWriteInt(0x00, 0x00000004,1); // writing value 0x0000000C = 12 = 0.0 to address 0 = 0x00(GCONF) 0x00000008 不能移动 会左右抖动 // TMC5160_SPIWriteInt(0x03, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 1 = 0x03(SLAVECONF) // TMC5160_SPIWriteInt(0x05, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 2 = 0x05(X_COMPARE) // TMC5160_SPIWriteInt(0x06, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 3 = 0x06(OTP_PROG) // TMC5160_SPIWriteInt(0x08, 0x0000000E,1); // writing value 0x00000011 = 17 = 0.0 to address 4 = 0x08(FACTORY_CONF) // TMC5160_SPIWriteInt(0x09, 0x00010606,1); // writing value 0x00010606 = 67078 = 0.0 to address 5 = 0x09(SHORT_CONF) TMC5160_SPIWriteInt(0x0A, 0x00080400,1); // writing value 0x00080400 = 525312 = 0.0 to address 6 = 0x0A(DRV_CONF) // TMC5160_SPIWriteInt(0x0B, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 7 = 0x0B(GLOBAL_SCALER) // 速度相关的驱动控制寄存器 TMC5160_SPIWriteInt(0x10, 0x00070A02,1); // IHOLD->0~7bit; IRUN->12~8bit TMC5160_SPIWriteInt(0x11, 0x0000000A,1); // writing value 0x0000000A = 10 = 0.0 to address 9 = 0x11(TPOWERDOWN) TMC5160_SPIWriteInt(0x13, 0x00000000,1); // 0x13(TPWMTHRS),StealthChop上限,超过该值后启用降噪,TSTEP >= TPWMTHRS使能降噪 TMC5160_SPIWriteInt(0x14, 0x00000000,1); // 0x14(TCOOLTHRS),降温操作,当该值 >= TSTEP >= THIGH 时,将禁用降噪,使能降温。 TMC5160_SPIWriteInt(0x15, 0x00000000,1); // 0x15(THIGH),该值大于等于TSTEP时,coolstep和steathchop都会被禁用 // 斜波发生器运动寄存器 TMC5160_SPIWriteInt(RAMPMODE_ADDR, rampmode,1); // writing value 0x00000000 = 0 = 0.0 to address 13 = 0x20(RAMPMODE) TMC5160_SPIWriteInt(XACTUAL_ADDR, 0x00000000,1); // writing value 0xFFCC12F0 = 0 = 0.0 to address 14 = 0x21(XACTUAL) TMC5160_SPIWriteInt(0x23, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 15 = 0x23(VSTART) TMC5160_SPIWriteInt(A1_ADDR, acc_1,1); // A1 TMC5160_SPIWriteInt(AMAX_ADDR, acc_max,1); // AMAX TMC5160_SPIWriteInt(V1_ADDR, speed_1,1); // V1 TMC5160_SPIWriteInt(VMAX_ADDR, speed_max,1); // VMAX TMC5160_SPIWriteInt(D1_ADDR, dcr_1,1); // D1 TMC5160_SPIWriteInt(DMAX_ADDR, dcr_max,1); // DMAX TMC5160_SPIWriteInt(0x2B, 0x00000010,1); // VSTOP >= 0x0000000A TMC5160_SPIWriteInt(0x2C, 0x00003FFF,1); // TZEROWAIT TMC5160_SPIWriteInt(XTARGET_ADDR, xtarget,1); // writing value 0xFFCC12F0 = 0 = 0.0 to address 24 = 0x2D(XTARGET) // TMC5160_SPIWriteInt(0x33, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 25 = 0x33(VDCMIN) TMC5160_SPIWriteInt(0x34, 0x00000000,1); // 0x34(SW_MODE),0x00000400使能堵转 // // 编码器寄存器 // TMC5160_SPIWriteInt(0x38, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 27 = 0x38(ENCMODE) // TMC5160_SPIWriteInt(0x39, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 28 = 0x39(X_ENC) // TMC5160_SPIWriteInt(0x3A, 0x00010000,1); // writing value 0x00010000 = 65536 = 0.0 to address 29 = 0x3A(ENC_CONST) // TMC5160_SPIWriteInt(0x3D, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 30 = 0x3D(ENC_DEVIATION) // // 电机驱动寄存器-电机微步控制寄存器 // TMC5160_SPIWriteInt(0x60, 0xAAAAB554,1); // writing value 0xAAAAB554 = 0 = 0.0 to address 31 = 0x60(MSLUT[0]) // TMC5160_SPIWriteInt(0x61, 0x4A9554AA,1); // writing value 0x4A9554AA = 1251300522 = 0.0 to address 32 = 0x61(MSLUT[1]) // TMC5160_SPIWriteInt(0x62, 0x24492929,1); // writing value 0x24492929 = 608774441 = 0.0 to address 33 = 0x62(MSLUT[2]) // TMC5160_SPIWriteInt(0x63, 0x10104222,1); // writing value 0x10104222 = 269500962 = 0.0 to address 34 = 0x63(MSLUT[3]) // TMC5160_SPIWriteInt(0x64, 0xFBFFFFFF,1); // writing value 0xFBFFFFFF = 0 = 0.0 to address 35 = 0x64(MSLUT[4]) // TMC5160_SPIWriteInt(0x65, 0xB5BB777D,1); // writing value 0xB5BB777D = 0 = 0.0 to address 36 = 0x65(MSLUT[5]) // TMC5160_SPIWriteInt(0x66, 0x49295556,1); // writing value 0x49295556 = 1227445590 = 0.0 to address 37 = 0x66(MSLUT[6]) // TMC5160_SPIWriteInt(0x67, 0x00404222,1); // writing value 0x00404222 = 4211234 = 0.0 to address 38 = 0x67(MSLUT[7]) // TMC5160_SPIWriteInt(0x68, 0xFFFF8056,1); // writing value 0xFFFF8056 = 0 = 0.0 to address 39 = 0x68(MSLUTSEL) // TMC5160_SPIWriteInt(0x69, 0x00F70000,1); // writing value 0x00F70000 = 16187392 = 0.0 to address 40 = 0x69(MSLUTSTART) // // 电机驱动寄存器-驱动寄存器组 TMC5160_SPIWriteInt(0x6C, 0x000100C3,1); // 0x6C(CHOPCONF)斩波器配置 TMC5160_SPIWriteInt(0x6D, 0x00000000,1); // 0x6D(COOLCONF),16-22bit设置堵转灵敏度,值越小灵敏度越高,最大3F(63),最小C0(-64) // TMC5160_SPIWriteInt(0x6E, 0x00000000,1); // 0x6E(DCCTRL) TMC5160_SPIWriteInt(0x70, 0xC40C001E,1); // 0x70(PWMCONF)已开启自动调节 } uint8_t data_r[5] = {0};//存放接收到的数据 void TMC5160_SPIWriteInt(uint8_t addr, uint32_t data, uint8_t rw)//rw = 1为写,0为读 { char i = 0; unsigned long dat = 0; for(i = 0; i < 5; i++) data_r[i] = 0; TMC5160A_CS2_L; delay(100); if(rw) { addr |= 0x80; } else { addr &= 0x7F; } //地址 TMC5160A_CLK_H; for(i = 0; i < 8; i++) { TMC5160A_CLK_L; if(addr & 0x80) { TMC5160A_MOSI_H; } else { TMC5160A_MOSI_L; } addr <<= 1; TMC5160A_CLK_H; delay(20); data_r[0] <<= 1; if(TMC5160A_ReadVal) { data_r[0] |= 1; } } //数据 for(i = 0; i < 32; i++) { TMC5160A_CLK_L; if(data & 0x80000000) { TMC5160A_MOSI_H; } else { TMC5160A_MOSI_L; } data <<= 1; TMC5160A_CLK_H; delay(20); dat <<= 1; if(TMC5160A_ReadVal) { dat |= 1; } } data_r[0] = addr; data_r[1] = dat >> 24; data_r[2] = dat >> 16; data_r[3] = dat >> 8; data_r[4] = dat >> 0; TMC5160A_CS2_H; //SPI_CS片选拉1 } void TMC5160_SPIReadInt(uint8_t addr, uint8_t record[5])//从addr寄存器读取数据,然后记录到record中 { char i; for(i = 0; i < 5; i++) data_r[i] = 0; TMC5160_SPIWriteInt(addr,0,0); TMC5160_SPIWriteInt(addr,0,0); memcpy(record, data_r, 5); } uint8_t XA[5]={0},VA[5]={0},RAMP_STAT[5],DRV_STAT[5]; //用于存放接收到的8bit*5数据 signed int XA_32 = 0,VA_32 = 0,RAMP_STAT_32 = 0,DRV_STAT_32 = 0; //用于存放从8bit*5转化得到的32位数据 char tmc5160_sw =0; //用于控制电机,在按键功能中使用 signed int Raw_32(uint8_t raw[5]) //把5*8bit数据中的0~31位拼接成1*32bit的数值并返回 { signed int result = 0; result |= raw[1]; result <<= 8; result |= raw[2]; result <<= 8; result|= raw[3]; result <<= 8; result|= raw[4]; return result; } char busy_flag = 0; //忙信号标志 void tmc5160_operate(char operate_mode, uint32_t steps) { switch(operate_mode) { case 0 : //电机停止 { TMC5160_SPIReadInt(VACTUAL_ADDR,VA); //读取实际速度VACTUAL VA_32 = Raw_32(VA); TMC5160_SPIReadInt(XACTUAL_ADDR,XA); //读取实际位置XACTUAL XA_32 = Raw_32(XA); if( VA_32 != 0) //只要实际速度不为0,就进入减速 { busy_flag = 1; rampmode = 0x00000000; TMC5160_SPIWriteInt(RAMPMODE_ADDR,rampmode,1); //开启位置模式 TMC5160_SPIWriteInt(XTARGET_ADDR, XA_32, 1); //把当前位置设为目标位置,开启减速停止 }else { busy_flag = 0; } } break; case 1 : //电机开始正向运动 { if( busy_flag == 0) { busy_flag = 1; //忙信号置1,等待到达目标位置 TMC5160_SPIReadInt(XACTUAL_ADDR,XA); //读取实际位置XACTUAL XA_32 = Raw_32(XA); rampmode = 0x00000000; TMC5160_SPIWriteInt(RAMPMODE_ADDR,rampmode,1); //开启位置模式 TMC5160_SPIWriteInt(XTARGET_ADDR, XA_32 + steps, 1); //此时的实际位置+步长作为目标位置 delay(1000); //静止状态下会被 误判 成已经到达目标位置,因此进行延时等待寄存器发生变化。 } if(busy_flag == 1) { TMC5160_SPIReadInt(RAMP_STAT_ADDR,RAMP_STAT); //运动过程中读取斜坡状态 RAMP_STAT_32 = Raw_32(RAMP_STAT); if(RAMP_STAT_32 & 0x00000200) //到达目标位置,XACTUAL = XTARGET时,第9位会被置 1 { busy_flag = 0; //忙信号清零 } } } break; case 2 : //电机开始反向运动 { if( busy_flag == 0) { busy_flag = 1; TMC5160_SPIReadInt(XACTUAL_ADDR,XA); //读取实际位置XACTUAL XA_32 = Raw_32(XA); rampmode = 0x00000000; TMC5160_SPIWriteInt(RAMPMODE_ADDR,rampmode,1); //开启位置模式 TMC5160_SPIWriteInt(XTARGET_ADDR, XA_32 - steps, 1); delay(1000); //静止状态下会被 误判 成已经到达目标位置,因此进行延时等待寄存器发生变化。 } if(busy_flag == 1) { TMC5160_SPIReadInt(RAMP_STAT_ADDR,RAMP_STAT); //读取斜坡状态 RAMP_STAT_32 = Raw_32(RAMP_STAT); if(RAMP_STAT_32 & 0x00000200) //到达目标位置,XACTUAL = XTARGET时,第9位会被置 1 { busy_flag = 0; } } } break; default : { } break; } } void motor_protect_ads(float threshold_neg, float threshold_pos) { if( (X_ads1220 <= threshold_neg) && ( motor_direc != 1 ) ) //到达负限位后停止,停止后正向 { Motor_Run = 0; motor_direc = 1; } if( (X_ads1220 >= threshold_pos) && ( motor_direc != 2 ) ) //到达正限位后停止,停止后反向 { Motor_Run = 0; motor_direc = 2; } } void motor_protect_ocin(void) { if( (ocin1 == 0) && (motor_direc != 1) ) { tmc5160_operate(0, 0); if(busy_flag == 0) motor_direc = 1; } if( (ocin2 == 0) && ( motor_direc != 2 ) ) { tmc5160_operate(0, 0); if(busy_flag == 0) motor_direc = 2; } }