#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 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,用的串口1,PA9->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); // 目标位置设为极大值 } }