|
|
@ -2,8 +2,8 @@ |
|
|
|
|
|
|
|
#include "i2c.h"
|
|
|
|
using namespace iflytop; |
|
|
|
#define TAG "hardware"
|
|
|
|
#define ENABLE_CAN 1
|
|
|
|
#define TAG "hardware"
|
|
|
|
#define TEST_TMC_ENCODER_DIRECTION 0
|
|
|
|
extern "C" { |
|
|
|
int fputc(int ch, FILE *stream) { |
|
|
|
uint8_t c = ch; |
|
|
@ -18,148 +18,124 @@ void Hardware::registerListener(HardwareListener *listener) { |
|
|
|
m_listenerNum++; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void Hardware::hardwareinit() { |
|
|
|
STM32_HAL::regListener(this); |
|
|
|
|
|
|
|
m_canOnRxDataFlag = false; |
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* 调试指示灯初始化 * |
|
|
|
*******************************************************************************/ |
|
|
|
debug_light_init(); |
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* CANSLAVEService初始化 * |
|
|
|
*******************************************************************************/ |
|
|
|
IflytopCanSlave::iflytop_can_slave_config_t *config = canSlaveService.createDefaultConfig(DEVICE_ID); |
|
|
|
canSlaveService.initialize(this, config); |
|
|
|
canSlaveService.activateRxIT(); |
|
|
|
canSlaveService.registerListener(this); |
|
|
|
/*******************************************************************************
|
|
|
|
* 帕尔贴初始化 * |
|
|
|
*******************************************************************************/ |
|
|
|
can_init(); |
|
|
|
temperature_init(); |
|
|
|
fan_init(1000); |
|
|
|
peltier_init(); |
|
|
|
/*******************************************************************************
|
|
|
|
* 温度传感器初始化 * |
|
|
|
*******************************************************************************/ |
|
|
|
tmp117[0].initializate(&hi2c1, TMP117::ID0); |
|
|
|
tmp117[1].initializate(&hi2c1, TMP117::ID1); |
|
|
|
tmp117[2].initializate(&hi2c1, TMP117::ID2); |
|
|
|
tmp117[3].initializate(&hi2c1, TMP117::ID3); |
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* 电机初始化 * |
|
|
|
*******************************************************************************/ |
|
|
|
tmc_init(); |
|
|
|
tmc_extern_clk_enable(); |
|
|
|
// 4361初始化
|
|
|
|
TMC4361A::TMC4361AConfig_t *tmc4361aconfig = TMC4361A::createDeafultTMC4361AConfig(this); |
|
|
|
tmc4361aconfig->encoder_config.diff_enc_in_disable = false; |
|
|
|
tmc4361aconfig->encoder_config.invert_enc_dir = true; // 如果编码器方向和期望方向相反,设置为true
|
|
|
|
tmc4361aconfig->encoder_config.enc_in_res = 4000; |
|
|
|
tmc4361aconfig->close_loop_config.enable_closed_loop = false; |
|
|
|
|
|
|
|
tmc4361motor1.initialize(MOTOR_1_TMC4361A_CHANNEL, TMC4361A::IC_TMC2160, tmc4361aconfig); |
|
|
|
tmc4361motor1.setMaximumAcceleration(300000); |
|
|
|
tmc4361motor1.setMaximumDeceleration(300000); |
|
|
|
|
|
|
|
HAL_Delay(100); |
|
|
|
// 使能电机
|
|
|
|
tmc4361motor1.enableIC(true); |
|
|
|
/**
|
|
|
|
* @brief 通过读取Version寄存器来判断芯片是否正常 |
|
|
|
*/ |
|
|
|
int32_t ic4361Version = tmc4361motor1.readICVersion(); |
|
|
|
int32_t ic2160Version = tmc4361motor1.read2160ICVersion(); |
|
|
|
ZLOGI(TAG, "TMC4361Version:%x TMC2160VERSION:%x", ic4361Version, ic2160Version); |
|
|
|
if (ic4361Version != 2) { |
|
|
|
ZLOGE(TAG, "TMC4361 or TMC2160 is not normal"); |
|
|
|
} |
|
|
|
// 期望 4361Version:2 ic2160Version:30
|
|
|
|
// tmc4361motor1.stop();
|
|
|
|
// 测试编码器方向
|
|
|
|
// tmc4361motor1.rotate(-300000);
|
|
|
|
// while (true) {
|
|
|
|
// HAL_Delay(100);
|
|
|
|
// ZLOGI(TAG, "TMC4361A: XACTUAL:%d ENC_POS:%d DIFF:%d", tmc4361motor1.getXACTUAL(), tmc4361motor1.getENC_POS(), tmc4361motor1.getENC_POS_DEV());
|
|
|
|
// }
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* 风扇初始化 * |
|
|
|
*******************************************************************************/ |
|
|
|
fanInit(1000); |
|
|
|
/**
|
|
|
|
* @brief 风扇反馈初始化 |
|
|
|
* |
|
|
|
* FAN0_FB_INT PC1 |
|
|
|
* FAN1_FB_INT PC4 |
|
|
|
* FAN2_FB_INT PC5 |
|
|
|
* FAN3_FB_INT PC6 |
|
|
|
* FAN4_FB_INT PC7 |
|
|
|
* FAN5_FB_INT PC10 |
|
|
|
*/ |
|
|
|
m_fanStateMonitor[0].initialize(this, GPIOC, GPIO_PIN_1, fanGetPowerState(0)); |
|
|
|
m_fanStateMonitor[1].initialize(this, GPIOC, GPIO_PIN_4, fanGetPowerState(1)); |
|
|
|
m_fanStateMonitor[2].initialize(this, GPIOC, GPIO_PIN_5, fanGetPowerState(2)); |
|
|
|
m_fanStateMonitor[3].initialize(this, GPIOC, GPIO_PIN_6, fanGetPowerState(3)); |
|
|
|
m_fanStateMonitor[4].initialize(this, GPIOC, GPIO_PIN_7, fanGetPowerState(4)); |
|
|
|
m_fanStateMonitor[5].initialize(this, GPIOC, GPIO_PIN_10, fanGetPowerState(5)); |
|
|
|
} |
|
|
|
int32_t Hardware::port_tmc4361_get_version(uint8_t channel) { |
|
|
|
int value; |
|
|
|
uint8_t data[5]; |
|
|
|
data[0] = 0x7f; |
|
|
|
tmc_motor_spi_write_and_read(channel, &data[0], 5); |
|
|
|
value = ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | (data[3] << 8) | data[4]; |
|
|
|
return value; |
|
|
|
testHardwareFlag = true; |
|
|
|
} |
|
|
|
void Hardware::periodicJob() { |
|
|
|
#if 0
|
|
|
|
/**
|
|
|
|
* @brief 风扇状态监控服务周期调度 |
|
|
|
*/ |
|
|
|
for (size_t i = 0; i < ZARRAY_SIZE(m_fanStateMonitor); i++) { |
|
|
|
m_fanStateMonitor[i].periodicJob(); |
|
|
|
} |
|
|
|
#endif
|
|
|
|
do_debug_light_state(); |
|
|
|
#if ENABLE_CAN
|
|
|
|
// testCanSlaveTxAndRx();
|
|
|
|
#endif
|
|
|
|
debug_light_periodicJob(); |
|
|
|
can_periodicJob(); |
|
|
|
temperature_periodicJob(); |
|
|
|
fan_periodicJob(); |
|
|
|
peltier_periodicJob(); |
|
|
|
tmc_periodicJob(); |
|
|
|
} |
|
|
|
void Hardware::do_debug_light_state() { |
|
|
|
/*******************************************************************************
|
|
|
|
* 测试指示灯 * |
|
|
|
*******************************************************************************/ |
|
|
|
void Hardware::debug_light_init() { |
|
|
|
STM32_HAL::gpioInit(DEBUG_LIGHT_PORT, DEBUG_LIGHT_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW, GPIO_PIN_RESET); |
|
|
|
} |
|
|
|
|
|
|
|
void Hardware::debug_light_periodicJob() { |
|
|
|
static uint32_t lastprocess = 0; |
|
|
|
if (sys_haspassedms(lastprocess) > 300) { |
|
|
|
lastprocess = HAL_GetTick(); |
|
|
|
HAL_GPIO_TogglePin(DEBUG_LIGHT_PORT, DEBUG_LIGHT_PIN); |
|
|
|
} |
|
|
|
} |
|
|
|
void Hardware::TMC4361APort_setResetPinState(uint16_t channel, bool state) { tmc_nRESET_pin_set_state(channel, state); } |
|
|
|
void Hardware::TMC4361APort_setFREEZEPinState(uint16_t channel, bool state) { tmc_nFREEZE_pin_set_state(channel, state); } |
|
|
|
void Hardware::TMC4361APort_setENNPinState(uint16_t channel, bool state) { tmc_ENN_pin_set_state(channel, state); } |
|
|
|
bool Hardware::TMC4361APort_getTargetReachedPinState(uint16_t channel) { return false; } |
|
|
|
void Hardware::TMC4361APort_sleepus(int32_t us) { sleepus(us); } |
|
|
|
void Hardware::TMC4361APort_readWriteArray(uint8_t *data, size_t length) { tmc_motor_spi_write_and_read(0, data, length); } |
|
|
|
void Hardware::TMC4361APort_setSubICENNPinState(uint16_t channel, bool state) { tmc_subic_ENN_pin_set_state(channel, state); } |
|
|
|
void Hardware::STM32_HAL_onGPIO_EXTI_Callback(uint16_t gpioNum) { |
|
|
|
/*******************************************************************************
|
|
|
|
* CAN * |
|
|
|
*******************************************************************************/ |
|
|
|
void Hardware::can_init() { |
|
|
|
m_can.m_canOnRxDataFlag = false; |
|
|
|
|
|
|
|
IflytopCanSlave::iflytop_can_slave_config_t *config = m_can.canSlaveService.createDefaultConfig(DEVICE_ID); |
|
|
|
m_can.canSlaveService.initialize(this, config); |
|
|
|
m_can.canSlaveService.activateRxIT(); |
|
|
|
m_can.canSlaveService.registerListener(this); |
|
|
|
} |
|
|
|
void Hardware::can_periodicJob() { |
|
|
|
if (testHardwareFlag) { |
|
|
|
static uint32_t lastcall; |
|
|
|
static uint8_t tx[8] = {1, 2, 3, 4, 5, 6, 7, 8}; |
|
|
|
if (hasPassedMS(lastcall) > 1000) { |
|
|
|
lastcall = getTicket(); |
|
|
|
// canSlaveService.translate(0x01, tx, 8, 2);
|
|
|
|
m_can.canSlaveService.sendReport(1, 2, 3, 100); |
|
|
|
if (m_can.canSlaveService.getLastTransmitStatus() == HAL_OK) { |
|
|
|
ZLOGI(TAG, "send ok"); |
|
|
|
} else { |
|
|
|
ZLOGI(TAG, "send fail"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
/**
|
|
|
|
* @brief 赋予盘零位光电触发 |
|
|
|
* @brief 接收CAN消息 |
|
|
|
*/ |
|
|
|
if (gpioNum == TMC_HOME_REF_GPIO_PIN) { |
|
|
|
if (STM32_HAL_GPIO_IS_THIS_PIN_TRIGGER_IRQ(TMC_HOME_REF_GPIO)) { |
|
|
|
if (m_can.m_canOnRxDataFlag) { |
|
|
|
m_can.m_canOnRxDataFlag = false; |
|
|
|
static CAN_RxHeaderTypeDef packetHeader; |
|
|
|
static uint8_t packetData[8]; |
|
|
|
static IflytopCanSlave::packet_t packet; |
|
|
|
while (m_can.canSlaveService.getRxPacket(&packet)) { |
|
|
|
if (testHardwareFlag) { |
|
|
|
ZLOGI(TAG, "rx packet:"); |
|
|
|
ZLOGI(TAG, "\ttype:%01x, targetId:%01x, sourceId:%02x, seq:%02x, regAdd:%02x, regValue:%04x", //
|
|
|
|
packet.type, packet.targetId, packet.sourceId, packet.seq, packet.regAdd, packet.regValue); |
|
|
|
} |
|
|
|
for (size_t i = 0; i < m_listenerNum; i++) { |
|
|
|
m_listener[i]->Hardware_onHomeRefSwitchISR(); |
|
|
|
m_listener[i]->Hardware_OnCanRxData(&packet); |
|
|
|
} |
|
|
|
} |
|
|
|
m_can.canSlaveService.activateRxIT(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void Hardware::debug_light_init() { |
|
|
|
STM32_HAL::gpioInit(DEBUG_LIGHT_PORT, DEBUG_LIGHT_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW, GPIO_PIN_RESET); |
|
|
|
/*******************************************************************************
|
|
|
|
* 温度 * |
|
|
|
*******************************************************************************/ |
|
|
|
void Hardware::temperature_init() { |
|
|
|
m_temperature.tmp117[0].initializate(&hi2c1, TMP117::ID0); |
|
|
|
m_temperature.tmp117[1].initializate(&hi2c1, TMP117::ID1); |
|
|
|
m_temperature.tmp117[2].initializate(&hi2c1, TMP117::ID2); |
|
|
|
m_temperature.tmp117[3].initializate(&hi2c1, TMP117::ID3); |
|
|
|
} |
|
|
|
|
|
|
|
void Hardware::fanInit(int freq) { |
|
|
|
TMP117 *Hardware::temperature_get_tmp117(int off) { |
|
|
|
if (off < 0 || off > 3) { |
|
|
|
ZASSERT(0); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
return &m_temperature.tmp117[off]; |
|
|
|
} |
|
|
|
void Hardware::temperature_periodicJob() { |
|
|
|
if (testHardwareFlag) { |
|
|
|
/**
|
|
|
|
* @brief 周期打印温度 |
|
|
|
*/ |
|
|
|
static uint32_t lastcall; |
|
|
|
if (hasPassedMS(lastcall) > 1000) { |
|
|
|
lastcall = getTicket(); |
|
|
|
for (size_t i = 0; i < 4; i++) { |
|
|
|
float temp = m_temperature.tmp117[i].getTemperature(); |
|
|
|
if (m_temperature.tmp117[i].getLastCallStatus() == HAL_OK) { |
|
|
|
ZLOGI(TAG, "tmp117_%d:%f", i, temp); |
|
|
|
} else { |
|
|
|
ZLOGI(TAG, "tmp117_%d:read fail", i); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
/*******************************************************************************
|
|
|
|
* 风扇 * |
|
|
|
*******************************************************************************/ |
|
|
|
void Hardware::fan_init(int freq) { |
|
|
|
STM32_HAL::setPWMFreq(&htim2, freq); // fan0->fan3
|
|
|
|
STM32_HAL::setPWMFreq(&htim4, freq); // fan4
|
|
|
|
STM32_HAL::setPWMFreq(&htim8, freq); // fan5
|
|
|
@ -170,6 +146,23 @@ void Hardware::fanInit(int freq) { |
|
|
|
STM32_HAL::gpioInit(GPIOC, GPIO_PIN_2, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW, GPIO_PIN_RESET); |
|
|
|
// fan5
|
|
|
|
STM32_HAL::gpioInit(GPIOC, GPIO_PIN_3, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW, GPIO_PIN_RESET); |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief 风扇反馈初始化 |
|
|
|
* |
|
|
|
* FAN0_FB_INT PC1 |
|
|
|
* FAN1_FB_INT PC4 |
|
|
|
* FAN2_FB_INT PC5 |
|
|
|
* FAN3_FB_INT PC6 |
|
|
|
* FAN4_FB_INT PC7 |
|
|
|
* FAN5_FB_INT PC10 |
|
|
|
*/ |
|
|
|
m_fan.fanStateMonitor[0].initialize(this, GPIOC, GPIO_PIN_1, fanGetPowerState(0)); |
|
|
|
m_fan.fanStateMonitor[1].initialize(this, GPIOC, GPIO_PIN_4, fanGetPowerState(1)); |
|
|
|
m_fan.fanStateMonitor[2].initialize(this, GPIOC, GPIO_PIN_5, fanGetPowerState(2)); |
|
|
|
m_fan.fanStateMonitor[3].initialize(this, GPIOC, GPIO_PIN_6, fanGetPowerState(3)); |
|
|
|
m_fan.fanStateMonitor[4].initialize(this, GPIOC, GPIO_PIN_7, fanGetPowerState(4)); |
|
|
|
m_fan.fanStateMonitor[5].initialize(this, GPIOC, GPIO_PIN_10, fanGetPowerState(5)); |
|
|
|
} |
|
|
|
|
|
|
|
void Hardware::fanSetDutyCycle(int fanIndex, uint16_t dutyCycle) { |
|
|
@ -181,10 +174,10 @@ void Hardware::fanSetDutyCycle(int fanIndex, uint16_t dutyCycle) { |
|
|
|
|
|
|
|
if (fanIndex <= 3) { |
|
|
|
STM32_HAL::setPWMDuty(&htim2, TIM_CHANNEL_2, dutyCycle); |
|
|
|
m_fanState[0] = dutyCycle > 0; |
|
|
|
m_fanState[1] = dutyCycle > 0; |
|
|
|
m_fanState[2] = dutyCycle > 0; |
|
|
|
m_fanState[3] = dutyCycle > 0; |
|
|
|
m_fan.m_fanState[0] = dutyCycle > 0; |
|
|
|
m_fan.m_fanState[1] = dutyCycle > 0; |
|
|
|
m_fan.m_fanState[2] = dutyCycle > 0; |
|
|
|
m_fan.m_fanState[3] = dutyCycle > 0; |
|
|
|
|
|
|
|
if (dutyCycle > 0) { |
|
|
|
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); |
|
|
@ -194,7 +187,7 @@ void Hardware::fanSetDutyCycle(int fanIndex, uint16_t dutyCycle) { |
|
|
|
|
|
|
|
} else if (fanIndex == 4) { |
|
|
|
STM32_HAL::setPWMDuty(&htim4, TIM_CHANNEL_3, dutyCycle); |
|
|
|
m_fanState[4] = dutyCycle > 0; |
|
|
|
m_fan.m_fanState[4] = dutyCycle > 0; |
|
|
|
|
|
|
|
if (dutyCycle > 0) { |
|
|
|
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); |
|
|
@ -203,7 +196,7 @@ void Hardware::fanSetDutyCycle(int fanIndex, uint16_t dutyCycle) { |
|
|
|
} |
|
|
|
} else if (fanIndex == 5) { |
|
|
|
STM32_HAL::setPWMDuty(&htim8, TIM_CHANNEL_3, dutyCycle); |
|
|
|
m_fanState[5] = dutyCycle > 0; |
|
|
|
m_fan.m_fanState[5] = dutyCycle > 0; |
|
|
|
|
|
|
|
if (dutyCycle > 0) { |
|
|
|
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET); |
|
|
@ -218,14 +211,53 @@ bool *Hardware::fanGetPowerState(int fanIndex) { |
|
|
|
ZLOGE(TAG, "fanIndex is out of range!"); |
|
|
|
} |
|
|
|
} |
|
|
|
return &m_fanState[fanIndex]; |
|
|
|
return &m_fan.m_fanState[fanIndex]; |
|
|
|
} |
|
|
|
void Hardware::fanSetState0to3(uint16_t dutyCycle) { fanSetDutyCycle(0, dutyCycle); } |
|
|
|
void Hardware::fanSetState4(uint16_t dutyCycle) { fanSetDutyCycle(4, dutyCycle); } |
|
|
|
void Hardware::fanSetState5(uint16_t dutyCycle) { fanSetDutyCycle(5, dutyCycle); } |
|
|
|
void Hardware::fan_periodicJob() { |
|
|
|
/**
|
|
|
|
* @brief 风扇状态监控服务周期调度 |
|
|
|
*/ |
|
|
|
for (size_t i = 0; i < ZARRAY_SIZE(m_fan.fanStateMonitor); i++) { |
|
|
|
m_fan.fanStateMonitor[i].periodicJob(); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief 风扇测试 |
|
|
|
*/ |
|
|
|
if (testHardwareFlag) { |
|
|
|
static uint32_t lastcall; |
|
|
|
static int duty = 0; |
|
|
|
if (hasPassedMS(lastcall) > 1000) { |
|
|
|
lastcall = getTicket(); |
|
|
|
duty += 10; |
|
|
|
if (duty > 100) duty = 0; |
|
|
|
fanSetState0to3(duty); |
|
|
|
fanSetState4(duty); |
|
|
|
fanSetState5(duty); |
|
|
|
/**
|
|
|
|
* @brief DUYT大于零 FANPowerState为1 |
|
|
|
*/ |
|
|
|
ZLOGI(TAG, "Duty:%d,FANState:%d,%d,%d,%d,%d,%d", duty, *fanGetPowerState(0), //
|
|
|
|
*fanGetPowerState(1), //
|
|
|
|
*fanGetPowerState(2), //
|
|
|
|
*fanGetPowerState(3), //
|
|
|
|
*fanGetPowerState(4), //
|
|
|
|
*fanGetPowerState(5)); //
|
|
|
|
|
|
|
|
ZLOGI(TAG, "FANCount:%d,%d,%d,%d,%d,%d", m_fan.fanStateMonitor[0].getCount(), //
|
|
|
|
m_fan.fanStateMonitor[1].getCount(), //
|
|
|
|
m_fan.fanStateMonitor[2].getCount(), //
|
|
|
|
m_fan.fanStateMonitor[3].getCount(), //
|
|
|
|
m_fan.fanStateMonitor[4].getCount(), //
|
|
|
|
m_fan.fanStateMonitor[5].getCount()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
/*******************************************************************************
|
|
|
|
* 帕尔贴驱动电路 * |
|
|
|
* 帕尔贴 * |
|
|
|
*******************************************************************************/ |
|
|
|
void Hardware::peltier_cold_ctr_pwm(int pwm) { |
|
|
|
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pwm); |
|
|
@ -278,6 +310,20 @@ void Hardware::peltier_set_pwm(int pwm) { |
|
|
|
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_10, GPIO_PIN_RESET); /*COLD_CTR*/ |
|
|
|
} |
|
|
|
} |
|
|
|
void Hardware::peltier_periodicJob() { |
|
|
|
if (testHardwareFlag) { |
|
|
|
static uint32_t lastcall; |
|
|
|
static int duty = 0; |
|
|
|
if (hasPassedMS(lastcall) > 1000) { |
|
|
|
lastcall = getTicket(); |
|
|
|
duty += 10; |
|
|
|
if (duty > 100) duty = 0; |
|
|
|
peltier_set_pwm(duty); |
|
|
|
ZLOGI(TAG, "paltier set pwm:%d", duty); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* tmc芯片驱动相关 * |
|
|
|
*******************************************************************************/ |
|
|
@ -288,6 +334,48 @@ void Hardware::tmc_init() { |
|
|
|
GPIOE, GPIO_PIN_12, GPIO_MODE_OUTPUT_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_LOW, GPIO_PIN_SET); |
|
|
|
STM32_HAL::gpioInit( //
|
|
|
|
GPIOE, GPIO_PIN_11, GPIO_MODE_OUTPUT_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_LOW, GPIO_PIN_SET); |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief TMC使用的外部时钟在stm32cubemx中已经进行配置,输出时钟为16MHZ |
|
|
|
* 配置可以参考https://iflytop1.feishu.cn/wiki/wikcnog3hFm6dGFLMRksnhLb7Aw
|
|
|
|
*/ |
|
|
|
|
|
|
|
// 4361初始化
|
|
|
|
TMC4361A::TMC4361AConfig_t *tmc4361aconfig = TMC4361A::createDeafultTMC4361AConfig(this); |
|
|
|
tmc4361aconfig->encoder_config.diff_enc_in_disable = false; |
|
|
|
tmc4361aconfig->encoder_config.invert_enc_dir = true; // 如果编码器方向和期望方向相反,设置为true
|
|
|
|
tmc4361aconfig->encoder_config.enc_in_res = 4000; |
|
|
|
tmc4361aconfig->close_loop_config.enable_closed_loop = false; |
|
|
|
#if TEST_TMC_ENCODER_DIRECTION
|
|
|
|
// 测试编码器方式时关闭闭环控制
|
|
|
|
tmc4361aconfig->close_loop_config.enable_closed_loop = false; |
|
|
|
#endif
|
|
|
|
|
|
|
|
m_tmc.tmc4361motor1.initialize(MOTOR_1_TMC4361A_CHANNEL, TMC4361A::IC_TMC2160, tmc4361aconfig); |
|
|
|
m_tmc.tmc4361motor1.setMaximumAcceleration(300000); |
|
|
|
m_tmc.tmc4361motor1.setMaximumDeceleration(300000); |
|
|
|
|
|
|
|
HAL_Delay(100); |
|
|
|
// 使能电机
|
|
|
|
m_tmc.tmc4361motor1.enableIC(true); |
|
|
|
// 通过读取Version寄存器来判断芯片是否正常
|
|
|
|
int32_t ic4361Version = m_tmc.tmc4361motor1.readICVersion(); |
|
|
|
int32_t ic2160Version = m_tmc.tmc4361motor1.read2160ICVersion(); |
|
|
|
ZLOGI(TAG, "TMC4361Version:%x TMC2160VERSION:%x", ic4361Version, ic2160Version); |
|
|
|
if (ic4361Version != 2) { |
|
|
|
ZLOGE(TAG, "TMC4361 or TMC2160 is not normal"); |
|
|
|
} |
|
|
|
m_tmc.tmc4361motor1.rotate(300000); |
|
|
|
|
|
|
|
#if TEST_TMC_ENCODER_DIRECTION
|
|
|
|
while (true) { |
|
|
|
HAL_Delay(100); |
|
|
|
ZLOGI(TAG, "TMC4361A: XACTUAL:%d ENC_POS:%d DIFF:%d", //
|
|
|
|
m_tmc.tmc4361motor1.getXACTUAL(), //
|
|
|
|
m_tmc.tmc4361motor1.getENC_POS(), //
|
|
|
|
m_tmc.tmc4361motor1.getENC_POS_DEV()); |
|
|
|
} |
|
|
|
#endif
|
|
|
|
} |
|
|
|
|
|
|
|
void Hardware::tmc_motor_spi_select(int channel, bool state) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, state ? GPIO_PIN_SET : GPIO_PIN_RESET); } |
|
|
@ -299,14 +387,6 @@ void Hardware::tmc_motor_spi_write_and_read(int channel, uint8_t *data, size_t l |
|
|
|
tmc_motor_spi_select(channel, true); |
|
|
|
} |
|
|
|
} |
|
|
|
void Hardware::tmc_extern_clk_enable() { |
|
|
|
#if 1
|
|
|
|
/**
|
|
|
|
* @brief TMC使用的外部时钟在stm32cubemx中已经进行配置,输出时钟为16MHZ |
|
|
|
* 配置可以参考https://iflytop1.feishu.cn/wiki/wikcnog3hFm6dGFLMRksnhLb7Aw
|
|
|
|
*/ |
|
|
|
#endif
|
|
|
|
} |
|
|
|
void Hardware::tmc_nFREEZE_pin_set_state(uint8_t channel, bool state) { |
|
|
|
if (channel == MOTOR_1_TMC4361A_CHANNEL) { |
|
|
|
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_12, state ? GPIO_PIN_SET : GPIO_PIN_RESET); |
|
|
@ -319,66 +399,40 @@ void Hardware::tmc_subic_ENN_pin_set_state(uint8_t channel, bool state) { |
|
|
|
} |
|
|
|
} |
|
|
|
void Hardware::tmc_nRESET_pin_set_state(uint8_t channel, bool state) {} |
|
|
|
void Hardware::home_ref_switch_init() { //
|
|
|
|
void Hardware::tmc_home_ref_switch_init() { //
|
|
|
|
STM32_HAL::gpioInitAsEXIT(TMC_HOME_REF_GPIO_PORT, TMC_HOME_REF_GPIO_PIN, GPIO_NOPULL, TMC_HOME_REF_GPIO_IRQ_MODE); |
|
|
|
} |
|
|
|
bool Hardware::home_ref_switch_get_state() { return (HAL_GPIO_ReadPin(TMC_HOME_REF_GPIO_PORT, TMC_HOME_REF_GPIO_PIN) == TMC_HOME_REF_GPIO_USEFUL_STATE); } |
|
|
|
/*******************************************************************************
|
|
|
|
* 硬件测试 * |
|
|
|
*******************************************************************************/ |
|
|
|
void Hardware::testTmp117() { |
|
|
|
static uint32_t lastcall; |
|
|
|
if (hasPassedMS(lastcall) > 1000) { |
|
|
|
lastcall = getTicket(); |
|
|
|
for (size_t i = 0; i < 4; i++) { |
|
|
|
float temp = tmp117[i].getTemperature(); |
|
|
|
if (tmp117[i].getLastCallStatus() == HAL_OK) { |
|
|
|
ZLOGI(TAG, "tmp117_%d:%f", i, temp); |
|
|
|
} else { |
|
|
|
ZLOGI(TAG, "tmp117_%d:read fail", i); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
bool Hardware::tmc_home_ref_switch_get_state() { return (HAL_GPIO_ReadPin(TMC_HOME_REF_GPIO_PORT, TMC_HOME_REF_GPIO_PIN) == TMC_HOME_REF_GPIO_USEFUL_STATE); } |
|
|
|
int32_t Hardware::tmc_tmc4361_get_version(uint8_t channel) { |
|
|
|
int value; |
|
|
|
uint8_t data[5]; |
|
|
|
data[0] = 0x7f; |
|
|
|
tmc_motor_spi_write_and_read(channel, &data[0], 5); |
|
|
|
value = ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | (data[3] << 8) | data[4]; |
|
|
|
return value; |
|
|
|
} |
|
|
|
void Hardware::tmc_periodicJob() { m_tmc.tmc4361motor1.periodicJob(getTicket()); } |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief 测试CAN的发送和接收 |
|
|
|
*/ |
|
|
|
void Hardware::testCanSlaveTxAndRx() { |
|
|
|
{ |
|
|
|
static uint32_t lastcall; |
|
|
|
static uint8_t tx[8] = {1, 2, 3, 4, 5, 6, 7, 8}; |
|
|
|
if (hasPassedMS(lastcall) > 1000) { |
|
|
|
lastcall = getTicket(); |
|
|
|
// canSlaveService.translate(0x01, tx, 8, 2);
|
|
|
|
canSlaveService.sendReport(1, 2, 3, 100); |
|
|
|
if (canSlaveService.getLastTransmitStatus() == HAL_OK) { |
|
|
|
ZLOGI(TAG, "send ok"); |
|
|
|
} else { |
|
|
|
ZLOGI(TAG, "send fail"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
/*******************************************************************************
|
|
|
|
* TMC4361APort * |
|
|
|
*******************************************************************************/ |
|
|
|
|
|
|
|
void Hardware::TMC4361APort_setResetPinState(uint16_t channel, bool state) { tmc_nRESET_pin_set_state(channel, state); } |
|
|
|
void Hardware::TMC4361APort_setFREEZEPinState(uint16_t channel, bool state) { tmc_nFREEZE_pin_set_state(channel, state); } |
|
|
|
void Hardware::TMC4361APort_setENNPinState(uint16_t channel, bool state) { tmc_ENN_pin_set_state(channel, state); } |
|
|
|
bool Hardware::TMC4361APort_getTargetReachedPinState(uint16_t channel) { return false; } |
|
|
|
void Hardware::TMC4361APort_sleepus(int32_t us) { sleepus(us); } |
|
|
|
void Hardware::TMC4361APort_readWriteArray(uint8_t *data, size_t length) { tmc_motor_spi_write_and_read(0, data, length); } |
|
|
|
void Hardware::TMC4361APort_setSubICENNPinState(uint16_t channel, bool state) { tmc_subic_ENN_pin_set_state(channel, state); } |
|
|
|
void Hardware::STM32_HAL_onGPIO_EXTI_Callback(uint16_t gpioNum) { |
|
|
|
/**
|
|
|
|
* @brief 接收CAN消息 |
|
|
|
* @brief 赋予盘零位光电触发 |
|
|
|
*/ |
|
|
|
if (m_canOnRxDataFlag) { |
|
|
|
m_canOnRxDataFlag = false; |
|
|
|
static CAN_RxHeaderTypeDef packetHeader; |
|
|
|
static uint8_t packetData[8]; |
|
|
|
// while (canSlaveService.getRxMessage(&packetHeader, packetData)) {
|
|
|
|
// ZLOGI(TAG, "rx packet:");
|
|
|
|
// ZLOGI(TAG, "\tid:%x len:%d", packetHeader.StdId, packetHeader.DLC);
|
|
|
|
// ZLOGI_HEX(TAG, packetData, packetHeader.DLC);
|
|
|
|
// }
|
|
|
|
|
|
|
|
static IflytopCanSlave::packet_t packet; |
|
|
|
while (canSlaveService.getRxPacket(&packet)) { |
|
|
|
ZLOGI(TAG, "rx packet:"); |
|
|
|
ZLOGI(TAG, "\ttype:%01x, targetId:%01x, sourceId:%02x, seq:%02x, regAdd:%02x, regValue:%04x", //
|
|
|
|
packet.type, packet.targetId, packet.sourceId, packet.seq, packet.regAdd, packet.regValue); |
|
|
|
if (gpioNum == TMC_HOME_REF_GPIO_PIN) { |
|
|
|
if (STM32_HAL_GPIO_IS_THIS_PIN_TRIGGER_IRQ(TMC_HOME_REF_GPIO)) { |
|
|
|
for (size_t i = 0; i < m_listenerNum; i++) { |
|
|
|
m_listener[i]->Hardware_onHomeRefSwitchISR(); |
|
|
|
} |
|
|
|
} |
|
|
|
canSlaveService.activateRxIT(); |
|
|
|
} |
|
|
|
} |