步进电机驱动完成

This commit is contained in:
许晟昊 2024-12-24 15:12:22 +08:00
parent e4a9aff8b3
commit 7ac6baf560
11 changed files with 1501 additions and 1359 deletions

View File

@ -257,9 +257,13 @@ void TIM3_IRQHandler(void)
/* USER CODE END TIM3_IRQn 0 */
/* USER CODE BEGIN TIM3_IRQn 1 */
if (IS_TIM_IT_FLAG(TIM3))
if (IS_TIM_IT_FLAG(TMC2240_TIM))
{
TIM_IRQ_HANDLER(TIM3);
if (LL_TIM_IsActiveFlag_CC3(TMC2240_TIM))
{
tmc2240_motor_update(TMC2240_1);
}
TIM_IRQ_HANDLER(TMC2240_TIM);
}
/* USER CODE END TIM3_IRQn 1 */
}

View File

@ -75,7 +75,7 @@ void MX_TIM3_Init(void)
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
/* TIM3 interrupt Init */
NVIC_SetPriority(TIM3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),3, 0));
NVIC_SetPriority(TIM3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_Init 1 */
@ -86,8 +86,7 @@ void MX_TIM3_Init(void)
TIM_InitStruct.Autoreload = 1000;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_EnableARRPreload(TIM3);
LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_DisableARRPreload(TIM3);
LL_TIM_OC_EnablePreload(TIM3, LL_TIM_CHANNEL_CH3);
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;

View File

@ -148,24 +148,7 @@
<Name></Name>
</SetRegEntry>
</TargetDriverDllRegistry>
<Breakpoint>
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>262</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>134224768</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>../Core/Src/stm32f1xx_it.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\motor\../Core/Src/stm32f1xx_it.c\262</Expression>
</Bp>
</Breakpoint>
<Breakpoint/>
<WatchWindow1>
<Ww>
<count>0</count>
@ -175,37 +158,7 @@
<Ww>
<count>1</count>
<WinNumber>1</WinNumber>
<ItemText>tmc,0x0A</ItemText>
</Ww>
<Ww>
<count>2</count>
<WinNumber>1</WinNumber>
<ItemText>wdata</ItemText>
</Ww>
<Ww>
<count>3</count>
<WinNumber>1</WinNumber>
<ItemText>rdata</ItemText>
</Ww>
<Ww>
<count>4</count>
<WinNumber>1</WinNumber>
<ItemText>TMC2240_B_CURRENT</ItemText>
</Ww>
<Ww>
<count>5</count>
<WinNumber>1</WinNumber>
<ItemText>rdata</ItemText>
</Ww>
<Ww>
<count>6</count>
<WinNumber>1</WinNumber>
<ItemText>vel,0x0A</ItemText>
</Ww>
<Ww>
<count>7</count>
<WinNumber>1</WinNumber>
<ItemText>0x03E8,0x0A</ItemText>
<ItemText>app,0x0A</ItemText>
</Ww>
</WatchWindow1>
<MemoryWindow1>
@ -283,7 +236,7 @@
<Group>
<GroupName>Application/User/Core</GroupName>
<tvExp>0</tvExp>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
@ -395,7 +348,7 @@
<Group>
<GroupName>User/application</GroupName>
<tvExp>0</tvExp>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,12 @@ static uint8_t business_inspection(struct flow *fl)
FL_HEAD(fl);
for (;;)
{
tmc2240_process(TMC2240_1);
if (app.angel != 0)
{
tmc2240_motor_set_angle(TMC2240_1, app.angel);
app.angel = 0;
}
FL_LOCK_DELAY(fl, FL_CLOCK_SEC);
}
FL_TAIL(fl);
@ -35,6 +40,7 @@ static uint8_t idle_inspection(struct flow *fl)
{
GPIO_TOGGLE(LED_BLUE_GPIO_Port, LED_BLUE_Pin);
tmc2240_config_read(TMC2240_1);
tmc2240_process(TMC2240_1);
ssd1306_f6x8_string(0, 2, " tick:");
ssd1306_f6x8_number(40, 2, tick++, 0);
ssd1306_f6x8_string(0, 4, " cfg:");
@ -78,6 +84,6 @@ void app_init(void)
FL_INIT(&idle_fw); // 空闲任务
ENABLE_TIM(TASK_TIM);
ENABLE_TIM(TMC2240_TIM);
ssd1306_clear();
}

View File

@ -11,6 +11,7 @@
typedef struct
{
int32_t angel;
} app_t;
extern app_t app;

View File

@ -49,9 +49,8 @@ void board_init(void)
gpios.miso = gpio_create(TMC2240_MISO_GPIO_Port, TMC2240_MISO_Pin);
gpios.rst = gpio_create(NULL, 0);
gpios.rdy = gpio_create(NULL, 0);
tmc2240_init(TMC2240_1, SPI1, TIM3, LL_TIM_CHANNEL_CH3, &gpios);
tmc2240_init(TMC2240_1, SPI1, TMC2240_TIM, TMC2240_TIM_CH3, &gpios);
tmc2240_get(TMC2240_1)->en = gpio_create(TMC2240_EN_GPIO_Port, TMC2240_EN_Pin);
tmc2240_get(TMC2240_1)->dir = gpio_create(TMC2240_DIR_GPIO_Port, TMC2240_DIR_Pin);
tmc2240_get(TMC2240_1)->params.enable = TRUE;
}
}

View File

@ -7,7 +7,8 @@
#define UART_TXSIZE (240u) // 发送240个字节
#define TASK_TIM TIM1
#define TMC2240_TIM TIM3
#define TMC2240_TIM_CH3 LL_TIM_CHANNEL_CH3
typedef struct
{
/* data */

View File

@ -89,11 +89,16 @@ static void tmc2240_config_write(tmc2240_index_e index)
tmc->config.gconf.data = 0x00000000;
tmc->config.chopconf.data = 0x00410153;
tmc->config.chopconf.bits.mres = TMC2240_MRES_8;
tmc->config.chopconf.bits.mres = TMC2240_MRES_1;
tmc->config.drvconf.data = 0x00000021;
tmc->config.global_scaler.data = 0x00000000;
tmc->config.ihold_irun.data = 0x00071f1f;
tmc->config.ihold_irun.bits.ihold = 2;
tmc->config.ihold_irun.bits.irun = 16;
tmc->config.ihold_irun.bits.iholddelay = 5;
tmc->config.ihold_irun.bits.irundelay = 5;
tmc->config.pwmconf.data = 0xC44C261E;
tmc->config.gstat.data = 0x00000007;
tmc2240_reg_write(index, TMC2240_GCONF, tmc->config.gconf.data);
@ -105,21 +110,75 @@ static void tmc2240_config_write(tmc2240_index_e index)
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)
{
tmc->en->reset(*tmc->en);
PWM_START(tmc->timer, tmc->time_ch);
tmc->en->reset(*tmc->en);
tmc2240_reg_write(index, TMC2240_CHOPCONF, tmc->config.chopconf.data);
}
else
{
tmc->en->set(*tmc->en);
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);
}
}
@ -143,12 +202,12 @@ void tmc2240_init(tmc2240_index_e index, SPI_TypeDef *SPIx, TIM_TypeDef *timer,
{
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);
osel_memset((uint8_t *)&tmc->config, 0, sizeof(tmc2240_config_t));
osel_memset((uint8_t *)&tmc->read_config, 0, sizeof(tmc2240_config_t));
tmc->spi->interface.hardware_enable(tmc->spi, SPIx);
{
tmc->default_tm.sysclk = SystemCoreClock / 1000;
@ -162,6 +221,7 @@ void tmc2240_init(tmc2240_index_e index, SPI_TypeDef *SPIx, TIM_TypeDef *timer,
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)
@ -203,17 +263,82 @@ void tmc2240_process(tmc2240_index_e index)
DBG_ASSERT(tmc != NULL __DBG_LINE);
_tmc2240_enable(index, tmc->params.enable);
_tmc2240_direction(index, tmc->params.direction);
if (PWM_GET_ARR(tmc->timer) != tmc->params.arr)
if (tmc->params.enable == TRUE)
{
if (tmc->params.arr == 0)
_tmc2240_direction(index, tmc->params.direction);
if (PWM_GET_ARR(tmc->timer) != tmc->params.arr)
{
tmc->params.arr = tmc->default_tm.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);
}
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;
}
tmc2240_percent(index, tmc->params.percent);
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_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);
}
}

View File

@ -5,6 +5,7 @@
* @version 0.1
* @note
* 1. VM需要供电SPI无法正常通信
* 2. 421.812001/81=0.2251600
*/
#ifndef __TMC2240_H
@ -12,6 +13,7 @@
#include "main.h"
#include "spis.h"
#define MOTOR_42_STEP_ANGLE 1.8f // 42步进电机每步1.8度
#define TMC2240_PWM_DUTY_DEFAULT 50 // PWM默认占空比
/*
@ -327,30 +329,44 @@ typedef struct
// PRIVATE
struct
{
uint32_t sysclk;
uint32_t psc; // 预分频系数
uint16_t arr; // 自动重装值 auto reload value
uint32_t freq;
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;
BOOL enable; // 使能
tmc2240_direction_e direction; // 方向
float32 percent; // 占空比
uint16_t arr; // 自动重装值(改变速度)
uint32_t freq; // 频率
} params;
struct
{
uint16_t tmc2240_adc_temp;
float32 tmc2240_temperature;
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_process(tmc2240_index_e index);
void tmc2240_config_read(tmc2240_index_e index);
#endif // __TMC2240_H

View File

@ -49,7 +49,6 @@ Mcu.Pin14=PA13
Mcu.Pin15=PA14
Mcu.Pin16=VP_SYS_VS_Systick
Mcu.Pin17=VP_TIM1_VS_ClockSourceINT
Mcu.Pin18=VP_TIM3_VS_ClockSourceINT
Mcu.Pin2=PD1-OSC_OUT
Mcu.Pin3=PA3
Mcu.Pin4=PA4
@ -58,7 +57,7 @@ Mcu.Pin6=PA6
Mcu.Pin7=PA7
Mcu.Pin8=PB0
Mcu.Pin9=PB1
Mcu.PinsNb=19
Mcu.PinsNb=18
Mcu.ThirdParty0=RealThread.RT-Thread.3.1.5
Mcu.ThirdPartyNb=1
Mcu.UserConstants=
@ -78,7 +77,7 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:false
NVIC.TIM1_UP_IRQn=true\:3\:0\:true\:false\:true\:true\:true\:true
NVIC.TIM3_IRQn=true\:3\:0\:true\:false\:true\:true\:true\:true
NVIC.TIM3_IRQn=true\:0\:0\:true\:false\:true\:true\:true\:true
NVIC.USART1_IRQn=true\:5\:0\:true\:false\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA10.Mode=Asynchronous
@ -212,7 +211,7 @@ SPI1.VirtualType=VM_MASTER
TIM1.IPParameters=Prescaler,Period
TIM1.Period=99
TIM1.Prescaler=7199
TIM3.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
TIM3.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_DISABLE
TIM3.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
TIM3.IPParameters=Prescaler,Period,Channel-PWM Generation3 CH3,AutoReloadPreload
TIM3.Period=1000
@ -223,6 +222,4 @@ VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
VP_TIM1_VS_ClockSourceINT.Mode=Internal
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
VP_TIM3_VS_ClockSourceINT.Mode=Internal
VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT
board=custom