This commit is contained in:
2025-06-18 09:08:17 +08:00
commit 7999439a8f
363 changed files with 313769 additions and 0 deletions

587
USER/main.c Normal file
View File

@ -0,0 +1,587 @@
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "thb6128.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "main.h"
#include "motorstat.h"
#include <math.h>
extern char USART_RX_BUF[200];
int s1=0,s2=0;
int main(void)
{
// 初始化参数
u16 t;
u16 len;
int value;
MotorStat.MoveMode = 0;
MotorStat.NmberoNow = 0;
MotorStat.NmberoTarget = 0;
MotorStat.direction = 0;
MotorStat.speed = 0;
MotorStat.acc = 0;
MotorStat.dec = 0;
MotorStat.moveflag = 0;
MotorStat.backzero = 0;
MotorStat.speedflag = 0;
// MotorStat.accflag = 0;
// MotorStat.decflag = 0;
MotorStat.Nmbertargetflag = 0;
MotorStat.set_speed = setfreq;
MotorStat.stopmove = stopmotormove;
MotorStat.max_speed = 0;
MotorStat.move_phase = -1;
MotorStat.zheng_LimitTrigger = 0;
MotorStat.fu_LimitTrigger = 0;
MotorStat.target_position = 0;
MotorStat.zero_flag = 0;
MotorStat.max_speed = 2000;
//clk应该接在有定时器的io接口上PA8 TIM3用来捕获脉冲上升沿
delay_init(); // 延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC中断分组2:2位抢占优先级2位响应优先级
uart_init(115200); // 串口初始化为 115200,用的串口1PA9->RX ,PA10->TX
STEP_MOTOR_Init();
LED_Init(); // LED端口初始化
TIM1_PWM_CH1_Init();
//TIM1_PWM_Init(999, 3599); // 分频得到20hz 。PWM频率=72000000/9999/719=100hz 有震动
TIM3_Int_Init(999, 71);
TIM2_Capture_Init();
// TIM4_Capture_Init();
EXTI_Config(); //负限位
//TIM4_Int_Init(999,7199);
TIM_SetCompare1(TIM1, 500);
Dac1_Init(); // DAC初始化
// 关闭待机,拉高
GPIO_SetBits(GPIOC, GPIO_Pin_0);
// 设置enable引脚
GPIO_ResetBits(GPIOA, GPIO_Pin_11);
// 设置细分
STEP_SUBDIVIDE(4);
// 设置电流
Dac1_Set_Vol(1500); //
printf("wellcom to my motor\r\n ");
while (1) {
if (USART_RX_STA & 0x8000) {
len = USART_RX_STA & 0x3fff; // 得到此次接收到的数据长度
for (t = 0; t < len; t++) {
USART_SendData(USART1, USART_RX_BUF[t]); // 向串口1发送数据
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET); // 等待发送结束
}
USART_RX_STA = 0;
// 解析USART_RX_BUF 格式如下
/*SET#OPEN 打开
SET#OFF 脱机
SET#EN 使能电机
SET#MOVEING 转动
SET#DRECTION#0 正向 1反向
SET#CURRENT#1 设置电流
SET#ACC#1000 设置加速度
SET#DEC#1000 设置减速度
SET#ORIGIN 设置当前位置为0
SET#BAUD_RATE#9600 设置波特率
SET#MICROSTEPPING#1 设置细分
SET#SPEED#1000 设置速度 freq=1000时为50hz
SET#TARGET#1000 设置目标速度
MOVE#TO##1000 旋转到1000这个位置
MOVE#BY##1000 旋转1000步
MOVE#ZERO 旋转到远点*/
// 先提取第一个井号前的字符串
char *p = strtok(USART_RX_BUF, "#");
if (strcmp(p, "SET") == 0) {
// 提取第二个井号前的字符串
p = strtok(NULL, "#");
if (strcmp(p, "OPEN") == 0) {
// 打开
STEP_MOTOR_OPEN();
printf("OPEN\r\n");
}
if (strcmp(p, "OFF") == 0) {
// 脱机
STEP_MOTOR_OFF();
printf("OFF\r\n");
}
if (strcmp(p, "EN") == 0) {
// 使能电机
STEP_MOTOR_EN();
printf("EN\r\n");
}
// if (strcmp(p, "SET#CLEAR") == 0) {
// // 使能电机
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, DISABLE); //时钟使能
// printf("CLEAR\r\n");
// }
// if (strcmp(p, "MOVEING") == 0) {
// // 转动
// STEP_MOTOR_FORWARD();
// printf("MOVEING\r\n");
// }
if (strcmp(p, "ZERO") == 0) {
//设置当前位置为0
MotorStat.NmberoNow=0;
stopmotormove();
printf("ZERO\r\n");
}
if (strcmp(p, "DRECTION") == 0) {
// 转动
p = strtok(NULL, "#");
if (strcmp(p, "0") == 0) {
// 正向
STEP_MOTOR_FORWARD();
printf("DRECTION FORWARD\r\n");
}
if (strcmp(p, "1") == 0) {
// 反向
STEP_MOTOR_BACKWARD();
printf("DRECTION BACKWARD\r\n");
}
}
if (strcmp(p, "CURRENT") == 0) {
// 设置电流
p = strtok(NULL, "#");
value = atoi(p);
if(value<=3000)
{
set_CurrentValue(value);
printf("CURRENT %d\r\n", value);
}
else
printf("CURRENT OVER");
}
if (strcmp(p, "DEC") == 0) {
// 设置减速度
TIM5_Int_Init(999, 71);
p = strtok(NULL, "#");
value = atoi(p);
MotorStat.decel = value;
//MotorStat.dec=value;
// MotorStat.speedflag=1;
// MotorStat.decflag=1;
printf("DEC %d\r\n", value);
}
if (strcmp(p, "ACC") == 0) {
// 设置加速度
TIM5_Int_Init(999, 71);
p = strtok(NULL, "#");
value = atoi(p);
MotorStat.accel = value;
//MotorStat.acc=value;
// MotorStat.speedflag=1;
// MotorStat.accflag=1;
printf("ACC %d\r\n", value);
}
if (strcmp(p, "MICROSTEPPING") == 0) {
p = strtok(NULL, "#");
value = atoi(p);
STEP_SUBDIVIDE(value);
printf("MICROSTEPPING %d\r\n", value);
}
if (strcmp(p, "SPEED") == 0) {
p = strtok(NULL, "#");
value = atoi(p);
setfreq(value);
MotorStat.speed=value;
}
if (strcmp(p, "TARGET") == 0) { //max_speed
p = strtok(NULL, "#");
value = atoi(p);
MotorStat.max_speed = value; // 最大1000 steps/s
//MotorStat.Targetspeed=value;
printf("TARGET %d\r\n", value);
}
if (strcmp(p, "BAUD_RATE") == 0) {
p = strtok(NULL, "#");
value = atoi(p);
USART_Cmd(USART1, DISABLE);
uart_init(value);
}
} else if (strcmp(p, "MOVE") == 0) {
// 提取第二个井号前的字符串
p = strtok(NULL, "#");
if (strcmp(p, "TO") == 0) {
// 旋转到
p = strtok(NULL, "#");
value = atoi(p);
moveto(value);
printf("MOVE TO %d\r\n", value);
}
if (strcmp(p, "BY") == 0) {
// 旋转了
p = strtok(NULL, "#");
value = atoi(p);
MotorStat.NmberoTarget=value;
moveby();
printf("MOVE BY %d\r\n", value);
}
if (strcmp(p, "ZERO") == 0) {
// 旋转到负极限,归零
movetozero();
printf("MOVE TO ZERO\r\n");
}
if (strcmp(p, "INFO") == 0) {
// 获取当前信息(状态,位置,速度)
// if ( MotorStat.zero_flag == 1 && MotorStat.fu_LimitTrigger == 1){
// printf("Stats: %d, Pos: 0, Speed: %.1f\r\n", MotorStat.move_phase, MotorStat.current_speed);
// }
// else{
printf(" Stats: %d, Pos: %d, Speed: %.1f\r\n", MotorStat.move_phase, MotorStat.NmberoNow, MotorStat.current_speed);
// printf("fu : %d\r\n", MotorStat.fu_LimitTrigger);
// printf("GPIO : %d\r\n", GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6 ));
//}
}
}
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
}
// switch_fan();
// switch_zheng();
}
}
void moveby(void)
{
MotorStat.MoveMode=1;
MotorStat.moveflag = 1;
if(MotorStat.NmberoTarget>0){
GPIO_ResetBits(GPIOA, GPIO_Pin_12);//正转NmberoTarget个脉冲
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
GPIO_SetBits(GPIOA, GPIO_Pin_11);
MotorStat.direction=0;
printf("zhengzhuan\r\n");
}
if(MotorStat.NmberoTarget<0){
GPIO_SetBits(GPIOA,GPIO_Pin_12);//反转
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
GPIO_SetBits(GPIOA, GPIO_Pin_11);
MotorStat.direction=1;
printf("fan\r\n");
}
}
void moveto(int target)
{
stopmotormove();
MotorStat.target_position = target; // 保存目标位置到结构体
if (MotorStat.NmberoNow == target && MotorStat.zero_flag == 0) {
stopmotormove();
printf("Already at target: %d\r\n", target);
return;
}
int steps = target - MotorStat.NmberoNow;
// 运动参数设置
MotorStat.total_steps = abs(steps);
MotorStat.direction = (steps > 0) ? 0 : 1;
// 计算梯形曲线参数
double max_reachable_speed = sqrt(1.0* (2 * MotorStat.accel * MotorStat.total_steps));
MotorStat.max_speed = (max_reachable_speed < MotorStat.max_speed) ?
max_reachable_speed : MotorStat.max_speed;
MotorStat.accel_steps = (MotorStat.max_speed * MotorStat.max_speed) / (2 * MotorStat.accel);
MotorStat.decel_steps = (MotorStat.max_speed * MotorStat.max_speed) / (2 * MotorStat.decel);
if(MotorStat.accel_steps + MotorStat.decel_steps <= MotorStat.total_steps){
MotorStat.const_steps = MotorStat.total_steps - MotorStat.accel_steps - MotorStat.decel_steps;
} else {
MotorStat.accel_steps = MotorStat.total_steps * MotorStat.decel / (MotorStat.accel + MotorStat.decel);
MotorStat.decel_steps = MotorStat.total_steps - MotorStat.accel_steps;
MotorStat.const_steps = 0;
}
// 初始化运动参数
MotorStat.NmberoTarget = MotorStat.total_steps;
MotorStat.MoveMode = 1;
MotorStat.step_counter = 0;
MotorStat.current_speed = 0;
MotorStat.move_phase = 0;
MotorStat.moveflag = 1;
MotorStat.speedflag = 1;
if (MotorStat.direction == 0)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_12);
}
else
{
GPIO_SetBits(GPIOA, GPIO_Pin_12);
}
// 启动定时器和电机
GPIO_SetBits(GPIOA, GPIO_Pin_11);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
}
//void moveto(void)
//{
// if(MotorStat.NmberoNow>0)
// {
// GPIO_SetBits(GPIOA,GPIO_Pin_12);//反转
// MotorStat.direction=1;
// }
// else if(MotorStat.NmberoNow<0)
// {
// GPIO_ResetBits(GPIOA,GPIO_Pin_12);
// MotorStat.direction=0;
// }
// MotorStat.backzero = 1;
// if(MotorStat.NmberoNow==0)
// {
// stopmotormove();
// printf("already at zero\r\n");
// }
//}
void stopmotormove(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_11);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, DISABLE);
MotorStat.moveflag = 0;
MotorStat.step_counter = 0; // 重置步数计数器
MotorStat.current_speed = 0;
}
void setfreq(int freq)
{
uint32_t timer_clk = 72000000; // TIM1 时钟频率
uint32_t arr;
uint16_t psc = 0; // 预分频值,默认 0即不分频
if (freq <= 0)
{
TIM_Cmd(TIM1, DISABLE);
return;
}
// 计算初始 ARR 值PSC = 0
arr = (timer_clk / freq) - 1;
// 如果 ARR 超过 16 位65535增加预分频值直到 ARR 适配
while (arr > 65535 && psc < 65535)
{
psc++;
arr = (timer_clk / (freq * (psc))) - 1;
}
if (arr > 65535)
{
return;
}
TIM_Cmd(TIM1, DISABLE);
TIM_ARRPreloadConfig(TIM1, DISABLE);
TIM1->PSC = psc; // 设置新的预分频值
TIM1->ARR = arr;
TIM1->CCR1 = arr / 2; // 50% 占空比
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
// printf("Freq = %d Hz, ARR = %u, PSC = %u\r\n", freq, arr, psc);
// printf("Freq = %d Hz\r\n", freq);
}
void setgpiovalue(GPIO_TypeDef *GPIOx, int pinnumber, int vlue)
{
if (vlue == 0) {
GPIO_ResetBits(GPIOx, pinnumber);
} else {
GPIO_SetBits(GPIOx, pinnumber);
}
}
//void STEP_SUBDIVIDE(int divide)
//{ // 设置细分
// setgpiovalue(GPIOB, GPIO_Pin_13, divide & 0x01); /// 0
// setgpiovalue(GPIOB, GPIO_Pin_14, divide >> 1 & 0x01); // 1
// setgpiovalue(GPIOB, GPIO_Pin_15, divide >> 2 & 0x01); // 0
//}
void STEP_SUBDIVIDE(int divide)// 设置细分
{
// 设置细分
switch (divide) {
case 1:
setgpiovalue(GPIOB, GPIO_Pin_13, 0); // LLL
setgpiovalue(GPIOB, GPIO_Pin_14, 0);
setgpiovalue(GPIOB, GPIO_Pin_15, 0);
break;
case 2:
setgpiovalue(GPIOB, GPIO_Pin_13, 1); // HLL
setgpiovalue(GPIOB, GPIO_Pin_14, 0);
setgpiovalue(GPIOB, GPIO_Pin_15, 0);
break;
case 4:
setgpiovalue(GPIOB, GPIO_Pin_13, 0); // LHL
setgpiovalue(GPIOB, GPIO_Pin_14, 1);
setgpiovalue(GPIOB, GPIO_Pin_15, 0);
break;
case 8:
setgpiovalue(GPIOB, GPIO_Pin_13, 1); // HHL
setgpiovalue(GPIOB, GPIO_Pin_14, 1);
setgpiovalue(GPIOB, GPIO_Pin_15, 0);
break;
case 16:
setgpiovalue(GPIOB, GPIO_Pin_13, 0); // LLH
setgpiovalue(GPIOB, GPIO_Pin_14, 0);
setgpiovalue(GPIOB, GPIO_Pin_15, 1);
break;
case 32:
setgpiovalue(GPIOB, GPIO_Pin_13, 1); // HLH
setgpiovalue(GPIOB, GPIO_Pin_14, 1);
setgpiovalue(GPIOB, GPIO_Pin_15, 0);
break;
case 64:
setgpiovalue(GPIOB, GPIO_Pin_13, 0); // LHH
setgpiovalue(GPIOB, GPIO_Pin_14, 1);
setgpiovalue(GPIOB, GPIO_Pin_15, 1);
break;
case 128:
setgpiovalue(GPIOB, GPIO_Pin_13, 1); // HHH
setgpiovalue(GPIOB, GPIO_Pin_14, 1);
setgpiovalue(GPIOB, GPIO_Pin_15, 1);
break;
default:
printf("Error value: %d\r\n", divide);
break;
}
// printf("xifen = %d, %d %d %d \r\n", divide, GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13), GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14), GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15));
}
void set_CurrentValue(int value) // 设置电流
{
Dac1_Set_Vol(value);
}
void switch_zheng (void) //脱机
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==1&&s1==0) //PB6 1 -->极限
{
GPIO_ResetBits(GPIOA,GPIO_Pin_12); //正转
MotorStat.direction=0;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, DISABLE);
printf("already close & zheng\r\n");
GPIO_ResetBits(GPIOA,GPIO_Pin_11);
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)==1&&s1!=0)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_12); //,一定要注意初始化将函数提前声明将PA12拉低正转
MotorStat.direction=0;
GPIO_SetBits(GPIOA,GPIO_Pin_11);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
s1++;
printf("s%d \r\n",s1);
if(s1==500)
s1=0;
}
}
void switch_fan(void) //脱机
{
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1&&s2==0) //PA0 1 -->极限
{
GPIO_SetBits(GPIOA,GPIO_Pin_12); //将PA12拉高反转
MotorStat.direction=1;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, DISABLE);
printf("already close & fan\r\n");
GPIO_ResetBits(GPIOA,GPIO_Pin_11);
}
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1&&s2!=0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_11);
GPIO_SetBits(GPIOA,GPIO_Pin_12); //将PA12拉高反转
MotorStat.direction=1;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
s2++;
printf(" s%d \r\n",s2);
if(s2==500)
s2=0;
}
}
//float pulse_to_distance(int pulse_count) {
// const float pulse_distance = 0.0046; // 每个脉冲对应的位移 (mm)
// return pulse_count * pulse_distance;
//}
//bool is_reached_target(int pulse_count, float target_distance) {
// const float pulse_distance = 0.0046;
// float current_distance = pulse_count * pulse_distance;
// return fabs(current_distance - target_distance) < 0.001; // 允许一定的误差范围
//}
void movetozero(void) {
// MotorStat.fu_LimitTrigger = 0;
// 启动归零流程
MotorStat.zero_flag = 1;
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6 ) ==1) {
stopmotormove();
MotorStat.NmberoNow = 0;
}
// 持续向负极限方向移动
if(MotorStat.zero_flag == 1 && GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6 ) ==0) {
moveto(-6666); // 目标位置设为极大值
}
}