#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 = 0x000005DC; //A1 过渡阶段的加速度 uint32_t acc_max = 0x000003E8; //AMAX 最大加速度 uint32_t dcr_1 = 0x00000BB8; //D1 过渡阶段的减速度 uint32_t dcr_max = 0x000007D0; //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, 0x000001F4,1); // writing value 0x00000041 = 65 = 0.0 to address 10 = 0x13(TPWMTHRS) TMC5160_SPIWriteInt(0x14, 0x00000010,1); // writing value 0x00004189 = 16777 = 0.0 to address 11 = 0x14(TCOOLTHRS) TMC5160_SPIWriteInt(0x15, 0x00000010,1); // writing value 0x00000000 = 0 = 0.0 to address 12 = 0x15(THIGH) // 斜波发生器运动寄存器 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); // writing value 0x00000400 = 1024 = 0.0 to address 26 = 0x34(SW_MODE) // // 编码器寄存器 // 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); // writing value 0x00410153 = 4260179 = 0.0 to address 41 = 0x6C(CHOPCONF) TMC5160_SPIWriteInt(0x6D, 0x00000000,1); // writing value 0x00030000 = 196608 = 0.0 to address 42 = 0x6D(COOLCONF) // TMC5160_SPIWriteInt(0x6E, 0x00000000,1); // writing value 0x00000000 = 0 = 0.0 to address 43 = 0x6E(DCCTRL) TMC5160_SPIWriteInt(0x70, 0xC40C001E,1); // writing value 0xC40C001E = 0 = 0.0 to address 44 = 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]; signed int XA_32 = 0,VA_32 = 0,RAMP_STAT_32 = 0,DRV_STAT_32 = 0; //有正负 uint16_t SG_RESULT_16 = 0; char tmc5160_sw =0; //void tmc5160_act() //{ // TMC5160_SPIReadInt(XACTUAL_ADDR,XA);//读取实际位置XACTUAL // XA_32 = Raw_32(XA); // TMC5160_SPIReadInt(VACTUAL_ADDR,VA);//读取实际速度VACTUAL // VA_32 = Raw_32(VA); // if(tmc5160_sw == 1) // { // HAL_GPIO_WritePin(LED_ERR_GPIO_Port,LED_ERR_Pin,GPIO_PIN_RESET); //蓝灯常亮 // // rampmode = 0x00000001; // TMC5160_SPIWriteInt(RAMPMODE_ADDR,rampmode,1); //开启速度模式 // //// rampmode = 0x00000000; //// TMC5160_SPIWriteInt(RAMPMODE_ADDR,rampmode,1); //开启位置模式 //// if( XA_32 == 0x00000000 ) //// { //// xtarget = 0x00025800; //// TMC5160_SPIWriteInt(XTARGET_ADDR, xtarget,1); //正向转动3圈 //// } //// //// if( XA_32== 0x00025800 ) //// { //// xtarget = 0x00000000; //// TMC5160_SPIWriteInt(XTARGET_ADDR, xtarget,1); //接着反向转3圈(返回起点) //// } // }else // { // TMC5160_SPIWriteInt(XTARGET_ADDR,XA_32,1); //把当前位置设定为目标位置,进入减速阶段 // // if( abs(VA_32) <= 0x0000000A ) // 视作已经停止 // { // HAL_GPIO_TogglePin(LED_ERR_GPIO_Port,LED_ERR_Pin); //蓝灯闪烁 // // } // } // //} signed int Raw_32(uint8_t raw[5]) //把5*8bit数据中的0~31位拼接成1*32bit的数值并返回 { uint32_t result = 0; result |= raw[1]; result <<= 8; result |= raw[2]; result <<= 8; result|= raw[3]; result <<= 8; result|= raw[4]; return result; } uint32_t X_temp = 0; char busy_flag = 0; void tmc5160_operate(char operate_mode, uint32_t steps) { switch(operate_mode) { case 0 : //电机停止 { VA_32 = Raw_32(VA); if( VA_32 != 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; X_temp = XA_32; //记录此时的实际位置 rampmode = 0x00000000; TMC5160_SPIWriteInt(RAMPMODE_ADDR,rampmode,1); //开启位置模式 TMC5160_SPIWriteInt(XTARGET_ADDR, X_temp + steps, 1); //此时的实际位置+步长作为目标位置 } if(busy_flag == 1) { delay(100); //静止状态下会被 误判 成已经到达目标位置,因此进行延时等待寄存器发生变化。 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; X_temp = 0; } } } break; case 2 : //电机开始反向运动 { if( busy_flag == 0) { busy_flag = 1; X_temp = XA_32; rampmode = 0x00000000; TMC5160_SPIWriteInt(RAMPMODE_ADDR,rampmode,1); //开启位置模式 TMC5160_SPIWriteInt(XTARGET_ADDR, X_temp - steps, 1); } if(busy_flag == 1) { delay(100); //静止状态下会被 误判 成已经到达目标位置,因此进行延时等待寄存器发生变化。 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; X_temp = 0; } } } break; // case 3 : //电机回到起点(上电位置) // { // if( busy_flag == 0) // { // busy_flag = 1; // rampmode = 0x00000000; // TMC5160_SPIWriteInt(RAMPMODE_ADDR,rampmode,1); //开启位置模式 // // speed_max <<=1; // TMC5160_SPIWriteInt(VMAX_ADDR, speed_max, 1); //以二倍速返回零点 // TMC5160_SPIWriteInt(XTARGET_ADDR, 0x00000000, 1); // } // if( RAMP_STAT_32 & 0x00000200 ) // { // busy_flag = 0; // speed_max >>=1; // TMC5160_SPIWriteInt(VMAX_ADDR, speed_max, 1); //恢复原速 // } // } // break; default : { } break; } } void motor_protect_ads(float threshold_neg, float threshold_pos) { if( (X_ads1220_prc <= threshold_neg) && (motor_direc != 1) ) { tmc5160_operate(0, 0); if(busy_flag == 0) motor_direc = 1; } if( (X_ads1220_prc >= threshold_pos) && ( motor_direc != 2 ) ) { tmc5160_operate(0, 0); if(busy_flag == 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; } }