新增驱动

This commit is contained in:
许晟昊 2025-01-02 19:33:50 +08:00
parent ca553d8def
commit 002c586b14
6 changed files with 1853 additions and 1 deletions

24
delay.c
View File

@ -80,6 +80,14 @@ void delay_us(uint32_t nus)
}
}
/**
* @brief
*
* 使
*
* @param timer_us
* @param us
*/
void delay_hardware_us(TIM_TypeDef *timer_us, uint32_t us)
{
RESET_TIM_COUNT(timer_us);
@ -87,6 +95,22 @@ void delay_hardware_us(TIM_TypeDef *timer_us, uint32_t us)
; // 等待计数器达到指定值
}
/**
* @brief
*
* 使
*
* @param timer_us
* @param us
*/
void delay_hardware_ms(TIM_TypeDef *timer_us, uint32_t ms)
{
while (ms--)
{
delay_hardware_us(timer_us, 1000); // 每毫秒延时1000微秒
}
}
/**
* @brief nms
* @param nms: ms数 (0< nms <= 65535)

View File

@ -17,7 +17,8 @@
void delay_init(uint16_t sysclk); /* 初始化延迟函数 */
void delay_ms(uint16_t nms); /* 延时nms */
void delay_us(uint32_t nus); /* 延时nus */
void delay_hardware_us(TIM_TypeDef *timer_us, uint32_t us); /* 硬件延时nus */
void delay_hardware_us(TIM_TypeDef *timer_us, uint32_t us); /* 硬件延时us */
void delay_hardware_ms(TIM_TypeDef *timer_us, uint32_t ms); /* 硬件延时ms */
void delay_tick(uint32_t ticks); /* 延时ticks */
#endif

1011
driver/ssd1306_oled.c Normal file

File diff suppressed because it is too large Load Diff

80
driver/ssd1306_oled.h Normal file
View File

@ -0,0 +1,80 @@
#ifndef __SSD1306_OLED_H
#define __SSD1306_OLED_H
#include "main.h"
// OLED引脚定义
#define SSD1306_SDA_PORT OLED_SDA_GPIO_Port
#define SSD1306_SDA_PIN OLED_SDA_Pin
#define SSD1306_SCK_PORT OLDE_SCK_GPIO_Port
#define SSD1306_SCK_PIN OLDE_SCK_Pin
// I2C地址
#define SSD1306_I2C_ADDRESS 0x78
// OLED显示参数
#define SSD1306_WIDTH 128
#define SSD1306_HEIGHT 64
// OLED颜色
#define SSD1306_WHITE 1
#define SSD1306_BLACK 0
// OLED命令定义
#define SSD1306_CMD_DISPLAY_OFF 0xAE
#define SSD1306_CMD_DISPLAY_ON 0xAF
#define SSD1306_CMD_SET_CONTRAST 0x81
#define SSD1306_CMD_DISPLAY_ALL_ON_RESUME 0xA4
#define SSD1306_CMD_DISPLAY_ALL_ON 0xA5
#define SSD1306_CMD_NORMAL_DISPLAY 0xA6
#define SSD1306_CMD_INVERT_DISPLAY 0xA7
#define SSD1306_CMD_SET_DISPLAY_OFFSET 0xD3
#define SSD1306_CMD_SET_COM_PINS 0xDA
#define SSD1306_CMD_SET_VCOM_DETECT 0xDB
#define SSD1306_CMD_SET_DISPLAY_CLOCK_DIV 0xD5
#define SSD1306_CMD_SET_PRECHARGE 0xD9
#define SSD1306_CMD_SET_MULTIPLEX 0xA8
#define SSD1306_CMD_SET_LOW_COLUMN 0x00
#define SSD1306_CMD_SET_HIGH_COLUMN 0x10
#define SSD1306_CMD_SET_START_LINE 0x40
#define SSD1306_CMD_MEMORY_MODE 0x20
#define SSD1306_CMD_COLUMN_ADDR 0x21
#define SSD1306_CMD_PAGE_ADDR 0x22
#define SSD1306_CMD_COM_SCAN_INC 0xC0
#define SSD1306_CMD_COM_SCAN_DEC 0xC8
#define SSD1306_CMD_SEG_REMAP 0xA0
#define SSD1306_CMD_CHARGE_PUMP 0x8D
#define SSD1306_CMD_SET_DC_DC_ENABLE 0x14
#define SDA_OUT() \
{ \
GPIO_SET_OUTPUT(SSD1306_SDA_PORT, SSD1306_SDA_PIN); \
}
#define SDA_IN() \
{ \
GPIO_SET_INPUT(SSD1306_SDA_PORT, SSD1306_SDA_PIN); \
}
// 函数声明
void ssd1306_init(void);
void ssd1306_logo(void);
void ssd1306_display_on(void);
void ssd1306_display_off(void);
void ssd1306_update_screen(void);
void ssd1306_fill(uint8_t color);
void ssd1306_clear(void);
void ssd1306_clear_buffer(void);
void ssd1306_draw_bmp(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const uint8_t *bmp);
void ssd1306_f6x8_string(uint8_t x, uint8_t y, const uint8_t *ch);
void ssd1306_f6x8_number(uint8_t x, uint8_t y, float32 num, uint8_t dot_num);
void ssd1306_f6x8_string_number(uint8_t x, uint8_t y, const uint8_t *ch, uint8_t unit, float32 num);
void ssd1306_f8x16_string(uint8_t x, uint8_t y, const uint8_t *ch);
void ssd1306_f8x16_number(uint8_t x, uint8_t y, float32 num, uint8_t dot_num);
void ssd1306_draw_text_center(uint8_t y, const char *text);
void ssd1306_draw_progress_bar(uint8_t progress);
void ssd1306_fill_rect_angle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color);
void ssd1306_draw_rect_angle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color);
void ssd1306_draw_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color);
void ssd1306_draw_pixel(uint8_t x, uint8_t y, uint8_t color);
#endif // __SSD1306_OLED_H

364
driver/tmc2240.c Normal file
View File

@ -0,0 +1,364 @@
#include "tmc2240.h"
tmc2240_t _tmc2240[TMC2240_MAX];
static void tmc2240_write(tmc2240_index_e index, uint8_t *data)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
DBG_ASSERT(tmc->spi != NULL __DBG_LINE);
tmc->spi->gpios.cs->reset(*tmc->spi->gpios.cs);
for (uint16_t i = 0; i < 5; i++)
{
tmc->spi->interface.u.normal.spi_send(tmc->spi, data[i]);
}
tmc->spi->gpios.cs->set(*tmc->spi->gpios.cs);
}
static void tmc2240_read(tmc2240_index_e index, uint8_t *wdata, uint8_t *rdata)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
DBG_ASSERT(tmc->spi != NULL __DBG_LINE);
tmc->spi->gpios.cs->reset(*tmc->spi->gpios.cs);
for (uint16_t i = 0; i < 5; i++)
{
rdata[i] = tmc->spi->interface.u.normal.spi_send(tmc->spi, wdata[i]);
}
tmc->spi->gpios.cs->set(*tmc->spi->gpios.cs);
__NOP();
__NOP();
__NOP();
tmc->spi->gpios.cs->reset(*tmc->spi->gpios.cs);
for (uint16_t i = 0; i < 5; i++)
{
rdata[i] = tmc->spi->interface.u.normal.spi_send(tmc->spi, wdata[i]);
}
tmc->spi->gpios.cs->set(*tmc->spi->gpios.cs);
}
static void tmc2240_reg_write(tmc2240_index_e index, uint8_t reg, uint32_t data)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
DBG_ASSERT(tmc->spi != NULL __DBG_LINE);
uint8_t wdata[5] = {0};
wdata[0] = TMC2240_HIGHT_BIT | reg;
wdata[1] = (data >> 24) & 0xFF;
wdata[2] = (data >> 16) & 0xFF;
wdata[3] = (data >> 8) & 0xFF;
wdata[4] = data & 0xFF;
tmc2240_write(index, wdata);
}
static uint32_t tmc2240_reg_read(tmc2240_index_e index, uint8_t reg)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
DBG_ASSERT(tmc->spi != NULL __DBG_LINE);
uint8_t wdata[5] = {0};
uint8_t rdata[5] = {0};
wdata[0] = reg;
tmc2240_read(index, wdata, rdata);
return (rdata[1] << 24) | (rdata[2] << 16) | (rdata[3] << 8) | rdata[4];
}
/**
* @brief TMC2240步进电机驱动器
*
* TMC2240步进电机驱动器的各种参数线
*
* @param index TMC2240步进电机驱动器的索引
*/
static void tmc2240_config_write(tmc2240_index_e index)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
tmc->config.gconf.data = 0x00000000;
tmc->config.chopconf.data = 0x00410153;
tmc->config.chopconf.bits.mres = TMC2240_MRES_8;
tmc->config.drvconf.data = 0x00000021;
tmc->config.global_scaler.data = 0x00000000;
tmc->config.ihold_irun.bits.ihold = 31;
tmc->config.ihold_irun.bits.irun = 31;
tmc->config.ihold_irun.bits.iholddelay = 0;
tmc->config.ihold_irun.bits.irundelay = 0;
tmc->config.pwmconf.data = 0xC44C261E;
tmc->config.gstat.data = 0x00000007;
tmc2240_reg_write(index, TMC2240_GCONF, tmc->config.gconf.data);
tmc2240_reg_write(index, TMC2240_CHOPCONF, tmc->config.chopconf.data);
tmc2240_reg_write(index, TMC2240_DRV_CONF, tmc->config.drvconf.data);
tmc2240_reg_write(index, TMC2240_GLOBAL_SCALER, tmc->config.global_scaler.data);
tmc2240_reg_write(index, TMC2240_IHOLD_IRUN, tmc->config.ihold_irun.data);
tmc2240_reg_write(index, TMC2240_PWMCONF, tmc->config.pwmconf.data);
tmc2240_reg_write(index, TMC2240_GSTAT, tmc->config.gstat.data);
}
static void _tmc2240_motor_update(tmc2240_index_e index)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
switch (tmc->config.chopconf.bits.mres)
{
case TMC2240_MRES_256:
tmc->motor.step_angle = MOTOR_42_STEP_ANGLE / 256;
break;
case TMC2240_MRES_128:
tmc->motor.step_angle = MOTOR_42_STEP_ANGLE / 128;
break;
case TMC2240_MRES_64:
tmc->motor.step_angle = MOTOR_42_STEP_ANGLE / 64;
break;
case TMC2240_MRES_32:
tmc->motor.step_angle = MOTOR_42_STEP_ANGLE / 32;
break;
case TMC2240_MRES_16:
tmc->motor.step_angle = MOTOR_42_STEP_ANGLE / 16;
break;
case TMC2240_MRES_8:
tmc->motor.step_angle = MOTOR_42_STEP_ANGLE / 8;
break;
case TMC2240_MRES_4:
tmc->motor.step_angle = MOTOR_42_STEP_ANGLE / 4;
break;
case TMC2240_MRES_2:
tmc->motor.step_angle = MOTOR_42_STEP_ANGLE / 2;
break;
case TMC2240_MRES_1:
tmc->motor.step_angle = MOTOR_42_STEP_ANGLE;
break;
default:
break;
}
tmc->motor.circle_pulse = 360 / tmc->motor.step_angle;
}
static void _tmc2240_enable(tmc2240_index_e index, BOOL enable)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
BOOL state = tmc->en->read(*tmc->en) == 0 ? TRUE : FALSE;
if (state == enable)
{
return;
}
if (enable == TRUE)
{
PWM_START(tmc->timer, tmc->time_ch);
tmc->en->reset(*tmc->en);
tmc2240_reg_write(index, TMC2240_CHOPCONF, tmc->config.chopconf.data);
}
else
{
PWM_STOP(tmc->timer, tmc->time_ch);
tmc->en->set(*tmc->en);
chopconf_u chopconf;
osel_memset((uint8_t *)&chopconf, 0, sizeof(chopconf_u));
chopconf.bits.mres = TMC2240_MRES_1;
tmc2240_reg_write(index, TMC2240_CHOPCONF, chopconf.data);
}
}
static void _tmc2240_direction(tmc2240_index_e index, tmc2240_direction_e dir)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
if (dir == TMC2240_FORWARD)
{
tmc->dir->reset(*tmc->dir);
}
else
{
tmc->dir->set(*tmc->dir);
}
}
void tmc2240_init(tmc2240_index_e index, SPI_TypeDef *SPIx, TIM_TypeDef *timer, uint32_t time_ch, spi_gpio_group_t *gpios)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
osel_memset((uint8_t *)tmc, 0, sizeof(tmc2240_t));
tmc->timer = timer;
tmc->time_ch = time_ch;
tmc->spi = spi_create(SPI_TYPE_NORMAL, *gpios, 0);
DBG_ASSERT(tmc->spi != NULL __DBG_LINE);
tmc->spi->interface.hardware_enable(tmc->spi, SPIx);
{
tmc->default_tm.sysclk = SystemCoreClock / 1000;
tmc->default_tm.psc = PWM_GET_PSC(tmc->timer);
tmc->default_tm.arr = PWM_GET_ARR(tmc->timer);
tmc->default_tm.freq = PWM_GET_FREQ(tmc->timer);
}
tmc->params.percent = TMC2240_PWM_DUTY_DEFAULT;
tmc->params.arr = 0;
tmc->params.freq = 0;
tmc->params.enable = FALSE;
tmc->params.direction = TMC2240_FORWARD;
tmc2240_config_write(index);
_tmc2240_motor_update(index);
}
tmc2240_t *tmc2240_get(tmc2240_index_e index)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
return &_tmc2240[index];
}
void tmc2240_percent(tmc2240_index_e index, float32 percent)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
PWM_SET_DUTY(tmc->timer, tmc->time_ch, ABS(percent));
}
void tmc2240_config_read(tmc2240_index_e index)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
tmc->read_config.gconf.data = tmc2240_reg_read(index, TMC2240_GCONF);
tmc->read_config.chopconf.data = tmc2240_reg_read(index, TMC2240_CHOPCONF);
tmc->read_config.drvconf.data = tmc2240_reg_read(index, TMC2240_DRV_CONF);
tmc->read_config.global_scaler.data = tmc2240_reg_read(index, TMC2240_GLOBAL_SCALER);
tmc->read_config.ihold_irun.data = tmc2240_reg_read(index, TMC2240_IHOLD_IRUN);
tmc->read_config.pwmconf.data = tmc2240_reg_read(index, TMC2240_PWMCONF);
tmc->read_config.gstat.data = tmc2240_reg_read(index, TMC2240_GSTAT);
tmc->data.tmc2240_adc_temp = tmc2240_reg_read(index, TMC2240_ADC_TEMP);
tmc->data.tmc2240_temperature = (float32)(tmc->data.tmc2240_adc_temp - 2038) / 7.7;
}
void tmc2240_test(tmc2240_index_e index)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
_tmc2240_enable(index, tmc->params.enable);
if (tmc->params.enable == TRUE)
{
_tmc2240_direction(index, tmc->params.direction);
if (PWM_GET_ARR(tmc->timer) != tmc->params.arr)
{
if (tmc->params.arr == 0)
{
tmc->params.arr = tmc->default_tm.arr;
}
PWM_SET_ARR(tmc->timer, tmc->params.arr);
tmc->params.freq = PWM_GET_FREQ(tmc->timer);
}
tmc2240_percent(index, tmc->params.percent);
if (tmc->config.chopconf.bits.mres != tmc->read_config.chopconf.bits.mres)
{
tmc2240_reg_write(index, TMC2240_CHOPCONF, tmc->config.chopconf.data);
_tmc2240_motor_update(index);
}
}
}
void tmc2240_motor_set_angle(tmc2240_index_e index, int32_t angle)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
if (angle == 0)
{
return;
}
if (angle > 0)
{
tmc->params.direction = TMC2240_FORWARD;
}
else
{
tmc->params.direction = TMC2240_BACKWARD;
}
tmc->motor.pulse_count = ABS(angle) / tmc->motor.step_angle;
tmc->motor.step_angle_count = 0;
tmc->params.enable = TRUE;
_tmc2240_direction(index, tmc->params.direction);
if (PWM_GET_ARR(tmc->timer) != tmc->params.arr)
{
if (tmc->params.arr == 0)
{
tmc->params.arr = tmc->default_tm.arr;
}
PWM_SET_ARR(tmc->timer, tmc->params.arr);
tmc->params.freq = PWM_GET_FREQ(tmc->timer);
}
tmc2240_percent(index, tmc->params.percent);
if (tmc->config.chopconf.bits.mres != tmc->read_config.chopconf.bits.mres)
{
tmc2240_reg_write(index, TMC2240_CHOPCONF, tmc->config.chopconf.data);
_tmc2240_motor_update(index);
}
_tmc2240_enable(index, tmc->params.enable);
}
void tmc2240_motor_update(tmc2240_index_e index)
{
DBG_ASSERT(index < TMC2240_MAX __DBG_LINE);
tmc2240_t *tmc = &_tmc2240[index];
DBG_ASSERT(tmc != NULL __DBG_LINE);
if (tmc->motor.pulse_count > 0)
{
tmc->motor.pulse_count--; // 脉冲数
tmc->motor.step_angle_count++; // 步距个数
if (tmc->params.direction == TMC2240_FORWARD)
{
tmc->motor.add_pulse_count++; /* 绝对位置++ */
}
else
{
tmc->motor.add_pulse_count--; /* 绝对位置-- */
}
}
/* 当脉冲数等于0的时候 代表需要发送的脉冲个数已完成,停止输出 */
if (tmc->motor.pulse_count <= 0)
{
tmc->params.enable = FALSE;
_tmc2240_enable(index, tmc->params.enable);
}
}

372
driver/tmc2240.h Normal file
View File

@ -0,0 +1,372 @@
/**
* @file tmc2240.h
* @author xushenghao
* @brief TMC2240驱动头文件
* @version 0.1
* @note
* 1. VM需要供电SPI无法正常通信
* 2. 421.812001/81=0.2251600
*/
#ifndef __TMC2240_H
#define __TMC2240_H
#include "main.h"
#include "spis.h"
#define MOTOR_42_STEP_ANGLE 1.8f // 42步进电机每步1.8度
#define TMC2240_PWM_DUTY_DEFAULT 50 // PWM默认占空比
/*
0x00 = 0x00002108 ;; writing GCONF @ address 0=0x00 with 0x00002108=8456=0.0
0x03 = 0x00000000 ;; writing SLAVECONF @ address 1=0x03 with 0x00000000=0=0.0
0x04 = 0x4001682C ;; writing IOIN @ address 2=0x04 with 0x4001682C=1073834028=0.0
0x0A = 0x00000021 ;; writing DRV_CONF @ address 3=0x0A with 0x00000021=33=0.0
0x0B = 0x00000000 ;; writing GLOBAL_SCALER @ address 4=0x0B with 0x00000000=0=0.0
0x10 = 0x00001208 ;; writing IHOLD_IRUN @ address 5=0x10 with 0x00001208=4616=0.0
0x11 = 0x00000000 ;; writing TPOWERDOWN @ address 6=0x11 with 0x00000000=0=0.0
0x13 = 0x00000000 ;; writing TPWMTHRS @ address 7=0x13 with 0x00000000=0=0.0
0x14 = 0x000003BE ;; writing TCOOLTHRS @ address 8=0x14 with 0x000003BE=958=0.0
0x15 = 0x00000000 ;; writing THIGH @ address 9=0x15 with 0x00000000=0=0.0
0x2D = 0x00000000 ;; writing DIRECT_MODE @ address 10=0x2D with 0x00000000=0=0.0
0x38 = 0x00000000 ;; writing ENCMODE @ address 11=0x38 with 0x00000000=0=0.0
0x39 = 0x00000000 ;; writing X_ENC @ address 12=0x39 with 0x00000000=0=0.0
0x3A = 0x00010000 ;; writing ENC_CONST @ address 13=0x3A with 0x00010000=65536=0.0
0x52 = 0x0B920F25 ;; writing OTW_OV_VTH @ address 14=0x52 with 0x0B920F25=194121509=0.0
0x60 = 0xAAAAB554 ;; writing MSLUT[0] @ address 15=0x60 with 0xAAAAB554=0=0.0
0x61 = 0x4A9554AA ;; writing MSLUT[1] @ address 16=0x61 with 0x4A9554AA=1251300522=0.0
0x62 = 0x24492929 ;; writing MSLUT[2] @ address 17=0x62 with 0x24492929=608774441=0.0
0x63 = 0x10104222 ;; writing MSLUT[3] @ address 18=0x63 with 0x10104222=269500962=0.0
0x64 = 0xFBFFFFFF ;; writing MSLUT[4] @ address 19=0x64 with 0xFBFFFFFF=0=0.0
0x65 = 0xB5BB777D ;; writing MSLUT[5] @ address 20=0x65 with 0xB5BB777D=0=0.0
0x66 = 0x49295556 ;; writing MSLUT[6] @ address 21=0x66 with 0x49295556=1227445590=0.0
0x67 = 0x00404222 ;; writing MSLUT[7] @ address 22=0x67 with 0x00404222=4211234=0.0
0x68 = 0xFFFF8056 ;; writing MSLUTSEL @ address 23=0x68 with 0xFFFF8056=0=0.0
0x69 = 0x00F70000 ;; writing MSLUTSTART @ address 24=0x69 with 0x00F70000=16187392=0.0
0x6C = 0x00410153 ;; writing CHOPCONF @ address 25=0x6C with 0x00410153=4260179=0.0
0x6D = 0x00040000 ;; writing COOLCONF @ address 26=0x6D with 0x00040000=262144=0.0
0x70 = 0xC44C001E ;; writing PWMCONF @ address 27=0x70 with 0xC44C001E=0=0.0
0x74 = 0x00000000 ;; writing SG4_THRS @ address 28=0x74 with 0x00000000=0=0.0
*/
#define TMC2240_GCONF 0x00
#define TMC2240_GSTAT 0x01
#define TMC2240_IFCNT 0x02
#define TMC2240_SLAVECONF 0x03
#define TMC2240_IOIN 0x04
#define TMC2240_DRV_CONF 0x0A
#define TMC2240_GLOBAL_SCALER 0x0B
#define TMC2240_IHOLD_IRUN 0x10
#define TMC2240_TPOWERDOWN 0x11
#define TMC2240_TSTEP 0x12
#define TMC2240_TPWMTHRS 0x13
#define TMC2240_TCOOLTHRS 0x14
#define TMC2240_THIGH 0x15
#define TMC2240_DIRECT_MODE 0x2D
#define TMC2240_ENCMODE 0x38
#define TMC2240_XENC 0x39
#define TMC2240_ENC_CONST 0x3A
#define TMC2240_ENC_STATUS 0x3B
#define TMC2240_ENC_LATCH 0x3C
#define TMC2240_ADC_VSUPPLY_AIN 0x50
#define TMC2240_ADC_TEMP 0x51
#define TMC2240_OTW_OV_VTH 0x52
#define TMC2240_MSLUT0 0x60
#define TMC2240_MSLUT1 0x61
#define TMC2240_MSLUT2 0x62
#define TMC2240_MSLUT3 0x63
#define TMC2240_MSLUT4 0x64
#define TMC2240_MSLUT5 0x65
#define TMC2240_MSLUT6 0x66
#define TMC2240_MSLUT7 0x67
#define TMC2240_MSLUTSEL 0x68
#define TMC2240_MSLUTSTART 0x69
#define TMC2240_MSCNT 0x6A
#define TMC2240_MSCURACT 0x6B
#define TMC2240_CHOPCONF 0x6C
#define TMC2240_COOLCONF 0x6D
#define TMC2240_DCCTRL 0x6E
#define TMC2240_DRVSTATUS 0x6F
#define TMC2240_PWMCONF 0x70
#define TMC2240_PWMSCALE 0x71
#define TMC2240_PWM_AUTO 0x72
#define TMC2240_SG4_THRS 0x74
#define TMC2240_SG4_RESULT 0x75
#define TMC2240_SG4_IND 0x76
#define TMC2240_HIGHT_BIT 0x80
typedef enum
{
TMC2240_1,
TMC2240_MAX,
} tmc2240_index_e;
typedef enum
{
TMC2240_FORWARD, // 正转
TMC2240_BACKWARD, // 反转
} tmc2240_direction_e;
typedef enum
{
TMC2240_MRES_256,
TMC2240_MRES_128,
TMC2240_MRES_64,
TMC2240_MRES_32,
TMC2240_MRES_16,
TMC2240_MRES_8,
TMC2240_MRES_4,
TMC2240_MRES_2,
TMC2240_MRES_1, // FULL STEP
} tmc2240_mres_e;
// 0x00 GCONF
typedef union
{
uint32_t data;
struct
{
uint32_t reserved1 : 1;
/**
*
* 0x02^20
* 0x12^18
*/
uint32_t fast_standstill : 1;
/**
* StealthChop2模式
* 0x0StealthChop2
* 0x1StealthChop2电压PWM模式使能()
lHOLD =
*/
uint32_t en_pwm_mode : 1;
/**
* StealthChop2的步进输入筛选
* 0x0StealthChop2
* 0x1StealthChop2电压PWM模式使能
()
lHOLD=
*/
uint32_t multistep_filt : 1;
/**
* /
* 0x0
* 0x1
*/
uint32_t shaft : 1;
uint32_t diag0_error : 1;
uint32_t diag0_otpw : 1;
uint32_t diag0_stall : 1;
uint32_t diag1_stall : 1;
uint32_t diag1_index : 1;
uint32_t diag1_onstate : 1;
uint32_t reserved2 : 1;
uint32_t diag0_pushpull : 1;
uint32_t diag1_pushpull : 1;
uint32_t small_hysteresis : 1;
/**
*
* 0x0
* 0x1ENCA停止定序器
(
)
*/
uint32_t stop_enable : 1;
/**
* motpr相电流控制
* 0x0
* 0x1线
(0x2D)线A
(8..0)线B电流(24..16)
lHOLD设置进行定标
StealthChop2电流调节
StealthChop2电流调节仅适用于
*/
uint32_t direct_mode : 1;
} bits;
} gconf_u;
// 0x01 GSTAT
typedef union
{
uint32_t data;
struct
{
uint32_t reset : 1;
uint32_t drv_err : 1;
uint32_t uv_cp : 1;
uint32_t register_reset : 1;
uint32_t vm_uvlo : 1;
} bits;
} gstat_u;
// 0x0A DRVCONF
typedef union
{
uint32_t data;
struct
{
uint32_t current_range : 2; // 0-1
uint32_t reserved1 : 2; // 2-3
uint32_t slope_control : 2; // 4-5
} bits;
} drvconf_u;
// 0x0B GLOBAL_SCALER
typedef union
{
uint32_t data;
struct
{
uint32_t global_scale : 8; // 0-7
} bits;
} global_scaler_u;
// 0x10 IHOLD_IRUN
typedef union
{
uint32_t data;
struct
{
uint32_t ihold : 5; // 0-4
uint32_t reserved1 : 3; // 5-7
uint32_t irun : 5; // 8-12
uint32_t reserved2 : 3; // 13-15
uint32_t iholddelay : 4; // 16-19
uint32_t reserved3 : 4; // 20-23
uint32_t irundelay : 4; // 24-27
} bits;
} ihold_irun_u;
// 0x6C CHOPCONF
typedef union
{
uint32_t data;
struct
{
uint32_t toff : 4; // 0-3
uint32_t hstrt : 3; // 4-6
uint32_t hend : 4; // 7-10
uint32_t fd3 : 1; // 11
uint32_t disfdcc : 1; // 12
uint32_t reserved1 : 1;
uint32_t chm : 1; // 14
uint32_t tbl : 2; // 15-16
uint32_t reserved2 : 1;
uint32_t vhighfs : 1; // 18
uint32_t vhighchm : 1; // 19
uint32_t tpfd : 4; // 20-23
uint32_t mres : 4; // 24-27
uint32_t intpol : 1; // 28
uint32_t dedge : 1; // 29
uint32_t diss2g : 1; // 30
uint32_t diss2vs : 1; // 31
} bits;
} chopconf_u;
// 0x70 PWMCONF
typedef union
{
uint32_t data;
struct
{
/**
* PWM 0-255CS_ACTUAL=31 =30 使 PWM_OFS
* PWM_OFS pwm_autoscale 0 pwm_autoscale 1
* StealthChop2 PWM_OFS = 0 使
* PWM_OFS > 0 PWM
* IHOLD_IRUN
*/
uint32_t pwm_ofs : 8;
/**
* PWM PWM_GRAD x 256 / TSTEP PWM_OFS 使 PWM_GRAD
* PWM_GRAD pwm_autoscale 0 pwm_autoscale 1
* StealthChop2 PWM_GRAD_AUTO
*/
uint32_t pwm_grad : 8;
uint32_t pwm_freq : 2;
uint32_t pwm_autoscale : 1;
uint32_t pwm_autograd : 1;
} bits;
} pwmconf_u;
typedef struct
{
gconf_u gconf; // 0x00 GCONF
gstat_u gstat; // 0x01 GSTAT
drvconf_u drvconf; // 0x0A DRVCONF
global_scaler_u global_scaler; // 0x0B GLOBAL_SCALER
ihold_irun_u ihold_irun; // 0x10 IHOLD_IRUN
chopconf_u chopconf; // 0x6C CHOPCONF
pwmconf_u pwmconf; // 0x70 PWMCONF
} tmc2240_config_t;
typedef struct
{
gpio_t *en; ///< EN_PIN
gpio_t *dir; ///< DIR_PIN
TIM_TypeDef *timer;
uint32_t time_ch;
spi_t *spi;
tmc2240_config_t config;
tmc2240_config_t read_config;
uint32_t step;
__IO uint32_t step_count;
// PRIVATE
struct
{
uint32_t sysclk; // 系统时钟
uint32_t psc; // 预分频系数
uint16_t arr; // 自动重装值 auto reload value
uint32_t freq; // 频率
} default_tm;
struct
{
BOOL enable; // 使能
tmc2240_direction_e direction; // 方向
float32 percent; // 占空比
uint16_t arr; // 自动重装值(改变速度)
uint32_t freq; // 频率
} params;
struct
{
float32 step_angle; // 步进角度
uint16_t circle_pulse; // 一圈脉冲数
__IO int32_t add_pulse_count; /* 脉冲个数累计 */
__IO uint32_t pulse_count; /* 脉冲个数记录 */
__IO uint32_t step_angle_count; /* 步距个数 */
} motor;
struct
{
uint16_t tmc2240_adc_temp; // 温度ADC值
float32 tmc2240_temperature; // 温度
} data;
} tmc2240_t;
void tmc2240_init(tmc2240_index_e index, SPI_TypeDef *SPIx, TIM_TypeDef *timer, uint32_t time_ch, spi_gpio_group_t *gpios);
tmc2240_t *tmc2240_get(tmc2240_index_e index);
void tmc2240_motor_set_angle(tmc2240_index_e index, int32_t angle);
void tmc2240_motor_update(tmc2240_index_e index);
void tmc2240_test(tmc2240_index_e index);
void tmc2240_config_read(tmc2240_index_e index);
#endif // __TMC2240_H