38 changed files with 6 additions and 4556 deletions
-
BINhmp110/HMM100-Datasheet-B210813ZH.pdf
-
BINhmp110/HMP110 DOC247480-A Simplified Models.zip
-
BINhmp110/HMP110-Datasheet-B210852ZH.pdf
-
BINhmp110/HMP60-and-HMP110-Series-User-Guide-M211060EN-L.pdf
-
118hmp110/hmp110.cpp
-
71hmp110/hmp110.hpp
-
BINhpp272/HPP272-使用说明书.pdf
-
8hpp272/README.md
-
71hpp272/hpp272.cpp
-
79hpp272/hpp272.hpp
-
BINhpp272/过氧化氢传感器读取.zip
-
67modbus/modbus_basic.cpp
-
28modbus/modbus_basic.hpp
-
202modbus/modbus_block_host.cpp
-
31modbus/modbus_block_host.hpp
-
107preportional_valve/preportional_valve_ctrl.cpp
-
49preportional_valve/preportional_valve_ctrl.hpp
-
BINpxx_pressure_sensor_driver/DP600--RS485通讯说明书V0.1.docx
-
BINpxx_pressure_sensor_driver/HCP300新说明书.pdf
-
BINpxx_pressure_sensor_driver/P100标准MODBUS RTU通讯协议.pdf
-
244pxx_pressure_sensor_driver/pxx_pressure_sensor_bus.cpp
-
75pxx_pressure_sensor_driver/pxx_pressure_sensor_bus.hpp
-
6stm32basic.hpp
-
153sys_mgr.cpp
-
51sys_mgr.hpp
-
BINtmc/TMC5130A_datasheet_rev1.20 (1).pdf
-
19tmcdriver/tmc/tmc_type.h
-
67tmcdriver/tmc51x0/reg/TMC5130_Constants.h
-
1475tmcdriver/tmc51x0/reg/TMC5130_Fields.h
-
74tmcdriver/tmc51x0/reg/TMC5130_Register.h
-
59tmcdriver/tmc51x0/reg/TMC5130_Type.h
-
439tmcdriver/tmc51x0/tmc51x0.cpp
-
125tmcdriver/tmc51x0/tmc51x0.hpp
-
429zcanreceiver/zcanreceiver.cpp
-
48zcanreceiver/zcanreceiver.hpp
-
350zcanreceiver_old/zcanreceiver.cpp
-
116zcanreceiver_old/zcanreceiver.hpp
-
1zsdk.hpp
@ -1,118 +0,0 @@ |
|||
#include "hmp110.hpp"
|
|||
|
|||
#include "stm32basic/modbus/modbus_block_host.hpp"
|
|||
|
|||
using namespace iflytop; |
|||
|
|||
#define TAG "HMP110"
|
|||
|
|||
void HMP110::init(ModbusBlockHost* modbusBlockHost) { |
|||
m_modbusBlockHost = modbusBlockHost; |
|||
m_id = 240; |
|||
|
|||
m_cache_lock.init(); |
|||
m_chlock.init(); |
|||
} |
|||
|
|||
bool HMP110::readReg03(uint8_t slaveAddr, uint16_t regAddr, uint16_t* regVal, int overtimems) { //
|
|||
zlock_guard lck(m_chlock); |
|||
// ZLOGI(TAG, "=============== readReg03 %d %d", slaveAddr, regAddr);
|
|||
bool ret = m_modbusBlockHost->readReg03(slaveAddr, regAddr, regVal, overtimems); |
|||
// ZLOGI(TAG, "=============== END%d", ret);
|
|||
|
|||
|
|||
return ret; |
|||
} |
|||
bool HMP110::readReg03Muti(uint8_t slaveAddr, uint16_t regAddr, uint16_t* regVal, int regNum, int overtimems) { //
|
|||
zlock_guard lck(m_chlock); |
|||
// ZLOGI(TAG, "=============== readReg03Muti %d %d %d", slaveAddr, regAddr, regNum);
|
|||
bool ret = m_modbusBlockHost->readReg03Muti(slaveAddr, regAddr, regVal, regNum, overtimems); |
|||
// ZLOGI(TAG, "=============== END%d", ret);
|
|||
return ret; |
|||
} |
|||
bool HMP110::ping(int id) { |
|||
int16_t val = 0; |
|||
return readReg03(id, 0x1F00, (uint16_t*)&val, 300); |
|||
} |
|||
|
|||
void HMP110::setid(int32_t id) { m_id = id; } |
|||
|
|||
void HMP110::read_calibration_date(int32_t* year, int32_t* month, int32_t* day) { // TODO
|
|||
*year = 1; |
|||
*month = 2; |
|||
*day = 3; |
|||
} |
|||
int32_t HMP110::read_errorcode() { |
|||
int16_t val = 0; |
|||
bool suc = readReg03(m_id, 0x0200, (uint16_t*)&val, 300); |
|||
if (!suc) { |
|||
return -1; |
|||
} |
|||
|
|||
if (val == 1) { |
|||
return 0; |
|||
} |
|||
uint16_t ecodebuf[2]; |
|||
suc = readReg03Muti(m_id, 0x0203, ecodebuf, 2, 300); |
|||
|
|||
uint32_t ecode = ecodebuf[0] | (((uint32_t)ecodebuf[1]) << 16); |
|||
return ecode; |
|||
} |
|||
|
|||
bool HMP110::read_reg(int32_t add, uint16_t* val, size_t len) { |
|||
// ZLOGI(TAG, "read_reg %x %d", add, len);
|
|||
bool suc = readReg03Muti(m_id, add, val, len, 300); |
|||
// if (suc)
|
|||
// for (size_t i = 0; i < len; i++) {
|
|||
// ZLOGI(TAG, "val[%d] = %d", i, val[i]);
|
|||
// }
|
|||
// else
|
|||
// ZLOGE(TAG, "read_reg failed");
|
|||
return suc; |
|||
} |
|||
|
|||
bool HMP110::read_sensor_data(hmp110_sensordata_t* sensordata) { |
|||
uint16_t buf[7]; |
|||
bool suc = readReg03Muti(m_id, 0x0100, buf, 7, 300); |
|||
if (!suc) { |
|||
return false; |
|||
} |
|||
|
|||
sensordata->rh = buf[0]; |
|||
sensordata->temp = buf[1]; |
|||
sensordata->df_ptemp = buf[2]; |
|||
sensordata->ah = buf[3]; |
|||
sensordata->mr = buf[4]; |
|||
sensordata->wet_bulb_temp = buf[5]; |
|||
sensordata->enthalpy = buf[6]; |
|||
return true; |
|||
} |
|||
|
|||
void HMP110::updateSensorDataAndErrorcode() { |
|||
bool suc = read_sensor_data(&m_rdbuf); |
|||
osDelay(100); |
|||
int32_t errorcode = read_errorcode(); |
|||
if (errorcode != 0) { |
|||
ZLOGE(TAG, "errorcode: %d", errorcode); |
|||
} |
|||
if (!suc) { |
|||
ZLOGE(TAG, "read_sensor_data failed"); |
|||
errorcode = -1; |
|||
} |
|||
|
|||
{ |
|||
zlock_guard lck(m_cache_lock); |
|||
m_cachedata = m_rdbuf; |
|||
m_cache_errorcode = errorcode; |
|||
} |
|||
} |
|||
|
|||
int32_t HMP110::read_cache_errorcode() { |
|||
zlock_guard lck(m_cache_lock); |
|||
return m_cache_errorcode; |
|||
} |
|||
bool HMP110::read_cache_sensor_data(hmp110_sensordata_t* sensordata) { |
|||
zlock_guard lck(m_cache_lock); |
|||
*sensordata = m_cachedata; |
|||
return true; |
|||
} |
@ -1,71 +0,0 @@ |
|||
#pragma once
|
|||
#include <stddef.h>
|
|||
#include <stdio.h>
|
|||
|
|||
#include "stm32basic/modbus/modbus_block_host.hpp"
|
|||
#include "stm32basic/zsdk.hpp"
|
|||
|
|||
namespace iflytop { |
|||
|
|||
#define PXX_PRESSURE_SENSOR_NUM 10
|
|||
|
|||
class HMP110 { |
|||
public: |
|||
#pragma pack(1)
|
|||
|
|||
typedef struct { |
|||
int16_t rh; // Relative humidity %RH * 10
|
|||
int16_t temp; // Temperature °C * 10
|
|||
int16_t df_ptemp; // Dew/frost point temperature °C * 10
|
|||
int16_t ah; // Absolute humidity g/m3 * 10
|
|||
int16_t mr; // Mixing ratio g/kg * 10
|
|||
int16_t wet_bulb_temp; // Wet-bulb temperature °C * 10
|
|||
int16_t enthalpy; // Enthalpy kJ/kg * 10
|
|||
} hmp110_sensordata_t; |
|||
#pragma pack()
|
|||
|
|||
private: |
|||
/***********************************************************************************************************************
|
|||
* DATA * |
|||
***********************************************************************************************************************/ |
|||
|
|||
ModbusBlockHost* m_modbusBlockHost = NULL; |
|||
int32_t m_id = 0; |
|||
zmutex m_lock; |
|||
|
|||
hmp110_sensordata_t m_rdbuf; |
|||
|
|||
hmp110_sensordata_t m_cachedata; |
|||
int32_t m_cache_errorcode = 0; |
|||
zmutex m_cache_lock; |
|||
|
|||
zmutex m_chlock; |
|||
|
|||
|
|||
public: |
|||
/***********************************************************************************************************************
|
|||
* FUNC * |
|||
***********************************************************************************************************************/ |
|||
|
|||
void init(ModbusBlockHost* modbusBlockHost); |
|||
|
|||
bool ping(int id); |
|||
bool ping(); |
|||
void setid(int32_t id); |
|||
|
|||
void read_calibration_date(int32_t* year, int32_t* month, int32_t* day); // TODO
|
|||
int32_t read_errorcode(); // ret == -1 表明设备不在线
|
|||
bool read_reg(int32_t add, uint16_t* val, size_t len); |
|||
bool read_sensor_data(hmp110_sensordata_t* sensordata); |
|||
|
|||
void updateSensorDataAndErrorcode(); |
|||
|
|||
int32_t read_cache_errorcode(); |
|||
bool read_cache_sensor_data(hmp110_sensordata_t* sensordata); |
|||
|
|||
public: |
|||
bool readReg03(uint8_t slaveAddr, uint16_t regAddr, uint16_t* regVal, int overtimems); |
|||
bool readReg03Muti(uint8_t slaveAddr, uint16_t regAddr, uint16_t* regVal, int regNum, int overtimems); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -1,8 +0,0 @@ |
|||
|
|||
``` |
|||
注意事项: |
|||
1. 串口停止位是2位 |
|||
2. 波特率19200 |
|||
3. 默认ID 240 |
|||
|
|||
``` |
@ -1,71 +0,0 @@ |
|||
#include "hpp272.hpp"
|
|||
|
|||
#include "stm32basic/modbus/modbus_block_host.hpp"
|
|||
|
|||
using namespace iflytop; |
|||
|
|||
#define TAG "HPP272"
|
|||
|
|||
void HPP272::init(ModbusBlockHost* modbusBlockHost) { |
|||
m_modbusBlockHost = modbusBlockHost; |
|||
m_id = 240; |
|||
|
|||
m_cache_lock.init(); |
|||
} |
|||
bool HPP272::ping(int id) { |
|||
int16_t val = 0; |
|||
return m_modbusBlockHost->readReg03(id, 0x1F00, (uint16_t*)&val, 100); |
|||
} |
|||
|
|||
void HPP272::setid(int32_t id) { m_id = id; } |
|||
|
|||
void HPP272::read_calibration_date(int32_t* year, int32_t* month, int32_t* day) { // TODO
|
|||
*year = 0; |
|||
*month = 0; |
|||
*day = 0; |
|||
} |
|||
int32_t HPP272::read_errorcode() { |
|||
int16_t val = 0; |
|||
bool suc = m_modbusBlockHost->readReg03(m_id, 0x0200, (uint16_t*)&val, 100); |
|||
if (!suc) { |
|||
return -1; |
|||
} |
|||
|
|||
// 0 = Status OK.
|
|||
// 1 = Critical error,maintenance needed.
|
|||
// 2 = Error, device may recover automatically.
|
|||
// 4 = Warning.
|
|||
// 8 = Notification.
|
|||
// 16 = Calibration enabled
|
|||
|
|||
return val; |
|||
} |
|||
|
|||
bool HPP272::read_reg(int32_t add, uint16_t* val, size_t len) { return m_modbusBlockHost->readReg03Muti(m_id, add, val, len, 100); } |
|||
|
|||
bool HPP272::read_sensor_data(hpp272_data_t* sensordata) { //
|
|||
return m_modbusBlockHost->readReg03Muti(m_id, 0x0100, (uint16_t*)sensordata, sizeof(*sensordata) / 2, 100); |
|||
} |
|||
|
|||
void HPP272::updateSensorDataAndErrorcode() { |
|||
if (!read_sensor_data(&m_readbuf)) { |
|||
return; |
|||
} |
|||
int32_t errorcode = read_errorcode(); |
|||
|
|||
{ |
|||
zlock_guard lck(m_cache_lock); |
|||
m_cachedata = m_readbuf; |
|||
m_cache_errorcode = errorcode; |
|||
} |
|||
} |
|||
|
|||
int32_t HPP272::read_cache_errorcode() { |
|||
zlock_guard lck(m_cache_lock); |
|||
return m_cache_errorcode; |
|||
} |
|||
bool HPP272::read_cache_sensor_data(hpp272_data_t* sensordata) { |
|||
zlock_guard lck(m_cache_lock); |
|||
*sensordata = m_cachedata; |
|||
return true; |
|||
} |
@ -1,79 +0,0 @@ |
|||
#pragma once
|
|||
#include <stddef.h>
|
|||
#include <stdio.h>
|
|||
|
|||
#include "base/config_service.hpp"
|
|||
#include "stm32basic/modbus/modbus_block_host.hpp"
|
|||
#include "stm32basic/zsdk.hpp"
|
|||
|
|||
namespace iflytop { |
|||
|
|||
#define PXX_PRESSURE_SENSOR_NUM 10
|
|||
|
|||
class HPP272 { |
|||
public: |
|||
#pragma pack(1)
|
|||
typedef struct { |
|||
uint16_t hydrogen_peroxide_volume; // ppm 0x0100
|
|||
uint16_t h2o_h2o2_rs; // %RS * 100
|
|||
uint16_t temperature1; // °C * 100
|
|||
uint16_t relative_humidity; // %RH * 100
|
|||
uint16_t absolute_hydrogen_peroxide; // mg/m3
|
|||
uint16_t h2o_h2o2dew_point_temperature; // °C * 100
|
|||
uint16_t reserved1; //
|
|||
uint16_t water_volume; // ppm
|
|||
uint16_t water_vapor_pressure; // hpa
|
|||
uint16_t absolute_humidity; // g/m3
|
|||
uint16_t water_vapor_saturation_pressure_h2o; // hpa
|
|||
uint16_t temperature2; // °C * 100
|
|||
uint16_t h2o2_vapor_pressure; // hpa
|
|||
uint16_t water_vapor_saturation_pressure_h2o_h2o2; // hpa
|
|||
} hpp272_data_t; |
|||
#pragma pack()
|
|||
|
|||
private: |
|||
/***********************************************************************************************************************
|
|||
* DATA * |
|||
***********************************************************************************************************************/ |
|||
|
|||
ModbusBlockHost* m_modbusBlockHost = NULL; |
|||
|
|||
int32_t m_id = 0; |
|||
zmutex m_lock; |
|||
|
|||
hpp272_data_t m_readbuf; |
|||
|
|||
hpp272_data_t m_cachedata; |
|||
int32_t m_cache_errorcode = 0; |
|||
zmutex m_cache_lock; |
|||
|
|||
public: |
|||
/***********************************************************************************************************************
|
|||
* FUNC * |
|||
***********************************************************************************************************************/ |
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* @param modbusBlockHost |
|||
*/ |
|||
void init(ModbusBlockHost* modbusBlockHost); |
|||
|
|||
bool ping(int id); |
|||
bool ping(); |
|||
void setid(int32_t id); |
|||
|
|||
void read_calibration_date(int32_t* year, int32_t* month, int32_t* day); // TODO
|
|||
int32_t read_errorcode(); // see datasheet page83
|
|||
bool read_reg(int32_t add, uint16_t* val, size_t len); |
|||
bool read_sensor_data(hpp272_data_t* sensordata); |
|||
|
|||
void updateSensorDataAndErrorcode(); |
|||
|
|||
int32_t read_cache_errorcode(); |
|||
bool read_cache_sensor_data(hpp272_data_t* sensordata); |
|||
|
|||
public: |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -1,67 +0,0 @@ |
|||
/**
|
|||
* Modbus |
|||
* | add(1byte) | functionCode(1byte) | ...data... | crc1(1byte) | crc2(2byte)| |
|||
* |
|||
* |
|||
* |
|||
* |
|||
*/ |
|||
#include "modbus_basic.hpp"
|
|||
|
|||
#include <stdint.h>
|
|||
// CRC_16高8位数据区
|
|||
#define ASSERT(con) \
|
|||
while (!(con)) { \ |
|||
} |
|||
static const uint8_t auchCRCHi[] = { |
|||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, |
|||
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
|||
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, |
|||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
|||
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, |
|||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, |
|||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, |
|||
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
|||
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, |
|||
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40}; |
|||
// CRC低位字节值表
|
|||
static const uint8_t auchCRCLo[] = { // CRC_16低8位数据区
|
|||
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, |
|||
0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, |
|||
0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, |
|||
0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, |
|||
0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, |
|||
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, |
|||
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, |
|||
0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, |
|||
0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, |
|||
0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40}; |
|||
|
|||
/*CRC16查表计算函数*/ |
|||
|
|||
uint16_t modbus_gen_crc16(uint8_t *puckMsg, uint8_t usDataLen) { |
|||
volatile uint8_t uchCRCHi = 0xFF; // 高CRC字节初始化
|
|||
volatile uint8_t uchCRCLo = 0xFF; // 低CRC 字节初始化
|
|||
volatile uint32_t uIndex; // CRC循环中的索引
|
|||
// 传输消息缓冲区
|
|||
while (usDataLen--) { |
|||
// 计算CRC
|
|||
uIndex = uchCRCLo ^ *puckMsg++; |
|||
uchCRCLo = uchCRCHi ^ auchCRCHi[uIndex]; |
|||
uchCRCHi = auchCRCLo[uIndex]; |
|||
} |
|||
// 返回结果,高位在前
|
|||
return (uchCRCLo << 8 | uchCRCHi); |
|||
} |
|||
|
|||
void modbus_pack_crc_to_packet(uint8_t *puckMsg, uint8_t packetlen) { |
|||
uint16_t crc = modbus_gen_crc16(puckMsg, packetlen - 2); |
|||
puckMsg[packetlen - 2] = crc >> 8; |
|||
puckMsg[packetlen - 1] = crc; |
|||
} |
|||
|
|||
/*函数功能:用于校验接收到的信息是否有误
|
|||
输入参数:message是接收到的待校验消息,length是消息字节的长度 |
|||
函数输出:输出校验结果,没有错返回True,有错返回False |
|||
通过CRC校验校验接收的信息是否正确*/ |
|||
bool modbus_checkcrc16(uint8_t *message, uint8_t length) { return (modbus_gen_crc16(message, length) == 0x00) ? true : false; } |
@ -1,28 +0,0 @@ |
|||
#pragma once
|
|||
#include <stdbool.h>
|
|||
#include <stdint.h>
|
|||
|
|||
/**
|
|||
* @brief 生成CRC16校验码 |
|||
* |
|||
* @param puckMsg 数据指针 |
|||
* @param usDataLen 数据长度(不包含CRC16) |
|||
* @return uint16_t |
|||
*/ |
|||
uint16_t modbus_gen_crc16(uint8_t *puckMsg, uint8_t usDataLen); |
|||
/**
|
|||
* @brief 将CRC16校验码添加到数据包中 |
|||
* |
|||
* @param puckMsg 数据指针,数据中预留两个位置给CRC16 |
|||
* @param packetlen 数据长度 |
|||
*/ |
|||
void modbus_pack_crc_to_packet(uint8_t *puckMsg, uint8_t packetlen); |
|||
/**
|
|||
* @brief 检查CRC16校验码 |
|||
* |
|||
* @param message 数据指针 |
|||
* @param length 数据长度(包含CRC16) |
|||
* @return true 校验成功 |
|||
* @return false 校验失败 |
|||
*/ |
|||
bool modbus_checkcrc16(uint8_t *message, uint8_t length); |
@ -1,202 +0,0 @@ |
|||
#include "modbus_block_host.hpp"
|
|||
|
|||
#include "modbus_basic.hpp"
|
|||
using namespace iflytop; |
|||
#define PRV_DEBUG 0
|
|||
ModbusBlockHost::ModbusBlockHost() {} |
|||
ModbusBlockHost::~ModbusBlockHost() {} |
|||
|
|||
extern "C" { |
|||
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {} |
|||
} |
|||
|
|||
void ModbusBlockHost::initialize(UART_HandleTypeDef *huart) { |
|||
this->huart = huart; |
|||
m_modbus_lock.init(); |
|||
} |
|||
void ModbusBlockHost::cleanRxBuff() { //
|
|||
HAL_StatusTypeDef status; |
|||
do { |
|||
status = HAL_UART_Receive(huart, rxbuff, 1, 1); |
|||
} while (status == HAL_OK); |
|||
} |
|||
|
|||
void ModbusBlockHost::uarttx(uint8_t *buff, size_t len) { |
|||
ZASSERT(len < sizeof(txbuff)); |
|||
#if PRV_DEBUG
|
|||
printf("uart_tx:\n"); |
|||
for (size_t i = 0; i < len; i++) { |
|||
printf("%02x ", buff[i]); |
|||
} |
|||
printf("\n"); |
|||
#endif
|
|||
// HAL_UART_Transmit(huart, buff, len, 1000);
|
|||
HAL_UART_DMAStop(huart); |
|||
HAL_StatusTypeDef ret = HAL_UART_Transmit_DMA(huart, buff, len); |
|||
ZASSERT(ret == HAL_OK); |
|||
|
|||
// 等待DMA传输完成
|
|||
while (true) { |
|||
if (HAL_UART_GetState(huart) == HAL_UART_STATE_READY) break; |
|||
} |
|||
return; |
|||
} |
|||
bool ModbusBlockHost::uartrx(uint8_t *buff, size_t len, int overtimems) { |
|||
HAL_StatusTypeDef status; |
|||
ZASSERT(len < sizeof(rxbuff)); |
|||
|
|||
status = HAL_UART_Receive_DMA(huart, buff, len); |
|||
|
|||
if (status != HAL_OK) { |
|||
return false; |
|||
} |
|||
|
|||
for (size_t i = 0; i < overtimems; i++) { |
|||
osDelay(3); |
|||
if (HAL_UART_GetState(huart) == HAL_UART_STATE_READY) { |
|||
#if PRV_DEBUG
|
|||
if (status == HAL_OK) { |
|||
printf("uart_rx:"); |
|||
for (size_t i = 0; i < len; i++) { |
|||
printf("%02x ", buff[i]); |
|||
} |
|||
printf("\n"); |
|||
} |
|||
#endif
|
|||
return true; |
|||
} |
|||
} |
|||
#if PRV_DEBUG
|
|||
printf("uart_rx timeout\n"); |
|||
#endif
|
|||
|
|||
HAL_UART_Abort(huart); |
|||
HAL_UART_DMAStop(huart); |
|||
|
|||
return false; |
|||
} |
|||
|
|||
bool ModbusBlockHost::readReg03(uint8_t slaveAddr, uint16_t regAddr, uint16_t *regVal, int overtimems) { |
|||
zlock_guard lck(m_modbus_lock); |
|||
|
|||
txbuff[0] = slaveAddr; |
|||
txbuff[1] = 0x03; |
|||
txbuff[2] = regAddr >> 8; |
|||
txbuff[3] = regAddr & 0xff; |
|||
txbuff[4] = 0x00; |
|||
txbuff[5] = 0x01; |
|||
modbus_pack_crc_to_packet(txbuff, 6 + 2); |
|||
|
|||
cleanRxBuff(); |
|||
|
|||
uarttx(txbuff, 6 + 2); |
|||
|
|||
bool status; |
|||
status = uartrx(rxbuff, 5 + 2, overtimems); |
|||
|
|||
if (!status) { |
|||
return false; |
|||
} |
|||
|
|||
if (!modbus_checkcrc16(rxbuff, 7)) { |
|||
ZLOGE("ModbusBlockHost", "crc error"); |
|||
return false; |
|||
} |
|||
|
|||
*regVal = (((uint16_t)(rxbuff[3])) << 8) | rxbuff[4]; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
// static const char *hex2str(uint8_t *buff, size_t len) {
|
|||
// static char str[100];
|
|||
// for (size_t i = 0; i < len; i++) {
|
|||
// sprintf(str + i * 2, "%02x", buff[i]);
|
|||
// }
|
|||
// return str;
|
|||
// }
|
|||
|
|||
bool ModbusBlockHost::readReg03Muti(uint8_t slaveAddr, uint16_t regAddr, uint16_t *regVal, int regNum, int overtimems) { |
|||
zlock_guard lck(m_modbus_lock); |
|||
|
|||
txbuff[0] = slaveAddr; |
|||
txbuff[1] = 0x03; |
|||
txbuff[2] = regAddr >> 8; |
|||
txbuff[3] = regAddr & 0xff; |
|||
txbuff[4] = 0x00; |
|||
txbuff[5] = regNum; |
|||
modbus_pack_crc_to_packet(txbuff, 6 + 2); |
|||
|
|||
cleanRxBuff(); |
|||
|
|||
uarttx(txbuff, 6 + 2); |
|||
|
|||
bool status; |
|||
// 14*2 = 28
|
|||
status = uartrx(rxbuff, 5 + regNum * 2, overtimems); |
|||
if (!status) { |
|||
return false; |
|||
} |
|||
|
|||
if (!modbus_checkcrc16(rxbuff, 5 + regNum * 2)) { |
|||
ZLOGE("ModbusBlockHost", "crc error"); |
|||
return false; |
|||
} |
|||
for (int i = 0; i < regNum; i++) { |
|||
regVal[i] = ((uint16_t)(rxbuff[3 + i * 2]) << 8) | rxbuff[4 + i * 2]; |
|||
// int16_t val = regVal[i] ;
|
|||
// ZLOGI("RX", "%d", val);
|
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
bool ModbusBlockHost::writeReg06(uint8_t slaveAddr, uint16_t regAddr, uint16_t regVal, int overtimems) { |
|||
zlock_guard lck(m_modbus_lock); |
|||
|
|||
txbuff[0] = slaveAddr; |
|||
txbuff[1] = 0x06; |
|||
txbuff[2] = regAddr >> 8; |
|||
txbuff[3] = regAddr & 0xff; |
|||
txbuff[4] = regVal >> 8; |
|||
txbuff[5] = regVal & 0xff; |
|||
modbus_pack_crc_to_packet(txbuff, 6 + 2); |
|||
|
|||
cleanRxBuff(); |
|||
|
|||
uarttx(txbuff, 6 + 2); |
|||
|
|||
bool status; |
|||
status = uartrx(rxbuff, 8, overtimems); |
|||
|
|||
if (status && modbus_checkcrc16(rxbuff, 8)) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
bool ModbusBlockHost::writeReg10(uint8_t slaveAddr, uint16_t regAddr, uint16_t regVal, int overtimems) { |
|||
zlock_guard lck(m_modbus_lock); |
|||
|
|||
txbuff[0] = slaveAddr; |
|||
txbuff[1] = 0x10; |
|||
txbuff[2] = regAddr >> 8; |
|||
txbuff[3] = regAddr & 0xff; |
|||
txbuff[4] = 0x00; |
|||
txbuff[5] = 0x01; |
|||
txbuff[6] = 0x02; // 字节数
|
|||
txbuff[7] = regVal >> 8; |
|||
txbuff[8] = regVal & 0xff; |
|||
modbus_pack_crc_to_packet(txbuff, 9 + 2); |
|||
|
|||
cleanRxBuff(); |
|||
|
|||
uarttx(txbuff, 9 + 2); |
|||
|
|||
bool status; |
|||
status = uartrx(rxbuff, 8, overtimems); |
|||
|
|||
if (status && modbus_checkcrc16(rxbuff, 8)) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
@ -1,31 +0,0 @@ |
|||
#pragma once
|
|||
//
|
|||
#include "stm32basic/zbasic.h"
|
|||
#include "../mutex.hpp"
|
|||
|
|||
namespace iflytop { |
|||
class ModbusBlockHost { |
|||
UART_HandleTypeDef *huart; |
|||
|
|||
uint8_t txbuff[100]; |
|||
uint8_t rxbuff[100]; |
|||
|
|||
zmutex m_modbus_lock; |
|||
|
|||
public: |
|||
ModbusBlockHost(); |
|||
~ModbusBlockHost(); |
|||
|
|||
void initialize(UART_HandleTypeDef *huart); |
|||
|
|||
bool readReg03(uint8_t slaveAddr, uint16_t regAddr, uint16_t *regVal, int overtimems); |
|||
bool readReg03Muti(uint8_t slaveAddr, uint16_t regAddr, uint16_t *regVal, int regNum, int overtimems); |
|||
bool writeReg06(uint8_t slaveAddr, uint16_t regAddr, uint16_t regVal, int overtimems); |
|||
bool writeReg10(uint8_t slaveAddr, uint16_t regAddr, uint16_t regVal, int overtimems); |
|||
|
|||
private: |
|||
void cleanRxBuff(); |
|||
void uarttx(uint8_t *buff, size_t len); |
|||
bool uartrx(uint8_t *buff, size_t len, int overtimems); |
|||
}; |
|||
} // namespace iflytop
|
@ -1,107 +0,0 @@ |
|||
#include "preportional_valve_ctrl.hpp"
|
|||
|
|||
#include "transmit_disfection_protocol/transmit_disfection_protocol.hpp"
|
|||
using namespace iflytop; |
|||
using namespace zscanprotocol; |
|||
|
|||
#define WORK_STATE_REG 0x0000
|
|||
#define CTRL_STATE_REG 0x0001
|
|||
#define POS_STATE_REG 0x0013
|
|||
#define OVERTIME 30
|
|||
#define TAG "PreportionalValveCtrl"
|
|||
|
|||
void PreportionalValveCtrl::initialize(UART_HandleTypeDef* huart) { m_modbusBlockHost.initialize(huart); } |
|||
|
|||
int32_t PreportionalValveCtrl::writeReg06(uint8_t slaveAddr, uint16_t regAddr, uint16_t regVal) { |
|||
// 重发三次
|
|||
for (size_t i = 0; i < 3; i++) { |
|||
int32_t err = m_modbusBlockHost.writeReg06(slaveAddr, regAddr, regVal, OVERTIME); |
|||
if (err == 0) return 0; |
|||
} |
|||
return err::kerr_subdevice_offline; |
|||
} |
|||
int32_t PreportionalValveCtrl::readReg03(uint8_t slaveAddr, uint16_t regAddr, uint16_t* regVal) { |
|||
// 重发三次
|
|||
for (size_t i = 0; i < 3; i++) { |
|||
int32_t err = m_modbusBlockHost.readReg03(slaveAddr, regAddr, regVal, OVERTIME); |
|||
if (err == 0) return 0; |
|||
} |
|||
return err::kerr_subdevice_offline; |
|||
} |
|||
|
|||
int32_t PreportionalValveCtrl::setValvePos(int32_t valueid, int32_t pos) { //
|
|||
int32_t ret = 0; |
|||
if (valueid > 255 || valueid < 1) { |
|||
return err::kerr_invalid_param; |
|||
} |
|||
ret = writeReg06(valueid, CTRL_STATE_REG, pos); |
|||
if (!ret) return err::kerr_subdevice_offline; |
|||
|
|||
m_last_set_valve_ticket = HAL_GetTick(); |
|||
m_targetpos[valueid] = pos; |
|||
return 0; |
|||
} |
|||
|
|||
int32_t PreportionalValveCtrl::getValvePos(int32_t valueid, int32_t* pos) { |
|||
int32_t ret = 0; |
|||
if (valueid > 255 || valueid < 1) { |
|||
return err::kerr_invalid_param; |
|||
} |
|||
|
|||
uint16_t pos16 = 0; |
|||
ret = readReg03(valueid, POS_STATE_REG, &pos16); |
|||
if (!ret) return err::kerr_subdevice_offline; |
|||
|
|||
*pos = pos16; |
|||
return 0; |
|||
} |
|||
int32_t PreportionalValveCtrl::getValveOrderPos(int32_t valueid, int32_t* pos) { |
|||
int32_t ret = 0; |
|||
if (valueid > 255 || valueid < 1) { |
|||
return err::kerr_invalid_param; |
|||
} |
|||
|
|||
uint16_t pos16 = 0; |
|||
ret = readReg03(valueid, CTRL_STATE_REG, &pos16); |
|||
if (!ret) return err::kerr_subdevice_offline; |
|||
|
|||
*pos = pos16; |
|||
return 0; |
|||
} |
|||
|
|||
int32_t PreportionalValveCtrl::isBusy(int32_t valueid, int32_t* busy) { |
|||
#if 1
|
|||
int32_t orderpos = 0; |
|||
int32_t pos = 0; |
|||
int32_t err = 0; |
|||
|
|||
#if 0
|
|||
err = getValveOrderPos(valueid, &orderpos); |
|||
if (err != 0) return err; |
|||
#endif
|
|||
orderpos = m_targetpos[valueid]; |
|||
|
|||
err = getValvePos(valueid, &pos); |
|||
if (err != 0) return err; |
|||
|
|||
if (abs(m_targetpos[valueid] - pos) <= 11) { |
|||
*busy = 0; |
|||
} else { |
|||
*busy = 1; |
|||
} |
|||
return 0; |
|||
#endif
|
|||
} |
|||
|
|||
int32_t PreportionalValveCtrl::getValveWorkState(int32_t valueid, int32_t* state) { |
|||
int32_t ret = 0; |
|||
if (valueid > 255 || valueid < 1) { |
|||
return err::kerr_invalid_param; |
|||
} |
|||
|
|||
uint16_t state16 = 0; |
|||
ret = readReg03(valueid, WORK_STATE_REG, &state16); |
|||
if (!ret) return err::kerr_subdevice_offline; |
|||
*state = state16; |
|||
return 0; |
|||
} |
@ -1,49 +0,0 @@ |
|||
#pragma once
|
|||
#include <stddef.h>
|
|||
#include <stdio.h>
|
|||
|
|||
#include "base/config_service.hpp"
|
|||
#include "stm32basic/modbus/modbus_block_host.hpp"
|
|||
#include "stm32basic/zsdk.hpp"
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* https://iflytop1.feishu.cn/wiki/GQwCwHMqFiaJRwks80ncwaYKnSe
|
|||
*/ |
|||
|
|||
namespace iflytop { |
|||
using namespace std; |
|||
class PreportionalValveCtrl { |
|||
public: |
|||
typedef enum { |
|||
kstate_stop = 0x0, |
|||
kstate_running_forward = 0xaa, |
|||
kstate_running_backward = 0xbb, |
|||
kstate_err_state = 0xea, |
|||
} work_state_t; |
|||
|
|||
private: |
|||
/* data */ |
|||
ModbusBlockHost m_modbusBlockHost; |
|||
int32_t val = 0; |
|||
uint32_t m_last_set_valve_ticket = 0; |
|||
uint16_t m_targetpos[255]; |
|||
|
|||
public: |
|||
PreportionalValveCtrl() {}; |
|||
~PreportionalValveCtrl() {}; |
|||
|
|||
void initialize(UART_HandleTypeDef* huart); |
|||
int32_t setValvePos(int32_t valueid, int32_t pos); |
|||
int32_t getValvePos(int32_t valueid, int32_t* pos); |
|||
int32_t getValveOrderPos(int32_t valueid, int32_t* pos); |
|||
int32_t isBusy(int32_t valueid, int32_t* busy); |
|||
int32_t getValveWorkState(int32_t valueid, int32_t* state); |
|||
|
|||
private: |
|||
|
|||
int32_t writeReg06(uint8_t slaveAddr, uint16_t regAddr, uint16_t regVal); |
|||
int32_t readReg03(uint8_t slaveAddr, uint16_t regAddr, uint16_t* regVal); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -1,244 +0,0 @@ |
|||
#include "pxx_pressure_sensor_bus.hpp"
|
|||
|
|||
#include "stm32basic/modbus/modbus_block_host.hpp"
|
|||
|
|||
using namespace iflytop; |
|||
|
|||
#define TAG "PxxSensor"
|
|||
|
|||
/**
|
|||
* @brief |
|||
* |
|||
* |
|||
* p100_protocol |
|||
* 0x0000:从机地址位 |
|||
* p600_protocol |
|||
* 0x0018H:从机地址位 |
|||
* |
|||
* |
|||
* |
|||
* 程序编写指标参考: |
|||
* 响应频率 : 模拟信号输出≤500Hz、数字信号输出≤5Hz |
|||
* 指令回执响应时间 : 20ms |
|||
* |
|||
* 推荐指令间隔: |
|||
* 指令间隔至少30ms |
|||
*/ |
|||
|
|||
#define OVERTIME_MS 50
|
|||
|
|||
static const char* protocolType2Str(PXXPressureSensorBus::protocol_type_t type) { |
|||
switch (type) { |
|||
case PXXPressureSensorBus::kp100_protocol: |
|||
return "P100"; |
|||
case PXXPressureSensorBus::kdp600_protocol: |
|||
return "DP600"; |
|||
case PXXPressureSensorBus::kothers_protocol: |
|||
return "OTHERS"; |
|||
default: |
|||
return "UNKNOWN"; |
|||
} |
|||
} |
|||
|
|||
static const char* p100uint2Str(uint8_t uint) { |
|||
switch (uint) { |
|||
case 0: |
|||
return "Mpa"; |
|||
case 1: |
|||
return "kpa"; |
|||
case 2: |
|||
return "pa"; |
|||
case 3: |
|||
return "bar"; |
|||
case 4: |
|||
return "Mbar"; |
|||
case 5: |
|||
return "kgcm2"; |
|||
case 6: |
|||
return "psi"; |
|||
case 7: |
|||
return "mh2o"; |
|||
case 8: |
|||
return "mh2o"; |
|||
default: |
|||
return "UNKNOWN"; |
|||
} |
|||
} |
|||
|
|||
/***********************************************************************************************************************
|
|||
* GLOBAL * |
|||
***********************************************************************************************************************/ |
|||
|
|||
static osThreadId PxxPressureSensorThread; |
|||
static void onPxxPressureSensorThreadStart(void const* argument) { ((PXXPressureSensorBus*)argument)->threadFuncStart(); } |
|||
|
|||
/***********************************************************************************************************************
|
|||
* CLASS * |
|||
***********************************************************************************************************************/ |
|||
|
|||
bool PXXPressureSensorBus::pingDevice(int id) { |
|||
uint16_t add = 0; |
|||
bool suc = m_modbusBlockHost->readReg03(id, 0x0000, &add, OVERTIME_MS); |
|||
return suc; |
|||
} |
|||
|
|||
bool PXXPressureSensorBus::tryProbeProtocolP100(int id, sensor_t* sensor) { |
|||
uint16_t add = 0; |
|||
bool suc = m_modbusBlockHost->readReg03(id, 0x0000, &add, OVERTIME_MS); |
|||
if (!suc) { |
|||
return false; |
|||
} |
|||
if (id != add) { |
|||
return false; |
|||
} |
|||
osDelay(10); |
|||
int16_t val[6] = {0}; |
|||
|
|||
suc = m_modbusBlockHost->readReg03Muti(id, 0x02, (uint16_t*)val, 5, 50); |
|||
if (!suc) { |
|||
return false; |
|||
} |
|||
sensor->p100_sensor_info.precision = val[1]; |
|||
sensor->p100_sensor_info.pressure_unit = val[0]; |
|||
sensor->p100_sensor_info.value = val[2]; |
|||
sensor->p100_sensor_info.zero_point = val[3]; |
|||
sensor->p100_sensor_info.range_full_point = val[4]; |
|||
|
|||
sensor->id = id; |
|||
sensor->type = kp100_protocol; |
|||
sensor->detected = true; |
|||
|
|||
return true; |
|||
} |
|||
bool PXXPressureSensorBus::tryProbeProtocolDP600(int id, sensor_t* sensor) { |
|||
uint16_t add = 0; |
|||
bool suc = m_modbusBlockHost->readReg03(id, 0x0018, &add, OVERTIME_MS); |
|||
// ZLOGI(TAG, "tryProbeProtocolDP600 id:%d add:%d suc:%d", id, add, suc);
|
|||
if (!suc) { |
|||
return false; |
|||
} |
|||
if (id != add) { |
|||
return false; |
|||
} |
|||
|
|||
sensor->id = id; |
|||
sensor->type = kdp600_protocol; |
|||
sensor->detected = true; |
|||
return true; |
|||
} |
|||
|
|||
void PXXPressureSensorBus::probeSensor() { |
|||
memset(sensors, 0, sizeof(sensors)); |
|||
for (size_t i = 1; i < ZARRAY_SIZE(sensors); i++) { |
|||
osDelay(30); |
|||
bool pingSuc = false; |
|||
pingSuc = pingDevice(i); |
|||
ZLOGI(TAG, "pingDevice id:%d,%s", i, pingSuc ? "online" : "offline"); |
|||
if (pingSuc) { |
|||
sensorNum++; |
|||
if (tryProbeProtocolP100(i, &sensors[i])) continue; |
|||
osDelay(30); |
|||
if (tryProbeProtocolDP600(i, &sensors[i])) continue; |
|||
|
|||
sensors[i].id = i; |
|||
sensors[i].type = kothers_protocol; |
|||
sensors[i].detected = true; |
|||
} else { |
|||
} |
|||
} |
|||
|
|||
/**
|
|||
* @brief DUMP Sensor State |
|||
*/ |
|||
ZLOGI(TAG, "detect pressure sensor list:(%d)", sensorNum); |
|||
for (size_t i = 0; i < ZARRAY_SIZE(sensors); i++) { |
|||
if (sensors[i].detected) { |
|||
if (sensors[i].type == kp100_protocol) { |
|||
ZLOGI(TAG, " Sensor[%d] id:%d ptype:%s precision:%d unit:%s zero:%d full:%d", i, sensors[i].id, //
|
|||
protocolType2Str(sensors[i].type), //
|
|||
sensors[i].p100_sensor_info.precision, //
|
|||
p100uint2Str(sensors[i].p100_sensor_info.pressure_unit), //
|
|||
sensors[i].p100_sensor_info.zero_point, //
|
|||
sensors[i].p100_sensor_info.range_full_point); |
|||
} else { |
|||
ZLOGI(TAG, " Sensor[%d] id:%d ptype:%s detected:%d", i, sensors[i].id, protocolType2Str(sensors[i].type), sensors[i].detected); |
|||
} |
|||
} |
|||
} |
|||
ZLOGI(TAG, "end"); |
|||
initedEnd = true; |
|||
} |
|||
|
|||
void PXXPressureSensorBus::threadFuncStart() { |
|||
/**
|
|||
* @brief 枚举传感器设备 |
|||
*/ |
|||
probeSensor(); |
|||
/**
|
|||
* @brief 周期采集传感器数据 |
|||
*/ |
|||
while (true) { |
|||
//
|
|||
for (size_t i = 0; i < ZARRAY_SIZE(sensors); i++) { |
|||
if (!sensors[i].detected) { |
|||
continue; |
|||
} |
|||
|
|||
bool suc = false; |
|||
|
|||
if (sensors[i].type == kp100_protocol) { |
|||
int16_t val = 0; |
|||
suc = m_modbusBlockHost->readReg03(i, 0x0004, (uint16_t*)&val, OVERTIME_MS); |
|||
{ |
|||
zlock_guard l(m_lock); |
|||
if (suc) sensors[i].val = val; |
|||
sensors[i].online = suc; |
|||
} |
|||
} else if (sensors[i].type == kdp600_protocol) { |
|||
int16_t val = 0; |
|||
suc = m_modbusBlockHost->readReg03(i, 0x0000, (uint16_t*)&val, OVERTIME_MS); |
|||
|
|||
{ |
|||
zlock_guard l(m_lock); |
|||
if (suc) sensors[i].val = val; |
|||
sensors[i].online = suc; |
|||
} |
|||
} else { |
|||
{ |
|||
zlock_guard l(m_lock); |
|||
sensors[i].online = false; |
|||
} |
|||
continue; |
|||
} |
|||
osDelay(50); |
|||
} |
|||
osDelay(50); |
|||
} |
|||
} |
|||
|
|||
void PXXPressureSensorBus::init(UART_HandleTypeDef* huart) { |
|||
//
|
|||
m_lock.init(); |
|||
|
|||
m_modbusBlockHost = new ModbusBlockHost(); //
|
|||
m_modbusBlockHost->initialize(huart); |
|||
|
|||
osThreadDef(PxxPressureSensorThread, onPxxPressureSensorThreadStart, osPriorityNormal, 0, 1024); |
|||
PxxPressureSensorThread = osThreadCreate(osThread(PxxPressureSensorThread), this); |
|||
|
|||
while (!initedEnd) { |
|||
osDelay(10); |
|||
} |
|||
} |
|||
bool PXXPressureSensorBus::readData(int32_t id, int16_t* data) { |
|||
zlock_guard l(m_lock); |
|||
if (id < 0 || id >= ZARRAY_SIZE(sensors)) { |
|||
return false; |
|||
} |
|||
if (!sensors[id].online) { |
|||
return false; |
|||
} |
|||
*data = sensors[id].val; |
|||
return true; |
|||
} |
|||
void PXXPressureSensorBus::probe() {} |
@ -1,75 +0,0 @@ |
|||
#pragma once
|
|||
#include <stddef.h>
|
|||
#include <stdio.h>
|
|||
|
|||
#include "base/config_service.hpp"
|
|||
#include "stm32basic/modbus/modbus_block_host.hpp"
|
|||
#include "stm32basic/zsdk.hpp"
|
|||
|
|||
namespace iflytop { |
|||
|
|||
#define PXX_PRESSURE_SENSOR_NUM 10
|
|||
|
|||
class PXXPressureSensorBus { |
|||
public: |
|||
/***********************************************************************************************************************
|
|||
* STRUCT * |
|||
***********************************************************************************************************************/ |
|||
|
|||
typedef enum { |
|||
kp100_protocol, |
|||
kdp600_protocol, |
|||
kothers_protocol, |
|||
} protocol_type_t; |
|||
|
|||
typedef struct { |
|||
uint8_t precision; // 0,1,2,3
|
|||
uint8_t pressure_unit; // 0:map,1:kpa,2:pa
|
|||
int16_t value; |
|||
int16_t zero_point; |
|||
int16_t range_full_point; |
|||
} p100_sensor_info_t; |
|||
|
|||
typedef struct { |
|||
uint16_t id; |
|||
protocol_type_t type; |
|||
bool detected; |
|||
bool online; |
|||
p100_sensor_info_t p100_sensor_info; |
|||
|
|||
int32_t val; |
|||
} sensor_t; |
|||
|
|||
private: |
|||
/***********************************************************************************************************************
|
|||
* DATA * |
|||
***********************************************************************************************************************/ |
|||
|
|||
ModbusBlockHost* m_modbusBlockHost; |
|||
bool initedEnd = false; |
|||
zmutex m_lock; |
|||
|
|||
public: |
|||
sensor_t sensors[PXX_PRESSURE_SENSOR_NUM] = {0}; |
|||
int32_t sensorNum = 0; |
|||
|
|||
public: |
|||
/***********************************************************************************************************************
|
|||
* FUNC * |
|||
***********************************************************************************************************************/ |
|||
void init(UART_HandleTypeDef *huart); |
|||
bool readData(int32_t id, int16_t* data); |
|||
|
|||
private: |
|||
void probe(); |
|||
|
|||
public: |
|||
void threadFuncStart(); |
|||
|
|||
bool pingDevice(int id); |
|||
bool tryProbeProtocolP100(int id, sensor_t* sensor); |
|||
bool tryProbeProtocolDP600(int id, sensor_t* sensor); |
|||
void probeSensor(); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -0,0 +1,6 @@ |
|||
#pragma once
|
|||
#include "zbasic.h"
|
|||
#include "mutex.hpp"
|
|||
#include "zadc.hpp"
|
|||
#include "zspi.hpp"
|
|||
#include "zgpio.hpp"
|
@ -1,153 +0,0 @@ |
|||
#include "sys_mgr.hpp"
|
|||
|
|||
#include <stdlib.h>
|
|||
|
|||
#include "zbasic.h"
|
|||
using namespace iflytop; |
|||
|
|||
#define TAG "SysMgr"
|
|||
|
|||
extern "C" { |
|||
|
|||
/***********************************************************************************************************************
|
|||
* STM32_CODE_ERROR * |
|||
***********************************************************************************************************************/ |
|||
void SysMgr_on_Error_Handler() { |
|||
ZLOGE(TAG, "Error_Handler\n"); |
|||
while (1) { |
|||
} |
|||
} |
|||
|
|||
void SysMgr_on_assert_failed(uint8_t* file, uint32_t line) { |
|||
ZLOGE(TAG, "ASSERT: %s [%s:%d]\n", file, line); |
|||
while (1) { |
|||
} |
|||
} |
|||
extern uint8_t _end; /* Symbol defined in the linker script */ |
|||
extern uint8_t _estack; /* Symbol defined in the linker script */ |
|||
extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ |
|||
extern uint8_t* __sbrk_heap_end; |
|||
|
|||
static size_t get_free_heap_size() { |
|||
const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; |
|||
const uint8_t* max_heap = (uint8_t*)stack_limit; |
|||
uint8_t* prev_heap_end; |
|||
return max_heap - __sbrk_heap_end; |
|||
// if (__sbrk_heap_end + incr > max_heap) {
|
|||
// errno = ENOMEM;
|
|||
// return (void*)-1;
|
|||
// }
|
|||
} |
|||
|
|||
/***********************************************************************************************************************
|
|||
* STM32_ERROR_IRQ * |
|||
***********************************************************************************************************************/ |
|||
void SysMgr_on_NMI_Handler(void) { ZLOGI(TAG, "on NMI_Handler"); } |
|||
void SysMgr_on_HardFault_Handler(void) { ZLOGI(TAG, "on HardFault_Handler"); } |
|||
void SysMgr_on_MemManage_Handler(void) { ZLOGI(TAG, "on MemManage_Handler"); } |
|||
void SysMgr_on_BusFault_Handler(void) { ZLOGI(TAG, "on BusFault_Handler"); } |
|||
void SysMgr_on_UsageFault_Handler(void) { ZLOGI(TAG, "on UsageFault_Handler"); } |
|||
|
|||
/***********************************************************************************************************************
|
|||
* FREERTOS_ERROR * |
|||
***********************************************************************************************************************/ |
|||
void vApplicationStackOverflowHook(xTaskHandle xTask, signed char* pcTaskName) { |
|||
ZLOGE(TAG, "StackOverflowHook: %s\n", pcTaskName); |
|||
__disable_irq(); |
|||
while (1) { |
|||
} |
|||
} |
|||
void vApplicationMallocFailedHook(void) { |
|||
ZLOGE(TAG, "MallocFailedHook\n"); |
|||
__disable_irq(); |
|||
|
|||
while (1) { |
|||
} |
|||
} |
|||
} |
|||
SysMgr* SysMgr::ins() { |
|||
static SysMgr s_ins; |
|||
return &s_ins; |
|||
} |
|||
// void SysMgr::regTaskId(osThreadId id) {
|
|||
// m_task[m_ntask].Id = id;
|
|||
// m_ntask++;
|
|||
// }
|
|||
size_t SysMgr::osGetSysRunTime() { return HAL_GetTick(); } |
|||
UBaseType_t uxTaskGetSystemState(TaskStatus_t* const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t* const pulTotalRunTime); |
|||
|
|||
void SysMgr::initedFinished() { //
|
|||
static TaskStatus_t pxTaskStatusArray[SDK_MAX_TASK + 1]; |
|||
UBaseType_t uxArraySize = SDK_MAX_TASK + 1; |
|||
uint32_t pulTotalRunTime; |
|||
m_ntask = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, &pulTotalRunTime); |
|||
for (int i = 0; i < m_ntask; i++) { |
|||
m_task[i].Id = pxTaskStatusArray[i].xHandle; |
|||
} |
|||
ZASSERT_INFO(m_ntask < SDK_MAX_TASK, "task num is too large, please increase SDK_MAX_TASK"); |
|||
} |
|||
|
|||
size_t SysMgr::osGetMinimumEverFreeHeapSize() { return ::xPortGetMinimumEverFreeHeapSize(); } |
|||
size_t SysMgr::osGetFreeHeapSize() { return ::xPortGetFreeHeapSize(); } |
|||
size_t SysMgr::osGetTotalHeapSize() { return configTOTAL_HEAP_SIZE; } |
|||
size_t SysMgr::osGetFreeSysHeapSize() { return get_free_heap_size(); } |
|||
|
|||
int32_t SysMgr::getTaskNum() { return m_ntask; } |
|||
|
|||
void SysMgr::dumpSysInfo() { |
|||
|
|||
|
|||
zlog("---------------Heap Info--------------\n"); |
|||
zlog("MinimumEverFreeHeapSize : %d\n", osGetMinimumEverFreeHeapSize()); |
|||
zlog("RTOS FreeHeapSize : %d\n", osGetFreeHeapSize()); |
|||
zlog("RTOS TotalHeapSize : %d\n", osGetTotalHeapSize()); |
|||
zlog("Sys FreeHeap : %d\n", get_free_heap_size()); |
|||
zlog(""); |
|||
|
|||
zlog("---------------Task Info--------------\n"); |
|||
static char buf[40 * SDK_MAX_TASK]; // 40一个任务,最多支持10个任务
|
|||
vTaskList(buf); |
|||
zlog("Name State Priority Stack Num\n"); |
|||
zlog_raw(buf); |
|||
zlog("- TaskInfoEnd -\n"); |
|||
} |
|||
|
|||
uint32_t SysMgr::osTaskStackRemainingSize(osThreadId id) { return uxTaskGetStackHighWaterMark(id); } |
|||
const char* SysMgr::osTaskName(osThreadId id) { return pcTaskGetName(id); } |
|||
|
|||
osThreadId SysMgr::osGetId(int offset) { |
|||
if (offset < m_ntask) { |
|||
return m_task[offset].Id; |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
void SysMgr::osTaskName(osThreadId id, char* name, int bufsize) { |
|||
strncpy(name, pcTaskGetName(id), bufsize); |
|||
name[bufsize - 1] = 0; |
|||
} |
|||
void SysMgr::osTaskStackRemainingSize(osThreadId id, uint16_t* remainsize) { *remainsize = uxTaskGetStackHighWaterMark(id); } |
|||
void SysMgr::osTaskPriority(osThreadId id, uint16_t* priority) { *priority = uxTaskPriorityGet(id); } |
|||
void SysMgr::osTaskGetState(osThreadId id, char* state) { |
|||
eTaskState task_state = eTaskGetState(id); |
|||
switch (task_state) { |
|||
case eRunning: |
|||
*state = 'X'; |
|||
break; |
|||
case eReady: |
|||
*state = 'R'; |
|||
break; |
|||
case eBlocked: |
|||
*state = 'B'; |
|||
break; |
|||
case eSuspended: |
|||
*state = 'S'; |
|||
break; |
|||
case eDeleted: |
|||
*state = 'D'; |
|||
break; |
|||
default: |
|||
*state = '?'; |
|||
break; |
|||
} |
|||
} |
@ -1,51 +0,0 @@ |
|||
#pragma once
|
|||
#include "cmsis_os.h"
|
|||
#include "zbasic.h"
|
|||
|
|||
namespace iflytop { |
|||
class ZTaskInfo { |
|||
public: |
|||
osThreadId Id; |
|||
}; |
|||
|
|||
class SysMgr { |
|||
private: |
|||
/* data */ |
|||
|
|||
public: |
|||
ZTaskInfo m_task[30] = {0}; |
|||
int m_ntask = 0; |
|||
|
|||
static SysMgr* ins(); |
|||
void initedFinished(); |
|||
|
|||
void dumpSysInfo(); |
|||
|
|||
size_t osGetSysRunTime(); |
|||
|
|||
/***********************************************************************************************************************
|
|||
* HeapMgr * |
|||
***********************************************************************************************************************/ |
|||
size_t osGetMinimumEverFreeHeapSize(); |
|||
size_t osGetFreeHeapSize(); |
|||
size_t osGetTotalHeapSize(); |
|||
size_t osGetFreeSysHeapSize(); |
|||
|
|||
/***********************************************************************************************************************
|
|||
* TaskInfo * |
|||
***********************************************************************************************************************/ |
|||
|
|||
osThreadId osGetId(int offset); |
|||
|
|||
uint32_t osTaskStackRemainingSize(osThreadId id); |
|||
const char* osTaskName(osThreadId id); |
|||
|
|||
void osTaskName(osThreadId id, char* name, int bufsize); |
|||
void osTaskStackRemainingSize(osThreadId id, uint16_t* remainsize); |
|||
void osTaskPriority(osThreadId id, uint16_t* priority); |
|||
void osTaskGetState(osThreadId id, char* state); |
|||
|
|||
int32_t getTaskNum(); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
@ -1,19 +0,0 @@ |
|||
#pragma once |
|||
typedef enum { |
|||
kmres_256 = 0x00, |
|||
kmres_128 = 0x01, |
|||
kmres_64 = 0x02, |
|||
kmres_32 = 0x03, |
|||
kmres_16 = 0x04, |
|||
kmres_8 = 0x05, |
|||
kmres_4 = 0x06, |
|||
kmres_2 = 0x07, |
|||
kmres_1 = 0x08, |
|||
} mres_type_t; |
|||
|
|||
typedef enum { |
|||
kTMC4361A = 0x2, |
|||
kTMC2160AndTMC5160 = 0x30, |
|||
kTMC5130 = 0x11, |
|||
// kTMC5160 = 0x30, |
|||
} tmcic_id_t; |
@ -1,67 +0,0 @@ |
|||
/* |
|||
* TMC5130_Constants.h |
|||
* |
|||
* Created on: 13.06.2018 |
|||
* Author: LK |
|||
*/ |
|||
|
|||
#ifndef TMC_IC_TMC5130_TMC5130_CONSTANTS_H_ |
|||
#define TMC_IC_TMC5130_TMC5130_CONSTANTS_H_ |
|||
|
|||
#define TMC5130_REGISTER_COUNT 128 |
|||
#define TMC5130_MOTORS 1 |
|||
#define TMC5130_WRITE_BIT 0x80 |
|||
#define TMC5130_ADDRESS_MASK 0x7F |
|||
#define TMC5130_MAX_VELOCITY 8388096 |
|||
#define TMC5130_MAX_ACCELERATION 65535 |
|||
|
|||
// ramp modes (Register TMC5161_RAMPMODE) |
|||
#define TMC5130_MODE_POSITION 0 |
|||
#define TMC5130_MODE_VELPOS 1 |
|||
#define TMC5130_MODE_VELNEG 2 |
|||
#define TMC5130_MODE_HOLD 3 |
|||
|
|||
// limit switch mode bits (Register TMC5130_SWMODE) |
|||
#define TMC5130_SW_STOPL_ENABLE 0x0001 |
|||
#define TMC5130_SW_STOPR_ENABLE 0x0002 |
|||
#define TMC5130_SW_STOPL_POLARITY 0x0004 |
|||
#define TMC5130_SW_STOPR_POLARITY 0x0008 |
|||
#define TMC5130_SW_SWAP_LR 0x0010 |
|||
#define TMC5130_SW_LATCH_L_ACT 0x0020 |
|||
#define TMC5130_SW_LATCH_L_INACT 0x0040 |
|||
#define TMC5130_SW_LATCH_R_ACT 0x0080 |
|||
#define TMC5130_SW_LATCH_R_INACT 0x0100 |
|||
#define TMC5130_SW_LATCH_ENC 0x0200 |
|||
#define TMC5130_SW_SG_STOP 0x0400 |
|||
#define TMC5130_SW_SOFTSTOP 0x0800 |
|||
|
|||
// Status bits (Register TMC5130_RAMPSTAT) |
|||
#define TMC5130_RS_STOPL 0x0001 |
|||
#define TMC5130_RS_STOPR 0x0002 |
|||
#define TMC5130_RS_LATCHL 0x0004 |
|||
#define TMC5130_RS_LATCHR 0x0008 |
|||
#define TMC5130_RS_EV_STOPL 0x0010 |
|||
#define TMC5130_RS_EV_STOPR 0x0020 |
|||
#define TMC5130_RS_EV_STOP_SG 0x0040 |
|||
#define TMC5130_RS_EV_POSREACHED 0x0080 |
|||
#define TMC5130_RS_VELREACHED 0x0100 |
|||
#define TMC5130_RS_POSREACHED 0x0200 |
|||
#define TMC5130_RS_VZERO 0x0400 |
|||
#define TMC5130_RS_ZEROWAIT 0x0800 |
|||
#define TMC5130_RS_SECONDMOVE 0x1000 |
|||
#define TMC5130_RS_SG 0x2000 |
|||
|
|||
// Encoderbits (Register TMC5130_ENCMODE) |
|||
#define TMC5130_EM_DECIMAL 0x0400 |
|||
#define TMC5130_EM_LATCH_XACT 0x0200 |
|||
#define TMC5130_EM_CLR_XENC 0x0100 |
|||
#define TMC5130_EM_NEG_EDGE 0x0080 |
|||
#define TMC5130_EM_POS_EDGE 0x0040 |
|||
#define TMC5130_EM_CLR_ONCE 0x0020 |
|||
#define TMC5130_EM_CLR_CONT 0x0010 |
|||
#define TMC5130_EM_IGNORE_AB 0x0008 |
|||
#define TMC5130_EM_POL_N 0x0004 |
|||
#define TMC5130_EM_POL_B 0x0002 |
|||
#define TMC5130_EM_POL_A 0x0001 |
|||
|
|||
#endif /* TMC_IC_TMC5130_TMC5130_CONSTANTS_H_ */ |
1475
tmcdriver/tmc51x0/reg/TMC5130_Fields.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,74 +0,0 @@ |
|||
/* |
|||
* TMC5130_Register.h |
|||
* |
|||
* Created on: 30.09.2016 |
|||
* Author: ed based on te |
|||
*/ |
|||
|
|||
#ifndef TMC5130_REGISTER_H |
|||
#define TMC5130_REGISTER_H |
|||
|
|||
// ===== TMC5130 register set ===== |
|||
|
|||
#define TMC5130_GCONF 0x00 |
|||
#define TMC5130_GSTAT 0x01 |
|||
#define TMC5130_IFCNT 0x02 |
|||
#define TMC5130_SLAVECONF 0x03 |
|||
#define TMC5130_IOIN 0x04 |
|||
#define TMC5130_X_COMPARE 0x05 |
|||
|
|||
#define TMC5130_IHOLD_IRUN 0x10 |
|||
#define TMC5130_TPOWERDOWN 0x11 |
|||
#define TMC5130_TSTEP 0x12 |
|||
#define TMC5130_TPWMTHRS 0x13 |
|||
#define TMC5130_TCOOLTHRS 0x14 |
|||
#define TMC5130_THIGH 0x15 |
|||
|
|||
#define TMC5130_RAMPMODE 0x20 |
|||
#define TMC5130_XACTUAL 0x21 |
|||
#define TMC5130_VACTUAL 0x22 |
|||
#define TMC5130_VSTART 0x23 |
|||
#define TMC5130_A1 0x24 |
|||
#define TMC5130_V1 0x25 |
|||
#define TMC5130_AMAX 0x26 |
|||
#define TMC5130_VMAX 0x27 |
|||
#define TMC5130_DMAX 0x28 |
|||
#define TMC5130_D1 0x2A |
|||
#define TMC5130_VSTOP 0x2B |
|||
#define TMC5130_TZEROWAIT 0x2C |
|||
#define TMC5130_XTARGET 0x2D |
|||
|
|||
#define TMC5130_VDCMIN 0x33 |
|||
#define TMC5130_SWMODE 0x34 |
|||
#define TMC5130_RAMPSTAT 0x35 |
|||
#define TMC5130_XLATCH 0x36 |
|||
|
|||
#define TMC5130_ENCMODE 0x38 |
|||
#define TMC5130_XENC 0x39 |
|||
#define TMC5130_ENC_CONST 0x3A |
|||
#define TMC5130_ENC_STATUS 0x3B |
|||
#define TMC5130_ENC_LATCH 0x3C |
|||
|
|||
#define TMC5130_MSLUT0 0x60 |
|||
#define TMC5130_MSLUT1 0x61 |
|||
#define TMC5130_MSLUT2 0x62 |
|||
#define TMC5130_MSLUT3 0x63 |
|||
#define TMC5130_MSLUT4 0x64 |
|||
#define TMC5130_MSLUT5 0x65 |
|||
#define TMC5130_MSLUT6 0x66 |
|||
#define TMC5130_MSLUT7 0x67 |
|||
#define TMC5130_MSLUTSEL 0x68 |
|||
#define TMC5130_MSLUTSTART 0x69 |
|||
#define TMC5130_MSCNT 0x6A |
|||
#define TMC5130_MSCURACT 0x6B |
|||
|
|||
#define TMC5130_CHOPCONF 0x6C |
|||
#define TMC5130_COOLCONF 0x6D |
|||
#define TMC5130_DCCTRL 0x6E |
|||
#define TMC5130_DRVSTATUS 0x6F |
|||
#define TMC5130_PWMCONF 0x70 |
|||
#define TMC5130_PWMSTATUS 0x71 |
|||
#define TMC5130_ENCM_CTRL 0x72 |
|||
#define TMC5130_LOST_STEPS 0x73 |
|||
|
|||
#endif /* TMC5130_REGISTER_H */ |
@ -1,59 +0,0 @@ |
|||
#pragma once |
|||
#include <stdint.h> |
|||
|
|||
#include "TMC5130_Constants.h" |
|||
#include "TMC5130_Fields.h" |
|||
#include "TMC5130_Register.h" |
|||
namespace iflytop { |
|||
class TMC5130RampStat { |
|||
public: |
|||
uint32_t m_state; |
|||
typedef enum { |
|||
/** |
|||
* @brief |
|||
* R :只读 |
|||
* R+C:只读,但读后会自动清零 |
|||
*/ |
|||
ktmc5130_rs_stopl = TMC5130_RS_STOPL, // (R ) |
|||
ktmc5130_rs_stopr = TMC5130_RS_STOPR, // (R ) |
|||
ktmc5130_rs_latchl = TMC5130_RS_LATCHL, // (R+C) |
|||
ktmc5130_rs_latchr = TMC5130_RS_LATCHR, // (R+C) |
|||
ktmc5130_rs_ev_stopl = TMC5130_RS_EV_STOPL, // (R ) |
|||
ktmc5130_rs_ev_stopr = TMC5130_RS_EV_STOPR, // (R ) |
|||
ktmc5130_rs_ev_stop_sg = TMC5130_RS_EV_STOP_SG, // (R+C) |
|||
ktmc5130_rs_ev_posreached = TMC5130_RS_EV_POSREACHED, // (R+C) |
|||
ktmc5130_rs_velreached = TMC5130_RS_VELREACHED, // (R ) |
|||
ktmc5130_rs_posreached = TMC5130_RS_POSREACHED, // (R ) 是否到达目标位置 |
|||
ktmc5130_rs_vzero = TMC5130_RS_VZERO, // (R ) |
|||
ktmc5130_rs_zerowait = TMC5130_RS_ZEROWAIT, // (R ) |
|||
ktmc5130_rs_secondmove = TMC5130_RS_SECONDMOVE, // (R+C) |
|||
ktmc5130_rs_sg = TMC5130_RS_SG, // (R ) |
|||
} ramp_stat_bit_t; |
|||
|
|||
TMC5130RampStat(uint32_t state) : m_state(state) {} |
|||
bool isSetted(ramp_stat_bit_t bit) { return (m_state & bit) != 0; } |
|||
}; |
|||
|
|||
typedef struct { |
|||
uint32_t sg_result : 10; |
|||
uint32_t reserved0 : 5; |
|||
uint32_t fsactive : 1; |
|||
uint32_t cs_actual : 5; |
|||
uint32_t reserved1 : 3; |
|||
uint32_t stallguard : 1; |
|||
uint32_t ot : 1; // overtemperature flag |
|||
uint32_t otpw : 1; // overtemperature pre warning flag |
|||
uint32_t s2ga : 1; // short to ground indicator phase A |
|||
uint32_t s2gb : 1; // short to ground indicator phase B |
|||
uint32_t ola : 1; // open load indicator phase A |
|||
uint32_t olb : 1; // open load indicator phase B |
|||
uint32_t stst : 1; // standstill indicator |
|||
} TMC5130DevStatusReg_t; |
|||
|
|||
typedef struct { |
|||
uint32_t reset : 1; // 复位标识 |
|||
uint32_t drv_err : 1; // |
|||
uint32_t uv_cp : 1; |
|||
} TMC5130GState_t; |
|||
|
|||
} // namespace iflytop |
@ -1,439 +0,0 @@ |
|||
#include "tmc51x0.hpp"
|
|||
|
|||
#include "reg/TMC5130_Constants.h"
|
|||
#include "reg/TMC5130_Fields.h"
|
|||
#include "reg/TMC5130_Register.h"
|
|||
//
|
|||
#include "stm32basic/mutex.hpp"
|
|||
#include "stm32basic/zspi.hpp"
|
|||
|
|||
using namespace iflytop; |
|||
|
|||
#if 0
|
|||
// Register access permissions:
|
|||
// 0x00: none (reserved)
|
|||
// 0x01: read
|
|||
// 0x02: write
|
|||
// 0x03: read/write
|
|||
// 0x13: read/write, separate functions/values for reading or writing
|
|||
// 0x21: read, flag register (read to clear)
|
|||
// 0x42: write, has hardware presets on reset
|
|||
static const uint8_t tmc5130_defaultRegisterAccess[TMC5130_REGISTER_COUNT] = { |
|||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|||
0x03, 0x21, 0x01, 0x02, 0x13, 0x02, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x00 - 0x0F
|
|||
0x02, 0x02, 0x01, 0x02, 0x02, 0x02, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x10 - 0x1F
|
|||
0x03, 0x03, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, ____, 0x02, 0x02, 0x02, 0x03, ____, ____, // 0x20 - 0x2F
|
|||
____, ____, ____, 0x02, 0x03, 0x21, 0x01, ____, 0x03, 0x03, 0x02, 0x21, 0x01, ____, ____, ____, // 0x30 - 0x3F
|
|||
____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x40 - 0x4F
|
|||
____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, // 0x50 - 0x5F
|
|||
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x01, 0x01, 0x03, 0x02, 0x02, 0x01, // 0x60 - 0x6F
|
|||
0x42, 0x01, 0x02, 0x01, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____, ____ // 0x70 - 0x7F
|
|||
}; |
|||
#endif
|
|||
|
|||
/***********************************************************************************************************************
|
|||
* 工具宏 * |
|||
***********************************************************************************************************************/ |
|||
|
|||
#define FIELD_SET(data, mask, shift, value) (data = (((data) & (~(mask))) | (((value) << (shift)) & (mask))))
|
|||
#define FIELD_GET(data, mask, shift) (((data) & (mask)) >> (shift))
|
|||
#define BYTE(value, n) (((value) >> ((n) << 3)) & 0xFF)
|
|||
#define NIBBLE(value, n) (((value) >> ((n) << 2)) & 0x0F)
|
|||
#define SHORT(value, n) (((value) >> ((n) << 4)) & 0xFFFF)
|
|||
#define WORD(value, n) (((value) >> ((n) << 5)) & 0xFFFFFFFF)
|
|||
|
|||
#define TMC51x0_ADDRESS(x) ((x) & (TMC5130_ADDRESS_MASK))
|
|||
#define TAG "TMC51X0"
|
|||
void TMC51X0::initialize(TMC51X0Cfg cfg) { |
|||
m_cfg = cfg; |
|||
m_hspi = cfg.hspi; |
|||
|
|||
ZLOGI(TAG, "SPI:%p CSPin:%s,enPIn:%s", cfg.hspi, pinname(cfg.csnpin), pinname(cfg.ennpin)); |
|||
m_mutex.init(); |
|||
|
|||
m_csnpin.initAsOutput(m_cfg.csnpin, kxs_gpio_nopull, false, true); |
|||
m_ennpin.initAsOutput(m_cfg.ennpin, kxs_gpio_nopull, false, true); |
|||
|
|||
enable(false); |
|||
|
|||
stop(); |
|||
|
|||
writeInt(TMC5130_PWMCONF, 0x000500C8); |
|||
writeInt(TMC5130_CHOPCONF, 0x000100c3); |
|||
writeInt(TMC5130_IHOLD_IRUN, 0x00051A00); |
|||
writeInt(TMC5130_PWMCONF, 0x000401c8); |
|||
writeInt(TMC5130_XTARGET, 0); |
|||
writeInt(TMC5130_XACTUAL, 0x00000000); |
|||
writeInt(TMC5130_VACTUAL, 0x00000000); |
|||
writeInt(TMC5130_TZEROWAIT, 0); |
|||
|
|||
setVstart(100); |
|||
setA1(30); |
|||
setAmax(50); |
|||
setV1(500); |
|||
setDmax(50); |
|||
setD1(30); |
|||
setVstop(100); |
|||
setTzerowait(100); |
|||
|
|||
setIHOLD_IRUN(0, 30, 100); |
|||
enable(false); |
|||
} |
|||
|
|||
/*******************************************************************************
|
|||
* 驱动器寄存器读写方法 * |
|||
*******************************************************************************/ |
|||
|
|||
void TMC51X0::readWriteArray(uint8_t *data, size_t length) { |
|||
portENTER_CRITICAL(); |
|||
m_csnpin.write(false); |
|||
HAL_SPI_TransmitReceive(m_hspi, data, data, length, 100); |
|||
m_csnpin.write(true); |
|||
portEXIT_CRITICAL(); |
|||
} |
|||
void TMC51X0::writeDatagram(uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4) { |
|||
uint8_t data[5] = {static_cast<uint8_t>(address | static_cast<uint8_t>(TMC5130_WRITE_BIT)), x1, x2, x3, x4}; |
|||
readWriteArray(&data[0], 5); |
|||
} |
|||
void TMC51X0::writeInt(uint8_t address, int32_t value) { //
|
|||
writeDatagram(address, BYTE(value, 3), BYTE(value, 2), BYTE(value, 1), BYTE(value, 0)); |
|||
} |
|||
|
|||
void TMC51X0::writeField(uint8_t add, uint32_t mask, uint32_t shift, uint32_t value) { |
|||
uint32_t regval = readUInt(add); |
|||
regval = (regval & ~mask) | ((value << shift) & mask); |
|||
writeInt(add, regval); |
|||
} |
|||
|
|||
int32_t TMC51X0::readInt(uint8_t address) { |
|||
/**
|
|||
* @WARNING: |
|||
* 这里没有判断寄存器是否可读,有些寄存器是不可读所以,所以可能读回来的数值和写入数值是不相等的 |
|||
*/ |
|||
address = TMC51x0_ADDRESS(address); |
|||
|
|||
uint8_t data[5] = {0, 0, 0, 0, 0}; |
|||
|
|||
data[0] = address; |
|||
readWriteArray(&data[0], 5); |
|||
|
|||
data[0] = address; |
|||
readWriteArray(&data[0], 5); |
|||
|
|||
return ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | (data[3] << 8) | data[4]; |
|||
} |
|||
|
|||
uint32_t TMC51X0::readUInt(uint8_t address) { |
|||
int32_t val = readInt(address); |
|||
uint32_t ret; |
|||
memcpy(&ret, &val, sizeof(uint32_t)); |
|||
return ret; |
|||
} |
|||
|
|||
/***********************************************************************************************************************
|
|||
* BASIC * |
|||
***********************************************************************************************************************/ |
|||
|
|||
bool TMC51X0::ping() { |
|||
zlock_guard lkg(m_mutex); |
|||
uint32_t regval = readUInt(TMC5130_IOIN); |
|||
uint32_t chipId = FIELD_GET(regval, TMC5130_VERSION_MASK, TMC5130_VERSION_SHIFT); |
|||
return chipId != 0; |
|||
} |
|||
void TMC51X0::enable(bool enable) { |
|||
zlock_guard lkg(m_mutex); |
|||
|
|||
m_ennpin.write(!enable); |
|||
} |
|||
|
|||
int32_t TMC51X0::to_motor_acc(int32_t acc) { //
|
|||
int32_t val = acc / 60.0 * m_onecirclepulse; // 65535
|
|||
if (val > 65535) val = 65535; |
|||
return val; |
|||
} |
|||
int32_t TMC51X0::to_motor_vel(int32_t vel) { //
|
|||
int32_t val = vel / 60.0 * m_onecirclepulse; |
|||
if (val > 8388095 /*2^23-512*/) { |
|||
val = 8388095; |
|||
} |
|||
return val; |
|||
} // rpm
|
|||
int32_t TMC51X0::to_motor_pos(int32_t pos) { //
|
|||
int32_t val = pos * 1.0 / m_scale * m_scale_deceleration * m_onecirclepulse + 0.5; |
|||
return val; |
|||
} //
|
|||
|
|||
int32_t TMC51X0::to_user_pos(int32_t pos) { //
|
|||
int32_t val = pos / m_onecirclepulse * m_scale / m_scale_deceleration + 0.5; |
|||
// ZLOGI("TMC5130", "to_user_pos %d,%d", pos, val);
|
|||
return val; |
|||
} //
|
|||
int32_t TMC51X0::to_user_vel(int32_t vel) { //
|
|||
int32_t val = vel * 60.0 / m_onecirclepulse; |
|||
return val; |
|||
} |
|||
/***********************************************************************************************************************
|
|||
* CTRL * |
|||
***********************************************************************************************************************/ |
|||
void TMC51X0::stop() { |
|||
zlock_guard lkg(m_mutex); |
|||
|
|||
rotate(0); |
|||
} |
|||
void TMC51X0::rotate(int32_t velocity) { |
|||
zlock_guard lkg(m_mutex); |
|||
|
|||
velocity = to_motor_vel(velocity); |
|||
writeInt(TMC5130_VMAX, abs(velocity)); |
|||
writeInt(TMC5130_RAMPMODE, (velocity >= 0) ? TMC5130_MODE_VELPOS : TMC5130_MODE_VELNEG); |
|||
} |
|||
void TMC51X0::moveTo(int32_t position, uint32_t velocityMax) { |
|||
zlock_guard lkg(m_mutex); |
|||
|
|||
position = to_motor_pos(position); |
|||
velocityMax = to_motor_vel(velocityMax); |
|||
writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION); |
|||
writeInt(TMC5130_VMAX, velocityMax); |
|||
writeInt(TMC5130_XTARGET, position); |
|||
} |
|||
void TMC51X0::moveToEnd(int32_t direction, uint32_t velocityMax) { |
|||
zlock_guard lkg(m_mutex); |
|||
|
|||
if (direction >= 0) { |
|||
writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION); |
|||
writeInt(TMC5130_VMAX, to_motor_vel(velocityMax)); |
|||
writeInt(TMC5130_XTARGET, INT32_MAX / 1.5 - 1000); |
|||
} else { |
|||
writeInt(TMC5130_RAMPMODE, TMC5130_MODE_POSITION); |
|||
writeInt(TMC5130_VMAX, to_motor_vel(velocityMax)); |
|||
writeInt(TMC5130_XTARGET, INT32_MIN / 1.5 + 1000); |
|||
} |
|||
} |
|||
|
|||
void TMC51X0::moveBy(int32_t relativePosition, uint32_t velocityMax) { // determine actual position and add numbers of ticks to move
|
|||
zlock_guard lkg(m_mutex); |
|||
|
|||
int32_t pos = getXACTUAL(); |
|||
int32_t target = pos + relativePosition; |
|||
moveTo(target, velocityMax); |
|||
} |
|||
|
|||
/***********************************************************************************************************************
|
|||
* GET STATE * |
|||
***********************************************************************************************************************/ |
|||
|
|||
int32_t TMC51X0::getXACTUAL() { |
|||
zlock_guard lkg(m_mutex); |
|||
|
|||
return to_user_pos(readInt(TMC5130_XACTUAL)); |
|||
} |
|||
int32_t TMC51X0::getVACTUAL() { |
|||
zlock_guard lkg(m_mutex); |
|||
return to_user_pos(readInt(TMC5130_VACTUAL)); |
|||
} |
|||
int32_t TMC51X0::getEncVal() { |
|||
zlock_guard lkg(m_mutex); |
|||
int32_t enc_val = to_user_pos(readInt(TMC5130_XENC)); |
|||
if (m_enc_resolution < 0) { |
|||
enc_val = -enc_val; |
|||
} |
|||
return enc_val; |
|||
} |
|||
TMC5130RampStat TMC51X0::getRampStat() { |
|||
zlock_guard lkg(m_mutex); |
|||
int32_t val = readInt(TMC5130_RAMPSTAT); |
|||
return TMC5130RampStat(val); |
|||
} |
|||
|
|||
bool TMC51X0::isReachTarget(TMC5130RampStat *state) { |
|||
zlock_guard lkg(m_mutex); |
|||
int mode = readInt(TMC5130_RAMPMODE); |
|||
if (mode == TMC5130_MODE_POSITION) { |
|||
return state->isSetted(TMC5130RampStat::ktmc5130_rs_posreached); |
|||
} else { |
|||
return state->isSetted(TMC5130RampStat::ktmc5130_rs_vzero) && state->isSetted(TMC5130RampStat::ktmc5130_rs_velreached); |
|||
} |
|||
} |
|||
bool TMC51X0::isTMC5130() { |
|||
zlock_guard lkg(m_mutex); |
|||
uint32_t regval = readUInt(TMC5130_IOIN); |
|||
uint32_t chipId = FIELD_GET(regval, TMC5130_VERSION_MASK, TMC5130_VERSION_SHIFT); |
|||
return chipId == kTMC5130; |
|||
} |
|||
|
|||
TMC5130DevStatusReg_t TMC51X0::getDevStatus() { // R 读后不清
|
|||
zlock_guard lkg(m_mutex); |
|||
static_assert(sizeof(TMC5130DevStatusReg_t) == 4); |
|||
uint32_t value = readInt(TMC5130_DRVSTATUS); |
|||
TMC5130DevStatusReg_t val; |
|||
memcpy(&val, &value, sizeof(TMC5130DevStatusReg_t)); |
|||
return val; |
|||
} |
|||
TMC5130GState_t TMC51X0::getGState() { // R+C 读后自动清除
|
|||
zlock_guard lkg(m_mutex); |
|||
static_assert(sizeof(TMC5130GState_t) == 4); |
|||
uint32_t value = readInt(TMC5130_GSTAT); |
|||
TMC5130GState_t val; |
|||
memcpy(&val, &value, sizeof(TMC5130GState_t)); |
|||
return val; |
|||
} |
|||
int32_t TMC51X0::readICVersion() { |
|||
zlock_guard lkg(m_mutex); |
|||
uint32_t regval = readUInt(TMC5130_IOIN); |
|||
uint32_t chipId = FIELD_GET(regval, TMC5130_VERSION_MASK, TMC5130_VERSION_SHIFT); |
|||
return chipId; |
|||
} |
|||
|
|||
/***********************************************************************************************************************
|
|||
* set state * |
|||
***********************************************************************************************************************/ |
|||
|
|||
void TMC51X0::setXACTUAL(int32_t value) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_XACTUAL, to_motor_pos(value)); |
|||
} |
|||
void TMC51X0::setMotorShaft(bool reverse) { |
|||
zlock_guard lkg(m_mutex); |
|||
uint32_t regval = readUInt(TMC5130_GCONF); |
|||
FIELD_SET(regval, TMC5130_SHAFT_MASK, TMC5130_SHAFT_SHIFT, reverse ? 1 : 0); |
|||
writeInt(TMC5130_GCONF, regval); |
|||
// uint32_t readbak = readUInt(TMC5130_GCONF);
|
|||
// ZLOGI(TAG, "%x,%x", regval, readbak);
|
|||
} |
|||
void TMC51X0::setIHOLD_IRUN(uint8_t ihold, uint8_t irun, uint16_t iholddelay) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_IHOLD_IRUN, (iholddelay << TMC5130_IHOLDDELAY_SHIFT) | (irun << TMC5130_IRUN_SHIFT) | (ihold << TMC5130_IHOLD_SHIFT)); |
|||
} |
|||
void TMC51X0::setGlobalScale(uint8_t globalscale) { |
|||
#define TMC5160_GLOBAL_SCALER 0x0B
|
|||
#define TMC5160_GLOBAL_SCALER_MASK 0xFF
|
|||
#define TMC5160_GLOBAL_SCALER_SHIFT 0
|
|||
zlock_guard lkg(m_mutex); |
|||
if (isTMC5130()) { |
|||
return; |
|||
} |
|||
|
|||
if (globalscale == 0) { |
|||
globalscale = 0; |
|||
} else if (globalscale <= 31 && globalscale >= 1) { |
|||
globalscale = 32; |
|||
} else { |
|||
globalscale = globalscale; |
|||
} |
|||
writeInt(TMC5160_GLOBAL_SCALER, (readInt(TMC5160_GLOBAL_SCALER) & ~TMC5160_GLOBAL_SCALER_MASK) | (globalscale << TMC5160_GLOBAL_SCALER_SHIFT)); |
|||
} |
|||
void TMC51X0::setScale(int32_t scale) { |
|||
zlock_guard lkg(m_mutex); |
|||
m_scale = scale; |
|||
} |
|||
void TMC51X0::setScaleDenominator(int32_t scale) { |
|||
zlock_guard lkg(m_mutex); |
|||
m_scale_deceleration = scale; |
|||
} |
|||
void TMC51X0::setVstart(int32_t val) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_VSTART, to_motor_vel(val)); |
|||
} |
|||
void TMC51X0::setA1(int32_t val) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_A1, to_motor_acc(val)); |
|||
} |
|||
void TMC51X0::setAmax(int32_t val) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_AMAX, to_motor_acc(val)); |
|||
} |
|||
void TMC51X0::setV1(int32_t val) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_V1, to_motor_vel(val)); |
|||
} |
|||
void TMC51X0::setDmax(int32_t val) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_DMAX, to_motor_acc(val)); |
|||
} |
|||
void TMC51X0::setD1(int32_t val) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_D1, to_motor_acc(val)); |
|||
} |
|||
void TMC51X0::setVstop(int32_t val) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_VSTOP, to_motor_vel(val)); |
|||
} |
|||
void TMC51X0::setTzerowait(int32_t val) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(TMC5130_TZEROWAIT, val); |
|||
} |
|||
bool TMC51X0::setEncResolution(int32_t enc_resolution) { |
|||
zlock_guard lkg(m_mutex); |
|||
/**
|
|||
* @brief |
|||
* |
|||
* 1.假设电机是256细分 |
|||
* 2.假设TMC5130_ENC_CONST是十进制模式 |
|||
* 3.只支持指定分辨率的编码器 |
|||
*/ |
|||
|
|||
int32_t enc_resolution_tmp = enc_resolution * 4; |
|||
int16_t enc_const_integral = 0; |
|||
int16_t enc_const_fractional = 0; |
|||
|
|||
switch (abs(enc_resolution_tmp)) { |
|||
case 1000: |
|||
enc_const_integral = 51; |
|||
enc_const_fractional = 0.2 * 10000; |
|||
break; |
|||
case 1024: |
|||
enc_const_integral = 50; |
|||
enc_const_fractional = 0 * 10000; |
|||
break; |
|||
case 4000: |
|||
enc_const_integral = 12; |
|||
enc_const_fractional = 0.8 * 10000; |
|||
break; |
|||
case 4096: |
|||
enc_const_integral = 12; |
|||
enc_const_fractional = 0.5 * 10000; |
|||
break; |
|||
case 16384: |
|||
enc_const_integral = 3; |
|||
enc_const_fractional = 0.125 * 10000; |
|||
break; |
|||
case 0: |
|||
m_enc_resolution = 0; |
|||
return true; |
|||
|
|||
default: |
|||
return false; |
|||
break; |
|||
} |
|||
|
|||
m_enc_resolution = enc_resolution; |
|||
uint32_t setval = 0; |
|||
uint8_t *psetval = (uint8_t *)&setval; |
|||
|
|||
memcpy(psetval + 2, &enc_const_integral, 2); |
|||
memcpy(psetval, &enc_const_fractional, 2); |
|||
|
|||
writeInt(TMC5130_ENCMODE, 0x1 << 10); |
|||
writeInt(TMC5130_ENC_CONST, setval); |
|||
return true; |
|||
} |
|||
void TMC51X0::setEncVal(int32_t enc_val) { |
|||
zlock_guard lkg(m_mutex); |
|||
int32_t enc_set_val = to_motor_pos(enc_val); |
|||
if (m_enc_resolution < 0) { |
|||
enc_set_val = -enc_set_val; |
|||
} |
|||
writeInt(TMC5130_XENC, enc_set_val); |
|||
} |
|||
|
|||
/***********************************************************************************************************************
|
|||
* reg operation * |
|||
***********************************************************************************************************************/ |
|||
void TMC51X0::writeIntExt(uint8_t address, int32_t value) { |
|||
zlock_guard lkg(m_mutex); |
|||
writeInt(address, value); |
|||
} |
|||
int32_t TMC51X0::readIntExt(uint8_t address) { |
|||
zlock_guard lkg(m_mutex); |
|||
return readInt(address); |
|||
} |
@ -1,125 +0,0 @@ |
|||
#pragma once
|
|||
#include <stdbool.h>
|
|||
#include <stdint.h>
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
|
|||
#include "stm32basic/zbasic.h"
|
|||
#include "stm32basic/zgpio.hpp"
|
|||
//
|
|||
#include "../tmc/tmc_type.h"
|
|||
#include "reg/TMC5130_Type.h"
|
|||
#include "stm32basic/mutex.hpp"
|
|||
namespace iflytop { |
|||
/**
|
|||
* @brief |
|||
* 注意事项 |
|||
* |
|||
* 1. 6点加速控制只在位置模式下有效,在速度模式下无效 |
|||
* 2. 速度模式下只有AMAX有效 |
|||
* |
|||
*/ |
|||
class TMC51X0Cfg { |
|||
public: |
|||
SPI_HandleTypeDef *hspi = NULL; |
|||
Pin_t csnpin; |
|||
Pin_t ennpin; |
|||
|
|||
TMC51X0Cfg(SPI_HandleTypeDef *hspi, Pin_t csnpin, Pin_t ennpin) : hspi(hspi), csnpin(csnpin), ennpin(ennpin) {} |
|||
TMC51X0Cfg() {} |
|||
}; |
|||
|
|||
class TMC51X0 { |
|||
protected: |
|||
TMC51X0Cfg m_cfg; |
|||
|
|||
SPI_HandleTypeDef *m_hspi = NULL; |
|||
ZGPIO m_csnpin; |
|||
ZGPIO m_ennpin; |
|||
|
|||
int32_t m_scale = 10000; |
|||
int32_t m_scale_deceleration = 1; |
|||
mres_type_t m_MRES = kmres_256; |
|||
double m_onecirclepulse = 51200; |
|||
int32_t m_enc_resolution = 0; // 编码器分辨率,默认只有在256细分的情况下有效
|
|||
|
|||
zmutex m_mutex; |
|||
bool m_driErr = false; |
|||
|
|||
public: |
|||
void initialize(TMC51X0Cfg cfg); |
|||
|
|||
private: |
|||
/*******************************************************************************
|
|||
* 驱动器寄存器读写方法 * |
|||
*******************************************************************************/ |
|||
void readWriteArray(uint8_t *data, size_t length); |
|||
void writeDatagram(uint8_t address, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4); |
|||
void writeInt(uint8_t address, int32_t value); |
|||
void writeField(uint8_t add, uint32_t mask, uint32_t shift, uint32_t value); |
|||
int32_t readInt(uint8_t address); |
|||
uint32_t readUInt(uint8_t address); |
|||
|
|||
public: |
|||
bool ping(); |
|||
void enable(bool enable); |
|||
|
|||
void setdriErr(bool val) { m_driErr = val; } |
|||
bool getdriErr() { return m_driErr; } |
|||
/***********************************************************************************************************************
|
|||
* ctrl * |
|||
***********************************************************************************************************************/ |
|||
void rotate(int32_t velocity); |
|||
void moveTo(int32_t position, uint32_t velocityMax); |
|||
void moveToEnd(int32_t direction, uint32_t velocityMax); |
|||
void moveBy(int32_t relativePosition, uint32_t velocityMax); |
|||
void stop(); |
|||
/***********************************************************************************************************************
|
|||
* get state * |
|||
***********************************************************************************************************************/ |
|||
int32_t getXACTUAL(); // 当前位置
|
|||
int32_t getVACTUAL(); // 当前速度
|
|||
int32_t getEncVal(); // ENCVAL
|
|||
TMC5130RampStat getRampStat(); |
|||
TMC5130DevStatusReg_t getDevStatus(); // R 读后不清
|
|||
TMC5130GState_t getGState(); // R+C 读后自动清除
|
|||
int32_t readICVersion(); |
|||
|
|||
bool isReachTarget(TMC5130RampStat *state); // 是否到达目标位置
|
|||
bool isTMC5130(); |
|||
|
|||
/***********************************************************************************************************************
|
|||
* set state * |
|||
***********************************************************************************************************************/ |
|||
void setXACTUAL(int32_t value); // 设置当前位置
|
|||
void setMotorShaft(bool reverse); |
|||
void setIHOLD_IRUN(uint8_t ihold, uint8_t irun, uint16_t iholddelay); |
|||
void setGlobalScale(uint8_t globalscale); // ONLY for 5160
|
|||
void setScale(int32_t scale); |
|||
void setScaleDenominator(int32_t scale); |
|||
void setVstart(int32_t val); |
|||
void setA1(int32_t val); |
|||
void setAmax(int32_t val); |
|||
void setV1(int32_t val); |
|||
void setDmax(int32_t val); |
|||
void setD1(int32_t val); |
|||
void setVstop(int32_t val); |
|||
void setTzerowait(int32_t val); |
|||
bool setEncResolution(int32_t enc_resolution); |
|||
void setEncVal(int32_t enc_val); |
|||
|
|||
/***********************************************************************************************************************
|
|||
* reg operation * |
|||
***********************************************************************************************************************/ |
|||
void writeIntExt(uint8_t address, int32_t value); |
|||
int32_t readIntExt(uint8_t address); |
|||
|
|||
private: |
|||
int32_t to_motor_acc(int32_t acc); // rpm/s^2
|
|||
int32_t to_motor_vel(int32_t vel); // rpm
|
|||
int32_t to_motor_pos(int32_t pos); //
|
|||
int32_t to_user_pos(int32_t pos); //
|
|||
int32_t to_user_vel(int32_t vel); |
|||
}; |
|||
} // namespace iflytop
|
@ -1,429 +0,0 @@ |
|||
#include "zcanreceiver.hpp"
|
|||
|
|||
#include "../mutex.hpp"
|
|||
#include "stm32halport/stm32halport.hpp"
|
|||
#define TAG "zcan"
|
|||
#ifndef ENABLE_OLD_CAN_PROTOCOL
|
|||
#define CANHANDLER &hcan1
|
|||
#define CAN_FILTER_INDEX 0
|
|||
#define CAN_MAX_FILTER_NUM 7
|
|||
#define CAN_FIFO_NUM CAN_RX_FIFO0
|
|||
#define OVER_TIME_MS 30
|
|||
|
|||
using namespace iflytop; |
|||
using namespace zscanprotocol; |
|||
using namespace transmit_disfection_protocol; |
|||
|
|||
static uint8_t m_deviceId; |
|||
static zcanbus_on_rx_t m_rxlistener[30]; |
|||
static uint32_t m_numListener = 0; |
|||
static zcanbus_on_connected_t m_connectedlistener; |
|||
|
|||
static canrxbuffer_t m_rxbufcache; |
|||
|
|||
static uint16_t reportIndex; |
|||
|
|||
static uint8_t rxdata[200]; |
|||
static uint8_t txbuff[200]; |
|||
|
|||
static uint32_t lastpacket_ticket; |
|||
static bool m_is_connected; |
|||
|
|||
static uint8_t m_priority; |
|||
|
|||
zmutex m_lock; |
|||
|
|||
static void _oncanpacket(CAN_HandleTypeDef *hcan); |
|||
static void _processOneCanPacket(CAN_RxHeaderTypeDef *pHeader, uint8_t *aData); |
|||
static bool _getRxMessage(CAN_RxHeaderTypeDef *pHeader, uint8_t aData[] /*8byte table*/); |
|||
|
|||
extern "C" { |
|||
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0CompleteCallback"); } |
|||
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1CompleteCallback"); } |
|||
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2CompleteCallback"); } |
|||
void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0AbortCallback"); } |
|||
void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1AbortCallback"); } |
|||
void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2AbortCallback"); } |
|||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { _oncanpacket(hcan); } |
|||
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo0FullCallback"); } |
|||
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1MsgPendingCallback"); } |
|||
void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1FullCallback"); } |
|||
void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_SleepCallback"); } |
|||
void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_WakeUpFromRxMsgCallback"); } |
|||
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_ErrorCallback"); } |
|||
} |
|||
|
|||
/***********************************************************************************************************************
|
|||
* 中断消息处理 * |
|||
***********************************************************************************************************************/ |
|||
|
|||
static void _oncanpacket(CAN_HandleTypeDef *hcan) { |
|||
if (CANHANDLER != hcan) return; |
|||
CAN_RxHeaderTypeDef pHeader; |
|||
uint8_t aData[8] /*8byte table*/; |
|||
while (_getRxMessage(&pHeader, aData)) { |
|||
_processOneCanPacket(&pHeader, aData); |
|||
} |
|||
} |
|||
|
|||
static bool _getRxMessage(CAN_RxHeaderTypeDef *pHeader, uint8_t aData[] /*8byte table*/) { |
|||
/**
|
|||
* @brief 读取当前FIFO中缓存了多少帧的数据 |
|||
*/ |
|||
uint32_t level = HAL_CAN_GetRxFifoFillLevel(CANHANDLER, CAN_FIFO_NUM); |
|||
if (level == 0) { |
|||
return false; |
|||
} |
|||
HAL_StatusTypeDef HAL_RetVal; |
|||
HAL_RetVal = HAL_CAN_GetRxMessage(CANHANDLER, CAN_FIFO_NUM, pHeader, aData); |
|||
if (HAL_OK == HAL_RetVal) { |
|||
// 处理接收到的can总线数据
|
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
static void _processOneCanPacket(CAN_RxHeaderTypeDef *pHeader, uint8_t *aData) { |
|||
/**
|
|||
* @brief 消息格式 12bit from,1bit emergency |
|||
* |
|||
* [1] [4bit] [8bit] [8bit] [4bit/4bit] |
|||
* , from to frameNum/frameId |
|||
*/ |
|||
uint8_t from = (pHeader->ExtId & 0x00FF0000) >> 16; |
|||
uint8_t to = (pHeader->ExtId & 0x0000FF00) >> 8; |
|||
uint8_t nframe = (pHeader->ExtId & 0x000000F0) >> 4; |
|||
uint8_t frameId = (pHeader->ExtId & 0x0000000F); |
|||
|
|||
// ZLOGI(TAG, "from:%d to:%d nframe:%d frameId:%d", from, to, nframe, frameId);
|
|||
|
|||
if (pHeader->IDE == CAN_ID_STD) { |
|||
return; |
|||
} |
|||
|
|||
// 只接收主机消息
|
|||
if (from != 1) { |
|||
return; |
|||
} |
|||
|
|||
if (to != m_deviceId && to != 0xff) { |
|||
return; |
|||
} |
|||
|
|||
// 上次接收到的消息还没有来的急处理
|
|||
if (m_rxbufcache.dataIsReady) { |
|||
ZLOGI(TAG, "discard rx packet ,last packet not processed"); |
|||
return; |
|||
} |
|||
|
|||
if (frameId == 0) { |
|||
m_rxbufcache.canPacketNum = 0; |
|||
} |
|||
|
|||
if (frameId != m_rxbufcache.canPacketNum) { |
|||
m_rxbufcache.canPacketNum = 0; |
|||
ZLOGI(TAG, "discard rx packet ,due to lost packet"); |
|||
return; |
|||
} |
|||
|
|||
if (m_rxbufcache.canPacketNum < ZARRAY_SIZE(m_rxbufcache.canPacket)) { |
|||
if (m_rxbufcache.canPacketNum == 0) { |
|||
m_rxbufcache.header = *pHeader; |
|||
m_rxbufcache.from = from; |
|||
m_rxbufcache.to = to; |
|||
} |
|||
m_rxbufcache.canPacket[m_rxbufcache.canPacketNum].datalen = pHeader->DLC; |
|||
memcpy(m_rxbufcache.canPacket[m_rxbufcache.canPacketNum].aData, aData, 8); |
|||
m_rxbufcache.canPacketNum++; |
|||
} else { |
|||
ZLOGI(TAG, "discard rx packet ,due to buffer full"); |
|||
m_rxbufcache.canPacketNum = 0; |
|||
return; |
|||
} |
|||
|
|||
if (nframe == frameId + 1) { |
|||
if (m_rxbufcache.canPacketNum != nframe) { |
|||
m_rxbufcache.canPacketNum = 0; |
|||
ZLOGI(TAG, "discard rx packet ,due to lost packet"); |
|||
return; |
|||
} else { |
|||
m_rxbufcache.dataIsReady = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/***********************************************************************************************************************
|
|||
* FUNC * |
|||
***********************************************************************************************************************/ |
|||
|
|||
static HAL_StatusTypeDef activateRxIT() { |
|||
HAL_StatusTypeDef hal_status = HAL_ERROR; |
|||
if (CAN_FIFO_NUM == CAN_RX_FIFO0) { |
|||
hal_status = HAL_CAN_ActivateNotification(CANHANDLER, CAN_IT_RX_FIFO0_MSG_PENDING); |
|||
} else if (CAN_FIFO_NUM == CAN_RX_FIFO1) { |
|||
hal_status = HAL_CAN_ActivateNotification(CANHANDLER, CAN_IT_RX_FIFO1_MSG_PENDING); |
|||
} else { |
|||
ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n"); |
|||
return hal_status; |
|||
} |
|||
return hal_status; |
|||
} |
|||
// static HAL_StatusTypeDef deactivateRxIT() {
|
|||
// HAL_StatusTypeDef hal_status = HAL_ERROR;
|
|||
// if (CAN_FIFO_NUM == CAN_RX_FIFO0) {
|
|||
// hal_status = HAL_CAN_DeactivateNotification(CANHANDLER, CAN_IT_RX_FIFO0_MSG_PENDING);
|
|||
// } else if (CAN_FIFO_NUM == CAN_RX_FIFO1) {
|
|||
// hal_status = HAL_CAN_DeactivateNotification(CANHANDLER, CAN_IT_RX_FIFO1_MSG_PENDING);
|
|||
// } else {
|
|||
// ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n");
|
|||
// return hal_status;
|
|||
// }
|
|||
// return hal_status;
|
|||
// }
|
|||
|
|||
HAL_StatusTypeDef initializeFilter() { |
|||
HAL_StatusTypeDef HAL_Status; |
|||
CAN_FilterTypeDef sFilterConfig; |
|||
|
|||
uint32_t filterId; |
|||
uint32_t mask; |
|||
|
|||
memset(&sFilterConfig, 0, sizeof(sFilterConfig)); |
|||
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // 设为MASK模式
|
|||
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // CAN_FILTERSCALE_16BIT
|
|||
sFilterConfig.FilterFIFOAssignment = CAN_FIFO_NUM; // 关联过滤器到rxfifoNum
|
|||
sFilterConfig.FilterActivation = ENABLE; // 激活过滤器
|
|||
sFilterConfig.SlaveStartFilterBank = CAN_MAX_FILTER_NUM; // slave filter start index
|
|||
|
|||
/*******************************************************************************
|
|||
* 接收所有消息 * |
|||
*******************************************************************************/ |
|||
filterId = (0); //
|
|||
mask = (0); //
|
|||
sFilterConfig.FilterBank = CAN_FILTER_INDEX; //
|
|||
sFilterConfig.FilterMaskIdLow = mask & 0xffff; //
|
|||
sFilterConfig.FilterMaskIdHigh = (mask & 0xffff0000) >> 16; //
|
|||
sFilterConfig.FilterIdLow = filterId & 0xffff; //
|
|||
sFilterConfig.FilterIdHigh = (filterId & 0xffff0000) >> 16; //
|
|||
HAL_Status = HAL_CAN_ConfigFilter(CANHANDLER, &sFilterConfig); |
|||
if (HAL_Status != HAL_OK) { |
|||
ZLOGE(TAG, "HAL_CAN_ConfigFilter filter0 fail"); |
|||
return HAL_Status; |
|||
} |
|||
// ZLOGI(TAG, "HAL_CAN_ConfigFilter filterID1 %08x", filterId >> 3);
|
|||
return HAL_Status; |
|||
} |
|||
|
|||
void zcanbus_init(uint8_t deviceId) { |
|||
m_deviceId = deviceId; |
|||
|
|||
HAL_StatusTypeDef hal_status; |
|||
|
|||
m_rxbufcache.dataIsReady = false; |
|||
m_rxbufcache.id = 0; // 只接收来自主机的消息
|
|||
m_rxbufcache.canPacketNum = 0; |
|||
|
|||
hal_status = initializeFilter(); |
|||
if (hal_status != HAL_OK) { |
|||
ZLOGE(TAG, "start can initializeFilter fail\r\n"); |
|||
return; |
|||
} |
|||
|
|||
hal_status = HAL_CAN_Start(CANHANDLER); // 开启CAN
|
|||
if (hal_status != HAL_OK) { |
|||
ZLOGE(TAG, "start can fail\r\n"); |
|||
return; |
|||
} |
|||
m_lock.init(); |
|||
|
|||
HAL_StatusTypeDef status = activateRxIT(); |
|||
if (status != HAL_OK) { |
|||
ZLOGE(TAG, "activateRxIT fail\r\n"); |
|||
ZASSERT(0); |
|||
return; |
|||
} |
|||
ZLOGI(TAG, "zcanbus init done"); |
|||
} |
|||
void zcanbus_reglistener(zcanbus_on_rx_t rxlistener) { |
|||
ZASSERT(m_numListener < ZARRAY_SIZE(m_rxlistener)); |
|||
m_rxlistener[m_numListener++] = rxlistener; |
|||
} |
|||
|
|||
void zcanbus_reg_on_connected_listener(zcanbus_on_connected_t connectedlistener) { m_connectedlistener = connectedlistener; } |
|||
|
|||
bool zcanbus_send_packet(uint8_t to, uint8_t *packet, size_t len) { return zcanbus_send_packet(to, packet, len, OVER_TIME_MS); } |
|||
|
|||
static char *hex2str(uint8_t *data, size_t len) { |
|||
static char buf[200]; |
|||
memset(buf, 0, sizeof(buf)); |
|||
for (size_t i = 0; i < len; i++) { |
|||
sprintf(buf + i * 2, "%02x", data[i]); |
|||
} |
|||
return buf; |
|||
} |
|||
|
|||
bool zcanbus_send_packet(uint8_t to, uint8_t *packet, size_t len, int overtimems) { |
|||
ZLOGI(TAG, "sendPacket to:%d, %s(%d)", to, hex2str(packet,len), len); |
|||
int npacket = len / 8 + (len % 8 == 0 ? 0 : 1); |
|||
if (npacket > 255) { |
|||
ZLOGE(TAG, "sendPacket fail, len:%d", len); |
|||
return false; |
|||
} |
|||
int finalpacketlen = len % 8 == 0 ? 8 : len % 8; |
|||
|
|||
for (uint8_t i = 0; i < npacket; i++) { |
|||
bool suc = false; |
|||
if (i == npacket - 1) { |
|||
suc = zcanbus_send_sub_packet(to, npacket, i, packet + i * 8, finalpacketlen, overtimems); |
|||
} else { |
|||
suc = zcanbus_send_sub_packet(to, npacket, i, packet + i * 8, 8, overtimems); |
|||
} |
|||
if (!suc) { |
|||
// ZLOGE(TAG, "sendPacket fail, packet(%d:%d)", npacket, i);
|
|||
return false; |
|||
} |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
// static const char *canpacket_dump(uint8_t *data, int size) {
|
|||
// static char buf[20];
|
|||
// memset(buf, 0, sizeof(buf));
|
|||
// for (int i = 0; i < size; i++) {
|
|||
// sprintf(buf + i * 2, "%02x", data[i]);
|
|||
// }
|
|||
// return buf;
|
|||
// }
|
|||
|
|||
bool zcanbus_send_sub_packet(uint8_t to, int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems) { |
|||
CAN_TxHeaderTypeDef pHeader; |
|||
uint8_t aData[8] /*8byte table*/; |
|||
uint32_t txMailBox = 0; |
|||
|
|||
uint32_t enterticket = zget_ticket(); |
|||
|
|||
memset(&pHeader, 0, sizeof(pHeader)); |
|||
memset(aData, 0, sizeof(aData)); |
|||
pHeader.StdId = 0x00; |
|||
pHeader.ExtId = (m_deviceId << 16) | (to << 8) | (npacket << 4) | (packetIndex); |
|||
pHeader.ExtId |= (m_priority & 0x0f) << 24; |
|||
pHeader.ExtId |= (0x01 << 28); |
|||
pHeader.IDE = CAN_ID_EXT; |
|||
pHeader.RTR = CAN_RTR_DATA; |
|||
pHeader.DLC = len; |
|||
pHeader.TransmitGlobalTime = DISABLE; |
|||
|
|||
memcpy(aData, packet, len); |
|||
// ZLOGI(TAG, "tx %s", canpacket_dump(aData, len));
|
|||
|
|||
HAL_StatusTypeDef lastTransmitStatus = HAL_CAN_AddTxMessage(CANHANDLER, &pHeader, aData, &txMailBox); |
|||
if (lastTransmitStatus != HAL_OK) { |
|||
ZLOGE(TAG, "HAL_CAN_AddTxMessage fail"); |
|||
return false; |
|||
} |
|||
|
|||
while (HAL_CAN_IsTxMessagePending(CANHANDLER, txMailBox)) { |
|||
if (zhas_passedms(enterticket) > (uint32_t)overtimems) { |
|||
lastTransmitStatus = HAL_TIMEOUT; |
|||
HAL_CAN_AbortTxRequest(CANHANDLER, txMailBox); |
|||
return false; |
|||
} |
|||
zos_delay_ms(1); |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool zcanbus_send_ack(zcanbus_packet_t *rxpacket, uint8_t *param, size_t len) { |
|||
zlock_guard l(m_lock); |
|||
zcanbus_packet_t *txpacket = (zcanbus_packet_t *)txbuff; |
|||
txpacket->index = rxpacket->index; |
|||
txpacket->function_id = rxpacket->function_id; |
|||
txpacket->ptype = kreceipt; |
|||
if (param) memcpy(txpacket->params, param, len); |
|||
return zcanbus_send_packet(1 /*mainboard*/, (uint8_t *)&txpacket[0], sizeof(zcanbus_packet_t) + len); |
|||
} |
|||
|
|||
bool zcanbus_send_ack(iflytop::zscanprotocol::zcanbus_packet_t *rxpacket, int32_t val) { return zcanbus_send_ack(rxpacket, (uint8_t *)&val, sizeof(val)); } |
|||
bool zcanbus_send_ack(iflytop::zscanprotocol::zcanbus_packet_t *rxpacket, bool _val) { |
|||
int32_t val = _val ? 1 : 0; |
|||
return zcanbus_send_ack(rxpacket, (uint8_t *)&val, sizeof(val)); |
|||
} |
|||
|
|||
bool zcanbus_send_errorack(zcanbus_packet_t *rxpacket, int32_t errcode) { |
|||
zlock_guard l(m_lock); |
|||
m_priority = kpriority_receipt; |
|||
|
|||
zcanbus_packet_t *txpacket = (zcanbus_packet_t *)txbuff; |
|||
txpacket->index = rxpacket->index; |
|||
txpacket->function_id = rxpacket->function_id; |
|||
txpacket->ptype = kerror_receipt; |
|||
memcpy(txpacket->params, &errcode, sizeof(errcode)); |
|||
return zcanbus_send_packet(1 /*mainboard*/, (uint8_t *)&txpacket[0], sizeof(zcanbus_packet_t) + 4); |
|||
} |
|||
bool zcanbus_send_report(uint16_t function_id, uint8_t *param, size_t len, int32_t overtime) { |
|||
zlock_guard l(m_lock); |
|||
m_priority = kpriority_report; |
|||
|
|||
zcanbus_packet_t *txpacket = (zcanbus_packet_t *)txbuff; |
|||
txpacket->index = reportIndex++; |
|||
txpacket->function_id = function_id; |
|||
txpacket->ptype = kreport; |
|||
memcpy(txpacket->params, param, len); |
|||
return zcanbus_send_packet(1 /*mainboard*/, (uint8_t *)&txpacket[0], sizeof(zcanbus_packet_t) + len, overtime); |
|||
} |
|||
|
|||
bool zcanbus_send_emergency_report(uint16_t function_id, uint8_t *param, size_t len, int32_t overtime) { |
|||
zlock_guard l(m_lock); |
|||
m_priority = kpriority_emergency_report; |
|||
|
|||
zcanbus_packet_t *txpacket = (zcanbus_packet_t *)txbuff; |
|||
txpacket->index = reportIndex++; |
|||
txpacket->function_id = function_id; |
|||
txpacket->ptype = kreport; |
|||
memcpy(txpacket->params, param, len); |
|||
return zcanbus_send_packet(1 /*mainboard*/, (uint8_t *)&txpacket[0], sizeof(zcanbus_packet_t) + len, overtime); |
|||
} |
|||
|
|||
static void process_rx_packet(canrxbuffer_t *canrxbuf, uint8_t *rx, size_t len) { |
|||
zcanbus_packet_t *packet = (zcanbus_packet_t *)rx; |
|||
|
|||
lastpacket_ticket = zget_ticket(); |
|||
if (!m_is_connected) { |
|||
m_is_connected = true; |
|||
if (m_connectedlistener) m_connectedlistener(true); |
|||
} |
|||
|
|||
if (packet->ptype == kcmd) { |
|||
for (size_t i = 0; i < m_numListener; i++) { |
|||
m_rxlistener[i](canrxbuf->from, canrxbuf->to, rxdata, len); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void zcanbus_schedule() { |
|||
canrxbuffer_t *rxbuf = &m_rxbufcache; |
|||
|
|||
uint16_t fromId = 0; |
|||
uint16_t toId = 0; |
|||
|
|||
if (rxbuf->dataIsReady) { |
|||
int dataoff = 0; |
|||
// rxdata[0] = rxbuf->from;
|
|||
// rxdata[1] = rxbuf->to;
|
|||
for (size_t i = 0; i < rxbuf->canPacketNum; i++) { |
|||
memcpy(rxdata + dataoff, rxbuf->canPacket[i].aData, rxbuf->canPacket[i].datalen); |
|||
dataoff += rxbuf->canPacket[i].datalen; |
|||
ZASSERT(dataoff < ZARRAY_SIZE(rxdata)); |
|||
} |
|||
process_rx_packet(rxbuf, rxdata, dataoff); |
|||
rxbuf->dataIsReady = false; |
|||
} |
|||
|
|||
if (m_is_connected && zhas_passedms(lastpacket_ticket) > HEART_OVERTIME) { |
|||
m_is_connected = false; |
|||
if (m_connectedlistener) m_connectedlistener(false); |
|||
} |
|||
} |
|||
|
|||
bool zcanbus_is_connected() { return m_is_connected; } |
|||
#endif
|
@ -1,48 +0,0 @@ |
|||
//
|
|||
// Created by zwsd
|
|||
//
|
|||
|
|||
#pragma once
|
|||
#include "project_configs.h"
|
|||
#include "stm32basic/zbasic.h"
|
|||
#ifndef ENABLE_OLD_CAN_PROTOCOL
|
|||
#include "transmit_disfection_protocol/transmit_disfection_protocol.hpp"
|
|||
|
|||
typedef void (*zcanbus_on_rx_t)(uint8_t from, uint8_t to, uint8_t *packet, size_t len); |
|||
typedef void (*zcanbus_on_connected_t)(bool connected); |
|||
|
|||
typedef struct { |
|||
public: |
|||
uint8_t aData[8]; /*8byte table*/ |
|||
uint8_t datalen; |
|||
} stm32_can_packet_t; |
|||
|
|||
typedef struct { |
|||
public: |
|||
uint16_t id; |
|||
CAN_RxHeaderTypeDef header; |
|||
uint8_t from; |
|||
uint8_t to; |
|||
stm32_can_packet_t canPacket[20]; // 用于接收can消息
|
|||
uint8_t canPacketNum = 0; |
|||
bool dataIsReady; |
|||
} canrxbuffer_t; |
|||
|
|||
void zcanbus_init(uint8_t deviceId); |
|||
void zcanbus_reglistener(zcanbus_on_rx_t rxlistener); |
|||
void zcanbus_reg_on_connected_listener(zcanbus_on_connected_t connectedlistener); |
|||
void zcanbus_schedule(); |
|||
bool zcanbus_is_connected(); |
|||
|
|||
bool zcanbus_send_packet(uint8_t to, uint8_t *packet, size_t len); |
|||
bool zcanbus_send_packet(uint8_t to, uint8_t *packet, size_t len, int overtimems); |
|||
bool zcanbus_send_sub_packet(uint8_t to, int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems); |
|||
|
|||
bool zcanbus_send_ack(iflytop::zscanprotocol::zcanbus_packet_t *rxpacket, uint8_t *param, size_t len); |
|||
bool zcanbus_send_ack(iflytop::zscanprotocol::zcanbus_packet_t *rxpacket, int32_t val); |
|||
bool zcanbus_send_ack(iflytop::zscanprotocol::zcanbus_packet_t *rxpacket, bool _val); |
|||
bool zcanbus_send_errorack(iflytop::zscanprotocol::zcanbus_packet_t *rxpacket, int32_t errcode); |
|||
bool zcanbus_send_report(uint16_t function_id, uint8_t *param, size_t len, int32_t overtime); |
|||
bool zcanbus_send_emergency_report(uint16_t function_id, uint8_t *param, size_t len, int32_t overtime); |
|||
|
|||
#endif
|
@ -1,350 +0,0 @@ |
|||
#include "zcanreceiver.hpp"
|
|||
|
|||
#ifdef HAL_CAN_MODULE_ENABLED
|
|||
#include <stdio.h>
|
|||
#include <stdlib.h>
|
|||
#include <string.h>
|
|||
|
|||
#include "stm32basic/zbasic.h"
|
|||
|
|||
|
|||
|
|||
#define TAG "ZCanReceiver"
|
|||
|
|||
#define OVER_TIME_MS 100
|
|||
|
|||
#ifdef ENABLE_OLD_CAN_PROTOCOL
|
|||
#include "stm32halport/stm32halport.hpp"
|
|||
|
|||
extern "C" { |
|||
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0CompleteCallback"); } |
|||
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1CompleteCallback"); } |
|||
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2CompleteCallback"); } |
|||
void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox0AbortCallback"); } |
|||
void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox1AbortCallback"); } |
|||
void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_TxMailbox2AbortCallback"); } |
|||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { ZCanReceiver::ins()->STM32_HAL_onCAN_RxFifo0MsgPending(hcan); } |
|||
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo0FullCallback"); } |
|||
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1MsgPendingCallback"); } |
|||
void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_RxFifo1FullCallback"); } |
|||
void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_SleepCallback"); } |
|||
void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) { ZLOGI(TAG, "HAL_CAN_WakeUpFromRxMsgCallback"); } |
|||
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) { ZCanReceiver::ins()->STM32_HAL_onCAN_Error(hcan); } |
|||
} |
|||
|
|||
ZCanReceiver *ZCanReceiver::ins() { |
|||
static ZCanReceiver ins; |
|||
return &ins; |
|||
} |
|||
|
|||
ZCanReceiver::CFG *ZCanReceiver::createCFG(uint8_t deviceId) { |
|||
CFG *cfg = new CFG(); |
|||
ZASSERT(cfg != NULL); |
|||
cfg->deviceId = deviceId; |
|||
#ifdef STM32F103xB
|
|||
cfg->canHandle = &hcan; |
|||
#else
|
|||
cfg->canHandle = &hcan1; |
|||
#endif
|
|||
cfg->canFilterIndex0 = 0; |
|||
cfg->maxFilterNum = 7; |
|||
cfg->rxfifoNum = CAN_RX_FIFO0; |
|||
return cfg; |
|||
} |
|||
void ZCanReceiver::init(CFG *cfg) { |
|||
HAL_StatusTypeDef hal_status; |
|||
m_config = cfg; |
|||
|
|||
/**
|
|||
* @brief 初始化CAN |
|||
*/ |
|||
|
|||
/**
|
|||
* @brief 初始化消息接收buf |
|||
*/ |
|||
m_canPacketRxBuffer[0].dataIsReady = false; |
|||
m_canPacketRxBuffer[0].id = 1; // 只接收来自主机的消息
|
|||
m_canPacketRxBuffer[0].m_canPacketNum = 0; |
|||
|
|||
/**
|
|||
* @brief 初始化过滤器 |
|||
*/ |
|||
hal_status = initializeFilter(); |
|||
if (hal_status != HAL_OK) { |
|||
ZLOGE(TAG, "start can initializeFilter fail\r\n"); |
|||
return; |
|||
} |
|||
/**
|
|||
* @brief 启动CAN |
|||
*/ |
|||
hal_status = HAL_CAN_Start(m_config->canHandle); // 开启CAN
|
|||
if (hal_status != HAL_OK) { |
|||
ZLOGE(TAG, "start can fail\r\n"); |
|||
return; |
|||
} |
|||
|
|||
HAL_StatusTypeDef status = activateRxIT(); |
|||
if (status != HAL_OK) { |
|||
ZLOGE(TAG, "activateRxIT fail\r\n"); |
|||
return; |
|||
} |
|||
} |
|||
HAL_StatusTypeDef ZCanReceiver::initializeFilter() { |
|||
/**
|
|||
* @brief ID区帧格式 |
|||
* [ 27:0 ] |
|||
* [ STDID ] [ EXTID ] |
|||
* [11 :9] [8:6] [5:0] [17:16] [15:8] [7:0] |
|||
* 优先级 属性 帧类型 目标ID 源ID |
|||
*/ |
|||
HAL_StatusTypeDef HAL_Status; |
|||
CAN_FilterTypeDef sFilterConfig; |
|||
|
|||
uint32_t filterId; |
|||
uint32_t mask; |
|||
|
|||
memset(&sFilterConfig, 0, sizeof(sFilterConfig)); |
|||
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // 设为MASK模式
|
|||
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // CAN_FILTERSCALE_16BIT
|
|||
sFilterConfig.FilterFIFOAssignment = m_config->rxfifoNum; // 关联过滤器到rxfifoNum
|
|||
sFilterConfig.FilterActivation = ENABLE; // 激活过滤器
|
|||
sFilterConfig.SlaveStartFilterBank = m_config->maxFilterNum; // slave filter start index
|
|||
|
|||
/*******************************************************************************
|
|||
* 接收所有消息 * |
|||
*******************************************************************************/ |
|||
filterId = (0); //
|
|||
mask = (0); //
|
|||
sFilterConfig.FilterBank = m_config->canFilterIndex0; //
|
|||
sFilterConfig.FilterMaskIdLow = mask & 0xffff; //
|
|||
sFilterConfig.FilterMaskIdHigh = (mask & 0xffff0000) >> 16; //
|
|||
sFilterConfig.FilterIdLow = filterId & 0xffff; //
|
|||
sFilterConfig.FilterIdHigh = (filterId & 0xffff0000) >> 16; //
|
|||
HAL_Status = HAL_CAN_ConfigFilter(m_config->canHandle, &sFilterConfig); |
|||
if (HAL_Status != HAL_OK) { |
|||
ZLOGE(TAG, "HAL_CAN_ConfigFilter filter0 fail"); |
|||
return HAL_Status; |
|||
} |
|||
ZLOGI(TAG, "HAL_CAN_ConfigFilter filterID1 %08x", filterId >> 3); |
|||
return HAL_Status; |
|||
} |
|||
|
|||
void ZCanReceiver::registerListener(zcanbus_on_rx_t listener) { m_onRxData = listener; } |
|||
void ZCanReceiver::sendPacket(uint8_t *packet, size_t len, int overtime) { |
|||
/**
|
|||
* @brief |
|||
*/ |
|||
int npacket = len / 8 + (len % 8 == 0 ? 0 : 1); |
|||
if (npacket > 255) { |
|||
ZLOGE(TAG, "sendPacket fail, len:%d", len); |
|||
return; |
|||
} |
|||
int finalpacketlen = len % 8 == 0 ? 8 : len % 8; |
|||
|
|||
for (uint8_t i = 0; i < npacket; i++) { |
|||
bool suc = false; |
|||
if (i == npacket - 1) { |
|||
suc = sendPacketSub(npacket, i, packet + i * 8, finalpacketlen, overtime); |
|||
} else { |
|||
suc = sendPacketSub(npacket, i, packet + i * 8, 8, overtime); |
|||
} |
|||
if (!suc) { |
|||
ZLOGE(TAG, "sendPacket fail, packet(%d:%d)", npacket, i); |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void ZCanReceiver::sendAck(transmit_disinfection_protocol_header_t *cmdheader, uint8_t *data, size_t len) { |
|||
transmit_disinfection_protocol_header_t *txheader = (transmit_disinfection_protocol_header_t *)txbuff; |
|||
memcpy(txheader, cmdheader, sizeof(transmit_disinfection_protocol_header_t)); |
|||
txheader->packetType = kpt_ack; |
|||
memcpy(txheader->data, data, len); |
|||
sendPacket(txbuff, sizeof(transmit_disinfection_protocol_header_t) + len, OVER_TIME_MS); |
|||
} |
|||
|
|||
void ZCanReceiver::sendErrorAck(transmit_disinfection_protocol_header_t *cmdheader, int16_t errcode) { |
|||
transmit_disinfection_protocol_header_t *txheader = (transmit_disinfection_protocol_header_t *)txbuff; |
|||
memcpy(txheader, cmdheader, sizeof(transmit_disinfection_protocol_header_t)); |
|||
txheader->packetType = kpt_error_ack; |
|||
memcpy(txheader->data, &errcode, sizeof(errcode)); |
|||
sendPacket(txbuff, sizeof(transmit_disinfection_protocol_header_t) + 2, OVER_TIME_MS); |
|||
} |
|||
void ZCanReceiver::sendReport(uint16_t cmdid, uint8_t subcmdid, uint8_t *attachments, size_t len) { |
|||
transmit_disinfection_protocol_header_t *txheader = (transmit_disinfection_protocol_header_t *)txbuff; |
|||
txheader->packetindex = report_index++; |
|||
txheader->cmdid = cmdid; |
|||
txheader->subcmdid = subcmdid; |
|||
txheader->packetType = kpt_status_report; |
|||
memcpy(txheader->data, attachments, len); |
|||
sendPacket(txbuff, sizeof(transmit_disinfection_protocol_header_t) + len, OVER_TIME_MS); |
|||
} |
|||
|
|||
bool ZCanReceiver::sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems) { |
|||
CAN_TxHeaderTypeDef pHeader; |
|||
uint8_t aData[8] /*8byte table*/; |
|||
uint32_t txMailBox = 0; |
|||
|
|||
uint32_t enterticket = HAL_GetTick(); |
|||
|
|||
memset(&pHeader, 0, sizeof(pHeader)); |
|||
memset(aData, 0, sizeof(aData)); |
|||
pHeader.StdId = 0x00; |
|||
pHeader.ExtId = (m_config->deviceId << 16) | (npacket << 8) | packetIndex; |
|||
pHeader.IDE = CAN_ID_EXT; |
|||
pHeader.RTR = CAN_RTR_DATA; |
|||
pHeader.DLC = len; |
|||
pHeader.TransmitGlobalTime = DISABLE; |
|||
|
|||
memcpy(aData, packet, len); |
|||
|
|||
m_lastTransmitStatus = HAL_CAN_AddTxMessage(m_config->canHandle, &pHeader, aData, &txMailBox); |
|||
if (m_lastTransmitStatus != HAL_OK) { |
|||
ZLOGE(TAG, "HAL_CAN_AddTxMessage fail"); |
|||
return false; |
|||
} |
|||
|
|||
while (HAL_CAN_IsTxMessagePending(m_config->canHandle, txMailBox)) { |
|||
if (zhas_passedms(enterticket) > (uint32_t)overtimems) { |
|||
m_lastTransmitStatus = HAL_TIMEOUT; |
|||
HAL_CAN_AbortTxRequest(m_config->canHandle, txMailBox); |
|||
return false; |
|||
} |
|||
// m_os->sleepMS(1);
|
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool ZCanReceiver::getRxMessage(CAN_RxHeaderTypeDef *pHeader, uint8_t aData[] /*8byte table*/) { |
|||
/**
|
|||
* @brief 读取当前FIFO中缓存了多少帧的数据 |
|||
*/ |
|||
uint32_t level = HAL_CAN_GetRxFifoFillLevel(m_config->canHandle, m_config->rxfifoNum); |
|||
if (level == 0) { |
|||
return false; |
|||
} |
|||
HAL_StatusTypeDef HAL_RetVal; |
|||
HAL_RetVal = HAL_CAN_GetRxMessage(m_config->canHandle, m_config->rxfifoNum, pHeader, aData); |
|||
if (HAL_OK == HAL_RetVal) { |
|||
// 处理接收到的can总线数据
|
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
void ZCanReceiver::registerListener(CanPacketRxBufferCB_t cb) { m_listenerCBList.push_back(cb); } |
|||
|
|||
void ZCanReceiver::STM32_HAL_onCAN_RxFifo0MsgPending(CAN_HandleTypeDef *canHandle) { |
|||
/**
|
|||
* @brief 中断上下文 |
|||
*/ |
|||
// ZLOG_INFO("%s\n", __FUNCTION__);
|
|||
// printf("------------------%s\n", __FUNCTION__);
|
|||
if (canHandle != m_config->canHandle) { |
|||
return; |
|||
} |
|||
/**
|
|||
* @brief 处理can接收到消息 |
|||
*/ |
|||
CAN_RxHeaderTypeDef pHeader; |
|||
uint8_t aData[8] /*8byte table*/; |
|||
while (getRxMessage(&pHeader, aData)) { |
|||
/**
|
|||
* @brief 消息格式 |
|||
* |
|||
* [2] [3bit] [8bit] [8bit] [8bit] |
|||
* , from frameNum frameId |
|||
*/ |
|||
uint8_t from = (pHeader.ExtId >> 16 & 0xFF); |
|||
uint8_t nframe = (pHeader.ExtId & 0xFF00) >> 8; |
|||
uint8_t frameId = (pHeader.ExtId & 0x00FF); |
|||
CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[0]; |
|||
|
|||
// CAN_ID_STD
|
|||
// CAN_ID_EXT
|
|||
|
|||
if (pHeader.IDE == CAN_ID_STD) { |
|||
// 只接收扩展帧数据帧
|
|||
continue; |
|||
} |
|||
|
|||
if (from != rxbuf->id) { |
|||
// 目前只接收来自主机的消息
|
|||
continue; |
|||
} |
|||
|
|||
if (rxbuf->dataIsReady) { |
|||
// 上次接收到的消息还没有来的急处理
|
|||
continue; |
|||
} |
|||
/**
|
|||
* @TODO:判断是否丢包 |
|||
*/ |
|||
if (frameId == 0) { |
|||
rxbuf->m_canPacketNum = 0; |
|||
} |
|||
|
|||
if (rxbuf->m_canPacketNum < 255) { |
|||
rxbuf->m_canPacket[rxbuf->m_canPacketNum].pHeader = pHeader; |
|||
memcpy(rxbuf->m_canPacket[rxbuf->m_canPacketNum].aData, aData, 8); |
|||
rxbuf->m_canPacketNum++; |
|||
} |
|||
if (nframe == frameId + 1) { |
|||
rxbuf->dataIsReady = true; |
|||
rxbuf->maxFrameId = frameId; |
|||
} |
|||
} |
|||
|
|||
// deactivateRxIT();
|
|||
} |
|||
void ZCanReceiver::STM32_HAL_onCAN_Error(CAN_HandleTypeDef *canHandle) { |
|||
if (canHandle != m_config->canHandle) { |
|||
return; |
|||
} |
|||
ZLOGE(TAG, "onCAN_Error\r\n"); |
|||
} |
|||
void ZCanReceiver::loop() { |
|||
CanPacketRxBuffer *rxbuf = &m_canPacketRxBuffer[0]; |
|||
if (rxbuf->dataIsReady) { |
|||
int dataoff = 0; |
|||
for (size_t i = 0; i < rxbuf->m_canPacketNum; i++) { |
|||
memcpy(rxdata + dataoff, rxbuf->m_canPacket[i].aData, rxbuf->m_canPacket[i].pHeader.DLC); |
|||
dataoff += rxbuf->m_canPacket[i].pHeader.DLC; |
|||
memset(&rxbuf->m_canPacket[i], 0, sizeof(rxbuf->m_canPacket[i])); |
|||
} |
|||
if (m_onRxData) { |
|||
m_onRxData(rxbuf, rxdata, dataoff); |
|||
} |
|||
|
|||
for (auto &var : m_listenerCBList) { |
|||
if (var) var(rxbuf, rxdata, dataoff); |
|||
} |
|||
rxbuf->dataIsReady = false; |
|||
} |
|||
} |
|||
HAL_StatusTypeDef ZCanReceiver::activateRxIT() { |
|||
HAL_StatusTypeDef hal_status = HAL_ERROR; |
|||
if (m_config->rxfifoNum == CAN_RX_FIFO0) { |
|||
hal_status = HAL_CAN_ActivateNotification(m_config->canHandle, CAN_IT_RX_FIFO0_MSG_PENDING); |
|||
} else if (m_config->rxfifoNum == CAN_RX_FIFO1) { |
|||
hal_status = HAL_CAN_ActivateNotification(m_config->canHandle, CAN_IT_RX_FIFO1_MSG_PENDING); |
|||
} else { |
|||
ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n"); |
|||
return hal_status; |
|||
} |
|||
return hal_status; |
|||
} |
|||
HAL_StatusTypeDef ZCanReceiver::deactivateRxIT() { |
|||
HAL_StatusTypeDef hal_status = HAL_ERROR; |
|||
if (m_config->rxfifoNum == CAN_RX_FIFO0) { |
|||
hal_status = HAL_CAN_DeactivateNotification(m_config->canHandle, CAN_IT_RX_FIFO0_MSG_PENDING); |
|||
} else if (m_config->rxfifoNum == CAN_RX_FIFO1) { |
|||
hal_status = HAL_CAN_DeactivateNotification(m_config->canHandle, CAN_IT_RX_FIFO1_MSG_PENDING); |
|||
} else { |
|||
ZLOGE(TAG, "start can HAL_CAN_ActivateNotification CAN_IT_RX_FIFO0_MSG_PENDING fail\r\n"); |
|||
return hal_status; |
|||
} |
|||
return hal_status; |
|||
} |
|||
|
|||
#endif
|
|||
#endif
|
@ -1,116 +0,0 @@ |
|||
//
|
|||
// Created by zwsd
|
|||
//
|
|||
|
|||
#pragma once
|
|||
#include <functional>
|
|||
#include <list>
|
|||
|
|||
#include "project_configs.h"
|
|||
#include "stm32basic/zbasic.h"
|
|||
|
|||
#ifdef ENABLE_OLD_CAN_PROTOCOL
|
|||
|
|||
#include "transmit_disinfection_protocol_v1/transmit_disinfection_protocol_v1.hpp"
|
|||
|
|||
namespace iflytop { |
|||
namespace zcr { |
|||
using namespace std; |
|||
typedef enum { |
|||
kpacketHeader = 0, |
|||
kpacketData = 1, |
|||
kpacketTail = 2, |
|||
} packet_type_t; |
|||
|
|||
class CANPacket { |
|||
public: |
|||
CAN_RxHeaderTypeDef pHeader; |
|||
uint8_t aData[8]; /*8byte table*/ |
|||
}; |
|||
|
|||
class CanPacketRxBuffer { |
|||
public: |
|||
uint16_t id; |
|||
CANPacket m_canPacket[256]; // 用于接收can消息
|
|||
uint8_t m_canPacketNum = 0; |
|||
uint8_t maxFrameId = 0; |
|||
bool dataIsReady; |
|||
}; |
|||
}; // namespace zcr
|
|||
|
|||
using namespace zcr; |
|||
|
|||
typedef void (*zcanbus_on_rx_t)(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len); |
|||
|
|||
typedef function<void(CanPacketRxBuffer *rxbuf, uint8_t *packet, size_t len)> CanPacketRxBufferCB_t; |
|||
|
|||
class ZCanReceiver { |
|||
public: |
|||
class CFG { |
|||
public: |
|||
uint8_t deviceId; //
|
|||
/*******************************************************************************
|
|||
* CANConfig * |
|||
*******************************************************************************/ |
|||
CAN_HandleTypeDef *canHandle; // 默认使用CAN1
|
|||
int canFilterIndex0; // 过滤器0 接收,发给自身的消息
|
|||
int maxFilterNum; // 使用的过滤器数量,最大值14,默认为7
|
|||
int rxfifoNum; // 使用的FIFO,默认使用FIFO0
|
|||
int packetRxOvertime_ms; //
|
|||
}; |
|||
|
|||
uint8_t rxdata[1000]; |
|||
uint8_t txbuff[1000]; |
|||
|
|||
public: |
|||
class LoopJobContext { |
|||
public: |
|||
bool hasDoneSomething; |
|||
}; |
|||
|
|||
private: |
|||
CFG *m_config = NULL; // 配置
|
|||
bool m_canOnRxDataFlag = false; // 是否有数据接收,用于从中断上下文转移到MainLoop上下文
|
|||
uint32_t m_lastPacketTicket = 0; // 上一次接收到消息的时间,用于判断与主机是否断开连接
|
|||
HAL_StatusTypeDef m_lastTransmitStatus; // 上次调用can发送方法的返回值
|
|||
|
|||
zcanbus_on_rx_t m_onRxData = NULL; |
|||
list<CanPacketRxBufferCB_t> m_listenerCBList; |
|||
CanPacketRxBuffer m_canPacketRxBuffer[1]; |
|||
|
|||
int report_index = 0; |
|||
|
|||
public: |
|||
ZCanReceiver() {} |
|||
|
|||
static ZCanReceiver *ins(); |
|||
|
|||
CFG *createCFG(uint8_t deviceId); |
|||
void init(CFG *cfg); |
|||
|
|||
void registerListener(zcanbus_on_rx_t listener); |
|||
void registerListener(CanPacketRxBufferCB_t cb); |
|||
void sendPacket(uint8_t *packet, size_t len, int overtime); |
|||
void sendAck(transmit_disinfection_protocol_header_t *cmdheader, uint8_t *data, size_t len); |
|||
void sendErrorAck(transmit_disinfection_protocol_header_t *cmdheader, int16_t errcode); |
|||
bool sendPacketSub(int npacket, int packetIndex, uint8_t *packet, size_t len, int overtimems); |
|||
|
|||
void sendReport(uint16_t cmdid, uint8_t subcmdid, uint8_t *attachments, size_t len); |
|||
|
|||
uint8_t getDeviceId() { return m_config->deviceId; } |
|||
|
|||
void loop(); |
|||
|
|||
public: |
|||
virtual void STM32_HAL_onCAN_RxFifo0MsgPending(CAN_HandleTypeDef *can); |
|||
virtual void STM32_HAL_onCAN_Error(CAN_HandleTypeDef *can); |
|||
|
|||
private: |
|||
HAL_StatusTypeDef initializeFilter(); |
|||
HAL_StatusTypeDef activateRxIT(); |
|||
HAL_StatusTypeDef deactivateRxIT(); |
|||
bool getRxMessage(CAN_RxHeaderTypeDef *pHeader, uint8_t aData[] /*8byte table*/); |
|||
}; |
|||
|
|||
} // namespace iflytop
|
|||
#endif
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue