RUN__IT # 03 一个有符号整数,将每位上的数字进行反转

本文介绍了一个Python函数,用于反转32位有符号整数的每一位数字。该函数考虑了整数的正负号,并检查了反转后的整数是否在32位有符号整数的范围内,以避免溢出。

有方法的可以留言学习!

"""
给出一个32位的有符号整数,你需要将这个整数中每位上的数字进行反转
如:
输入:123
输出:321

输入:-123
输出:-321

输入:120
输出:21
假设我们的环境只能存储32位有符号整数,则其数值范围在(-2^31,2^31-1),如果反转后整数溢出,就返回0.
"""


def reversal(num):
    """整数反转"""
    if num <= 2 ** 31 - 1 and num >= -2 ** 31:
        str1 = str()
        if num < 0:
            num = str(abs(num))
            for i in num:
                str1 = i + str1
            return -int(str1)
        else:
            num = str(abs(num))
            for i in num:
                str1 = i + str1
            return int(str1)
    else:
        return 0


if __name__ == '__main__':
    num = -120340
    print(reversal(num))
我用USART2,PA2PA3引脚,/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file usart.c * @brief This file provides code for the configuration * of the USART instances. ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "usart.h" /* USER CODE BEGIN 0 */ #include <string.h> #include <stdio.h> /* USER CODE END 0 */ UART_HandleTypeDef huart2; /* USART2 init function */ void MX_USART2_UART_Init(void) { /* USER CODE BEGIN USART2_Init 0 */ /* USER CODE END USART2_Init 0 */ /* USER CODE BEGIN USART2_Init 1 */ /* USER CODE END USART2_Init 1 */ huart2.Instance = USART2; huart2.Init.BaudRate = 9600; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART2_Init 2 */ /* USER CODE END USART2_Init 2 */ } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 */ /* USART2 clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN USART2_MspInit 1 */ /* USER CODE END USART2_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspDeInit 0 */ /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); /* USER CODE BEGIN USART2_MspDeInit 1 */ /* USER CODE END USART2_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ 这是我的串口通讯设置,/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "i2c.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "OLED.h" #include <stdio.h> #include "Delay.h" #include <math.h> // 用于fabs函数(浮点数绝对值) #include <stdlib.h> // 用于abs函数整数绝对值) #include <string.h> // 新增:用于字符串处理 uint32_t loop_count = 0; uint8_t running = 0; uint8_t direction = 1; // 1 正转,0 反转 void Motor_SetSpeed(uint32_t freq); void Motor_RunSteps(uint32_t steps); #define MOTOR_FREQ 3200 //点动速度3200 //持续运动的定义代码 #define MOTOR_FREQ_START 500 // 起始频率(Hz) #define MOTOR_FREQ_TARGET 2000 // 匀速目标频率(Hz) #define MOTOR_ACCEL_STEP 100 // 每步加速的频率增量 #define MOTOR_ACCEL_DELAY 30 // 每级加速之间的延时(ms) #define MOTOR_DECEL_STEP 100 // 每步减速的频率降量 #define MOTOR_DECEL_DELAY 30 // 每级减速之间的延时(ms) #define MOTOR_RUN_TIME 2000 // 匀速运行时间(ms) //循环1000次的定义 #define PULSES_PER_MOVE 3200 #define CYCLE_TIMES 1000 volatile uint32_t pulse_count = 0; // 中断脉冲计数 uint16_t cycle_count = 0; // 正反转循环次数 uint8_t cycle_running = 0; // 循环运行状态:0停止,1运行 uint8_t current_dir = 0; // 当前方向 0反转,1正转 #define DIR_PIN GPIO_PIN_1 #define DIR_PORT GPIOA //增加次数和移动距离的定义 // 增加变量定义 // 动态变量,初始值 uint32_t pulses_per_move = 640; // 初始对应5mm,具体根据你的脉冲/mm计算调整 uint32_t cycle_times = 1000; // 初始循环次数 uint32_t spped = 10; // 按键状态,避免连发 uint8_t last_PA9_state = 1; // 上次PA9状态,1表示未按下,0表示按下 uint8_t last_PA11_state = 1; // 上次PA11状态,1表示未按下,0表示按下 uint8_t last_PA15_state = 1; // 上次PA15状态,1表示未按下,0表示按下 uint8_t last_PA10_state =1; // 上次PA10状态,1表示未按下,0表示按下 uint8_t last_PB3_state =1; // 上次PB3状态,1表示未按下,0表示按下 uint8_t last_PB5_state =1; // 上次PB5状态,1表示未按下,0表示按下 uint8_t last_PB14_state =1; // 上次PB14状态,1表示未按下,0表示按下 //显示屏定义 volatile uint8_t need_display_update = 0; // OLED是否需要刷新 volatile uint32_t pulse_counter = 0; // 当前脉冲计数,用于显示 #define FAULT_PINS (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6) // A4/A5/A6故障引脚组合 uint8_t fault_triggered = 0; // 故障触发标志:0无故障,1故障触发(A4/A5/A6断开) uint8_t fault_processed = 0; // 故障处理标志:0未处理,1已处理(避免重复处理) uint8_t fault_active = 0; // 实时故障状态:0正常,1故障(断开) // 编码器相关变量 int32_t encoder_absolute = 0; // 32位绝对计数(支持正负值) uint16_t encoder_last = 0; // 上一次的TIM1计数值 uint16_t encoder_current = 0; // 当前的TIM1计数值 #define ENCODER_PPR 3200.0f // 1圈脉冲数 #define LEAD 5.0f // 导程(mm/圈) #define CALIBRATION 0.8015f // 校准系数(根据实际调整) double encoder_distance = 0.00; // 带2位小数的距离 /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ //点动控制 void Motor_Start(uint8_t dir) { if(dir) HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); else HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); uint32_t timer_clock = 1000000; // 1MHz 计数频率,与你定时器预分频相关 uint32_t arr = (timer_clock / MOTOR_FREQ) - 1; __HAL_TIM_SET_AUTORELOAD(&htim2, arr); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, (arr + 1) / 2); // 50% 占空比 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); } //循环 //方向控制 void Motor_SetDirection(uint8_t dir) { if (dir) HAL_GPIO_WritePin(DIR_PORT, DIR_PIN, GPIO_PIN_SET); else HAL_GPIO_WritePin(DIR_PORT, DIR_PIN, GPIO_PIN_RESET); } //速度 void Motor_StartPWM(uint32_t freq) { uint32_t timer_clock = 1000000; // 1MHz uint32_t arr = (timer_clock / freq) - 1; __HAL_TIM_SET_AUTORELOAD(&htim2, arr); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, (arr + 1) / 2); __HAL_TIM_SET_COUNTER(&htim2, 0); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); HAL_TIM_Base_Start_IT(&htim2); // 启用中断计数 } //停止程序 void Motor_StopPWM(void) { HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1); HAL_TIM_Base_Stop_IT(&htim2); } // TIM2中断回调 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { pulse_count++; need_display_update = 1; } } #define ACCEL_RATIO 0.1 // 加速段占比(10%) #define DECEL_RATIO 0.1 // 减速段占比(10%) uint32_t FREQ_MAX = 1500; // 匀速段目标频率(动态计算) // 主运行函数:含加速-匀速-减速,故障时走完当前单次运行 void Motor_Run_One_Direction(void) { uint16_t freq; uint32_t target_pulse = 0; // 计算各段脉冲数(单次移动总脉冲数=pulses_per_move) uint32_t ACCEL_PULSES = (uint32_t)(pulses_per_move * ACCEL_RATIO); uint32_t DECEL_PULSES = (uint32_t)(pulses_per_move * DECEL_RATIO); uint32_t CONST_PULSES = pulses_per_move - ACCEL_PULSES - DECEL_PULSES; // 动态计算最大频率(根据速度和单次脉冲数) uint32_t FREQ_MIN = 1000; // 起始频率固定 float compensation = 1.02; // 补偿系数(原代码逻辑保留) FREQ_MAX = (pulses_per_move * spped * 2) / 60; FREQ_MAX = FREQ_MAX * compensation; // 补偿加减速时间损耗 // -------------------------- 加速段 -------------------------- for (uint32_t i = 0; i < ACCEL_PULSES; i++) { // PB6紧急停止或循环停止:中途终止(保留原功能) if (!cycle_running || HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_RESET) { Motor_StopPWM(); return; } // // 故障触发时不中途停止,继续走完当前段 // if (fault_triggered) {} // 计算当前频率(线性加速) freq = FREQ_MIN + ((FREQ_MAX - FREQ_MIN) * i) / ACCEL_PULSES; Motor_StartPWM(freq); // 等待当前脉冲完成 target_pulse = pulse_count + 1; while (pulse_count < target_pulse) { if (!cycle_running || HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_RESET) { Motor_StopPWM(); return; } } } // -------------------------- 匀速段 -------------------------- for (uint32_t i = 0; i < CONST_PULSES; i++) { // PB6紧急停止或循环停止:中途终止 if (!cycle_running || HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_RESET) { Motor_StopPWM(); return; } // // 故障触发时不中途停止 // if (fault_triggered) {} Motor_StartPWM(FREQ_MAX); // 等待当前脉冲完成 target_pulse = pulse_count + 1; while (pulse_count < target_pulse) { if (!cycle_running || HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_RESET) { Motor_StopPWM(); return; } } } // -------------------------- 减速段 -------------------------- for (uint32_t i = 0; i < DECEL_PULSES; i++) { // PB6紧急停止或循环停止:中途终止 if (!cycle_running || HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_RESET) { Motor_StopPWM(); return; } // // 故障触发时不中途停止 // if (fault_triggered) {} // 计算当前频率(线性减速) freq = FREQ_MAX - ((FREQ_MAX - FREQ_MIN) * i) / DECEL_PULSES; Motor_StartPWM(freq); // 等待当前脉冲完成 target_pulse = pulse_count + 1; while (pulse_count < target_pulse) { if (!cycle_running || HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_RESET) { Motor_StopPWM(); return; } } } Motor_StopPWM(); // 单次运行结束后停止PWM } // 更新编码器绝对位置(核心函数) void Encoder_UpdateAbsolute(void) { int16_t diff; // 前后两次的差值(16位有符号) // 读取当前计数值 encoder_current = __HAL_TIM_GET_COUNTER(&htim1); // 计算差值(处理16位溢出) diff = encoder_current - encoder_last; // 若差值超过32767(16位有符号最大值),说明是负溢出(反转) if (diff > 32767) { diff -= 65536; // 修正为负值(如65535→0,实际差值是-1) } // 若差值小于-32768,说明是正溢出(正转) else if (diff < -32768) { diff += 65536; // 修正为正值(如0→65535,实际差值是+65535) } // 更新绝对位置 encoder_absolute += diff; // 保存当前值作为下一次的“上一次值” encoder_last = encoder_current; } uint8_t last_PB1_state = 1; // PB1上次状态(1=未按下,0=按下) uint8_t last_PB10_state = 1; // PB10上次状态 uint8_t single_move_running = 0; // 单次移动状态标记 #define SINGLE_MOVE_PULSES 320 // 0.5mm对应的脉冲数 float total_dist = 0.0f; // 累计移动距离(mm),正转+1,反转-1,初始为0 void Motor_SingleMove1mm(uint8_t dir) { if (single_move_running) return; // 防止重复触发 single_move_running = 1; // 标记移动中 // 设置方向 Motor_SetDirection(dir); // 设置匀速频率(基于当前速度参数) float compensation = 1.02; uint32_t move_freq = (SINGLE_MOVE_PULSES * spped * 2) / 60 * compensation; if (move_freq < 500) move_freq = 500; // 最低频率限制 if (move_freq > 3000) move_freq = 3000; // 最高频率限制 // 启动PWM并计数脉冲 pulse_count = 0; Motor_StartPWM(move_freq); // 等待达到目标脉冲数(320 = 0.5mm) while (pulse_count < SINGLE_MOVE_PULSES); // 移动完成,停止电机 Motor_StopPWM(); if (dir == 1) // dir=1:正转 total_dist += 1.0f; else // dir=0:反转 total_dist -= 1.0f; single_move_running = 0; // 清除移动状态 } /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM2_Init(); MX_I2C1_Init(); MX_TIM1_Init(); MX_USART2_UART_Init(); /* USER CODE BEGIN 2 */ Motor_StopPWM();// 确保电机停止 // 初始化OLED OLED_Init(); // 初始化显示屏 // === OLED 初始界面清屏与初始化显示 === OLED_Clear(); OLED_ShowString(1, 1, "Dist:"); OLED_ShowNum(1, 6, 0, 2); OLED_ShowString(2, 1, "Cycle:"); OLED_ShowNum(2, 7, 0, 5); OLED_ShowString(3, 1, "Len:"); OLED_ShowString(3, 8, "spped:"); HAL_TIM_Encoder_Start(&htim1, TIM_CHANNEL_1 | TIM_CHANNEL_2); // 必须启动,否则计数值为0 #define ENCODER_PULSES_PER_REV 3200 // 假设编码器一圈3200脉冲,需根据实际修改 encoder_last = __HAL_TIM_GET_COUNTER(&htim1); // 记录初始计数值 encoder_absolute = 0; // 初始绝对位置设为0(零点) //uint32_t last_pulse_display = 0xFFFFFFFF; uint32_t last_cycle_display = 0xFFFF; float compensation =1.02; /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ // while (1) { // 更新编码器绝对位置和距离 Encoder_UpdateAbsolute(); encoder_distance = (float)encoder_absolute * LEAD * CALIBRATION / ENCODER_PPR; // 读取数据 __disable_irq(); uint32_t pulse = pulse_count; // 实时脉冲数 uint32_t cycle = cycle_count; // 当前循环次数 uint32_t pulses_move = pulses_per_move; // 单次移动对应脉冲 __enable_irq(); //// 新代码:显示累计距离 total_dist(支持正负、2位小数、不清零) //OLED_ShowString(1, 1, "Dist:"); //// 拆分整数部分和小数部分(处理正负值) //int16_t dist_int = (int16_t)total_dist; // 整数部分(如1.99→1,-2.05→-2) //uint16_t dist_dec = (uint16_t)(fabs(total_dist - dist_int) * 100); // 小数部分(取绝对值,2位) //// 显示负号或空格(正数值前用空格占位,确保对齐) //if (total_dist < 0) //{ // OLED_ShowString(1, 6, "-"); // 负号显示在第1行第6列 // OLED_ShowNum(1, 7, abs(dist_int), 3); // 整数部分取绝对值(3位占位,如-3→003) //} //else //{ // OLED_ShowString(1, 6, " "); // 正数值前用空格占位,与负号对齐 // OLED_ShowNum(1, 7, dist_int, 3); // 整数部分(3位占位,如5→005) //} //// 显示小数和单位 //OLED_ShowString(1, 10, "."); // 小数点(第1行第10列) //OLED_ShowNum(1, 11, dist_dec, 2); // 2位小数(如0.05、1.99) //OLED_ShowString(1, 13, "mm"); // 单位(第1行第13列) //编码器距离显示 // 计算修正后的距离 int16_t dist_int = (int16_t)encoder_distance; // 整数部分(可正可负) uint16_t dist_dec = (uint16_t)(fabs(encoder_distance - dist_int) * 100); // 小数部分 // 拆分整数和小数部分(保留2位小数) int16_t pos_int = (int16_t)encoder_distance; // 声明并初始化 uint16_t pos_dec = (uint16_t)(fabs(encoder_distance - pos_int) * 100); OLED_ShowString(1, 1, "Dist:"); if (encoder_distance < 0) { OLED_ShowString(1, 6, "-"); OLED_ShowNum(1, 7, abs(pos_int), 3); // 使用dist_int } else { OLED_ShowString(1, 6, " "); OLED_ShowNum(1, 7, pos_int, 3); // 使用dist_int } OLED_ShowString(1, 10, "."); OLED_ShowNum(1, 11, pos_dec, 2); OLED_ShowString(1, 13, "mm"); // 计算单次拉伸距离(mm) uint32_t single_move_mm = (pulses_move / 640) * 1; // uint32_t single_mm = pulse / 640; // 每640脉冲=1mm uint32_t completed_cycles = cycle / 2; if ((cycle / 2) != last_cycle_display) { OLED_ShowString(2, 1, "Cycle:"); OLED_ShowNum(2, 7, cycle / 2, 5); last_cycle_display = cycle / 2; } // 第三行显示单次拉伸距离(不变,显示单次距离) OLED_ShowString(3, 1, "Len:"); OLED_ShowNum(3, 5, single_move_mm, 3); OLED_ShowString(3, 8, "spped:"); OLED_ShowNum(3, 15, spped, 2); // 第四行显示拉伸总次数 OLED_ShowString(4, 1, "Cycles:"); OLED_ShowNum(4, 8, cycle_times, 5); // PA15增加速度 uint8_t PA15_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15); if (last_PA15_state == 1 && PA15_state == 0&& spped<30) // 按下检测 { spped++; HAL_Delay(200); } last_PA15_state = PA15_state; // PB5减少速度 uint8_t PB5_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_5); if (last_PB5_state == 1 && PB5_state == 0&& spped>10) // 按下检测 { spped--; HAL_Delay(200); } last_PB5_state = PB5_state; // PB14增加移动距离(按一次加1mm) uint8_t PB14_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14); if (last_PB14_state == 1 && PB14_state == 0) // 下降沿检测,按下 { compensation+=0.0105; pulses_per_move += 640; // 假设3200脉冲对应5mm,按需调整 HAL_Delay(200); // 简单消抖 // 计算目标频率:每分钟20次单程(10次往返) FREQ_MAX = (pulses_per_move * spped*2) / 60; // 增加补偿加减速时间损耗 FREQ_MAX = FREQ_MAX * compensation; } last_PB14_state = PB14_state; // PB3减少移动距离(按一次减1mm) uint8_t PB3_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3); if (last_PB3_state == 1 && PB3_state == 0&& pulses_per_move>640) // 下降沿检测,按下 { compensation-=0.0105; pulses_per_move -= 640; // 假设3200脉冲对应5mm,按需调整 HAL_Delay(200); // 简单消抖 // 计算目标频率:每分钟20次单程(10次往返) FREQ_MAX = (pulses_per_move * spped*2) / 60; // 增加补偿加减速时间损耗 FREQ_MAX = FREQ_MAX * compensation; } last_PB3_state = PB3_state; // PA11增加循环次数(按一次加1000次) uint8_t PA11_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11); if (last_PA11_state == 1 && PA11_state == 0) // 按下检测 { cycle_times += 1000; HAL_Delay(200); } last_PA11_state = PA11_state; // PA10减少循环次数(按一次减1000次) uint8_t PA10_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_10); if (last_PA10_state == 1 && PA10_state == 0&&cycle_times>1000) // 按下检测 { cycle_times -= 1000; HAL_Delay(200); } last_PA10_state = PA10_state; // 点动控制(B0、B11) if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET) // B0按下,正转 { Motor_Start(1); // 开启PWM和方向 cycle_running = 0; // 关闭循环 running = 1; // 点动标志 } else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11) == GPIO_PIN_RESET) // B11按下,反转 { Motor_Start(0); cycle_running = 0; running = 1; } else if(running) // 按键释放,点动停止 { Motor_StopPWM(); running = 0; } // PB1和PB10单次1mm控制 // PB1按下:正转1mm uint8_t PB1_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1); if (last_PB1_state == 1 && PB1_state == 0 && !single_move_running) { Motor_SingleMove1mm(1); // 正转1mm HAL_Delay(200); // 消抖,防止一次按下多次触发 } last_PB1_state = PB1_state; // PB10按下:反转1mm uint8_t PB10_state = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10); if (last_PB10_state == 1 && PB10_state == 0 && !single_move_running) { Motor_SingleMove1mm(0); // 反转1mm HAL_Delay(200); // 消抖 } last_PB10_state = PB10_state; // 复位按钮 - PB15 被按下时,复位计数器 if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_15) == GPIO_PIN_RESET) { // 停止PWM输出 HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1); // 停止步进电机脉冲输出 // 复位变量 pulse_count = 0; cycle_count = 0; spped =10; pulses_per_move=640; cycle_times=1000; current_dir = 1; // 可以设为初始方向 // last_pulse_display = 0xFFFFFFFF; last_cycle_display = 0xFFFF; cycle_running = 0; // 停止循环状态 encoder_absolute = 0; // 当前位置设为零点 encoder_distance = 0.00; HAL_Delay(500); // 延时一下,避免误触 total_dist=0; // 清空显示 OLED_Clear(); } // 当故障消失(重新接上)且之前已处理故障,清零标志允许重启 if (!fault_active && fault_processed) { fault_triggered = 0; fault_processed = 0; } // 6.1 PB6紧急停止(保留原功能:直接停止,不回原点) if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6) == GPIO_PIN_RESET && cycle_running == 1) { Motor_StopPWM(); cycle_running = 0; fault_triggered = 0; fault_processed = 0; HAL_Delay(300); // 消抖 } // 6.2 A4/A5/A6故障检测(断开时触发,仅标记一次) else if (cycle_running == 1 && fault_triggered == 0) { // 任意一个故障引脚为高电平(断开),则触发故障 if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_SET || HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_SET || HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) == GPIO_PIN_SET) { fault_triggered = 1; fault_processed = 0; HAL_Delay(50); // 消抖 } } // -------------------------- 7. 循环运行与故障处理 -------------------------- // 7. 循环运行与故障处理(修正流程) if (cycle_running) { // 正常停止条件:循环完成 if (completed_cycles >= cycle_times) { Motor_StopPWM(); cycle_running = 0; } // 故障处理(核心修改) else if (fault_triggered && !fault_processed) { // 正转时断开:走完当前正转 → 反转回原点 if (current_dir == 0) { // 1. 确保走完当前正转脉冲 pulse_count = 0; Motor_SetDirection(current_dir); // 保持正转方向 Motor_Run_One_Direction(); // 完成当前正转 cycle_count++; } // 反转时断开:直接在原点停止(无需额外动作) else if (current_dir == 1) { // 无需走完当前反转,直接停止 Motor_StopPWM(); // cycle_count-=2; } // 处理完成,统一停止循环并更新状态 cycle_running = 0; fault_processed = 1; } // 正常运行 else if (!fault_triggered) { pulse_count = 0; Motor_SetDirection(current_dir); Motor_Run_One_Direction(); current_dir = !current_dir; // 切换方向 cycle_count++; } } // 8. 启动循环(PB4按下,无故障时) else if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) == GPIO_PIN_RESET && HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET && HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_RESET && HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6) == GPIO_PIN_RESET) { cycle_running = 1; pulse_count = 0; current_dir = 1; Motor_SetDirection(current_dir); } } } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ 这是我的main.c函数,我该怎么让stm32f103c8t6去和H05蓝牙连接,因为我上位机写了点动正转和反转#include "QtWidgetsApplication1.h" #include "ui_QtWidgetsApplication1.h" #include <QMessageBox> #pragma execution_character_set("utf-8") QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent) : QWidget(parent) , ui(new Ui::QtWidgetsApplication1Class) , discoveryAgent(nullptr) , socket(nullptr) { ui->setupUi(this); // 初始化蓝牙组件 discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this); socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol, this); // 仅保留核心功能的信号连接 connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &QtWidgetsApplication1::deviceDiscovered); connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, [=]() { ui->statusLabel->setText("扫描完成"); }); connect(socket, &QBluetoothSocket::connected, this, &QtWidgetsApplication1::socketConnected); connect(socket, &QBluetoothSocket::disconnected, this, &QtWidgetsApplication1::socketDisconnected); connect(socket, &QBluetoothSocket::readyRead, this, &QtWidgetsApplication1::dataReceived); // 新增:点动按钮信号连接 connect(ui->pointMoveForwardButton, &QPushButton::clicked, this, &QtWidgetsApplication1::on_pointMoveForwardButton_clicked); connect(ui->pointMoveBackwardButton, &QPushButton::clicked, this, &QtWidgetsApplication1::on_pointMoveBackwardButton_clicked); // 初始化UI状态 ui->startButton->setEnabled(false); ui->stopButton->setEnabled(false); ui->pointMoveForwardButton->setEnabled(false); // 初始禁用 ui->pointMoveBackwardButton->setEnabled(false); // 初始禁用 } QtWidgetsApplication1::~QtWidgetsApplication1() { if (socket && socket->isOpen()) socket->close(); delete socket; delete discoveryAgent; delete ui; } void QtWidgetsApplication1::on_scanButton_clicked() { ui->deviceListWidget->clear(); ui->statusLabel->setText("正在扫描..."); discoveryAgent->start(); } void QtWidgetsApplication1::deviceDiscovered(const QBluetoothDeviceInfo& info) { if (info.name().contains("HC-05", Qt::CaseInsensitive)) { QString deviceInfo = QString("%1 (%2)") .arg(info.name().isEmpty() ? "未知HC-05" : info.name()) .arg(info.address().toString()); ui->deviceListWidget->addItem(deviceInfo); targetDevice = info; } } void QtWidgetsApplication1::on_connectButton_clicked() { if (!targetDevice.isValid()) { QMessageBox::warning(this, "错误", "请先扫描并选择HC-05设备"); return; } const QBluetoothUuid serviceUuid(QStringLiteral("00001101-0000-1000-8000-00805F9B34FB")); socket->connectToService(targetDevice.address(), serviceUuid); ui->statusLabel->setText("正在连接HC-05..."); } void QtWidgetsApplication1::socketConnected() { ui->statusLabel->setText("已连接到HC-05"); ui->statusLabel->setText("已连接(状态码:" + QString::number(socket->state()) + ")"); ui->connectButton->setEnabled(false); ui->startButton->setEnabled(true); ui->stopButton->setEnabled(true); ui->pointMoveForwardButton->setEnabled(true); // 启用正转点动 ui->pointMoveBackwardButton->setEnabled(true); // 启用反转点动 } void QtWidgetsApplication1::socketDisconnected() { ui->statusLabel->setText("已断开连接"); ui->connectButton->setEnabled(true); ui->startButton->setEnabled(false); ui->stopButton->setEnabled(false); ui->pointMoveForwardButton->setEnabled(false); // 禁用正转点动 ui->pointMoveBackwardButton->setEnabled(false); // 禁用反转点动 } void QtWidgetsApplication1::on_startButton_clicked() { if (socket->state() == QBluetoothSocket::ConnectedState) { socket->write("START\n"); ui->statusLabel->setText("已发送启动指令"); } } void QtWidgetsApplication1::on_stopButton_clicked() { if (socket->state() == QBluetoothSocket::ConnectedState) { socket->write("STOP\n"); ui->statusLabel->setText("已发送停止指令"); } } void QtWidgetsApplication1::dataReceived() { QByteArray data = socket->readAll(); ui->recvTextEdit->append("单片机回传:" + data); } // 正转点动按钮槽函数 void QtWidgetsApplication1::on_pointMoveForwardButton_clicked() { if (socket->state() == QBluetoothSocket::ConnectedState) { QByteArray cmd = "POINT_FWD\n"; // 必须带换行符 qint64 bytesSent = socket->write(cmd); ui->statusLabel->setText("发送正转指令:" + QString(cmd) + "(" + QString::number(bytesSent) + "字节)"); } else { ui->statusLabel->setText("未连接蓝牙"); } } // 反转点动按钮槽函数(类似修改) void QtWidgetsApplication1::on_pointMoveBackwardButton_clicked() { if (socket->state() == QBluetoothSocket::ConnectedState) { QByteArray cmd = "POINT_BWD\n"; qint64 bytesSent = socket->write(cmd); ui->statusLabel->setText("发送反转指令:" + QString(cmd) + "(" + QString::number(bytesSent) + "字节)"); } else { ui->statusLabel->setText("未连接蓝牙"); } }但是上位机按下没反应
09-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值