正在开发的是一个 基于 STM32F103C8T6 的多功能智能小车控制系统,功能包括:
按键切换模式(巡线 / 避障 / 混合 / 停止)
红外循迹
超声波避障
LCD 显示
蜂鸣器提示音
C/D点弯道识别并鸣笛 /* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : ??????? (STM32F103C8T6 ???)
* @author : AI Assistant
* @version : 2.0
* @date : 2025-11-30
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include <stdio.h>
#include <string.h>
/* Private variables ---------------------------------------------------------*/
uint8_t runMode = 3; /* 0=?? 1=?? 2=?? 3=?? */
uint8_t carBodyState = 4; /* 0=? 2=? 3=? 4=? */
uint8_t leftState = 0;
uint8_t centreState = 0;
uint8_t rightState = 0;
static uint8_t wasTurning = 0;
static uint8_t eventCount = 0;
static uint8_t beepCooldown = 0;
char showBuffer[32] = {0};
int distance = 0;
uint32_t tick30ms = 0;
static uint8_t lastKey = 1;
/* ???? */
#define DISTANCE_THRESHOLD 60
#define HYBRID_DIST 30
/* ??????(???? gpio.h ???)------------------------------------*/
#ifndef KEY_Pin
#define KEY_Pin GPIO_PIN_0
#define KEY_GPIO_Port GPIOA
#endif
#ifndef IR_L_Pin
#define IR_L_Pin GPIO_PIN_1
#define IR_L_GPIO_Port GPIOA
#endif
#ifndef IR_M_Pin
#define IR_M_Pin GPIO_PIN_2
#define IR_M_GPIO_Port GPIOA
#endif
#ifndef IR_R_Pin
#define IR_R_Pin GPIO_PIN_3
#define IR_R_GPIO_Port GPIOA
#endif
#ifndef BEEP_Pin
#define BEEP_Pin GPIO_PIN_4
#define BEEP_GPIO_Port GPIOA
#endif
#ifndef LED_Pin
#define LED_Pin GPIO_PIN_5
#define LED_GPIO_Port GPIOA
#endif
/* ??????(??? PWM ??????)-------------------------------*/
#ifndef MOTOR_L_IN1_Pin
#define MOTOR_L_IN1_Pin GPIO_PIN_12
#define MOTOR_L_IN1_GPIO_Port GPIOB
#endif
#ifndef MOTOR_L_IN2_Pin
#define MOTOR_L_IN2_Pin GPIO_PIN_13
#define MOTOR_L_IN2_GPIO_Port GPIOB
#endif
#ifndef MOTOR_R_IN1_Pin
#define MOTOR_R_IN1_Pin GPIO_PIN_14
#define MOTOR_R_IN1_GPIO_Port GPIOB
#endif
#ifndef MOTOR_R_IN2_Pin
#define MOTOR_R_IN2_Pin GPIO_PIN_15
#define MOTOR_R_IN2_GPIO_Port GPIOB
#endif
/* ???? */
void SystemClock_Config(void);
void Error_Handler(void);
void update_line_sensor_state(void);
void patrol_mode(void);
void obstacle_avoidance_mode(void);
void hybrid_mode(void);
void update_mode_display(void);
/* ==================== ??:???????? ======================== */
/**
* @brief ???????
*/
void beep_once(void) {
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_SET);
HAL_Delay(60);
HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
}
/**
* @brief ????(?? C/D ???)
*/
void beep_twice(void) {
beep_once();
HAL_Delay(100);
beep_once();
}
/**
* @brief ???????(?????)
* @param left: ???? (-1000 ~ 1000),????
* @param right: ???? (-1000 ~ 1000),????
*/
void set_motor_speed(int left, int right) {
// === ?????? ===
if (left > 0) {
HAL_GPIO_WritePin(MOTOR_L_IN1_GPIO_Port, MOTOR_L_IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_L_IN2_GPIO_Port, MOTOR_L_IN2_Pin, GPIO_PIN_RESET);
} else if (left < 0) {
HAL_GPIO_WritePin(MOTOR_L_IN1_GPIO_Port, MOTOR_L_IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_L_IN2_GPIO_Port, MOTOR_L_IN2_Pin, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(MOTOR_L_IN1_GPIO_Port, MOTOR_L_IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_L_IN2_GPIO_Port, MOTOR_L_IN2_Pin, GPIO_PIN_RESET);
}
// === ?????? ===
if (right > 0) {
HAL_GPIO_WritePin(MOTOR_R_IN1_GPIO_Port, MOTOR_R_IN1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_R_IN2_GPIO_Port, MOTOR_R_IN2_Pin, GPIO_PIN_RESET);
} else if (right < 0) {
HAL_GPIO_WritePin(MOTOR_R_IN1_GPIO_Port, MOTOR_R_IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_R_IN2_GPIO_Port, MOTOR_R_IN2_Pin, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(MOTOR_R_IN1_GPIO_Port, MOTOR_R_IN1_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_R_IN2_GPIO_Port, MOTOR_R_IN2_Pin, GPIO_PIN_RESET);
}
// === ?? PWM ???(???)===
uint16_t pwm_left = (left < 0) ? -left : left;
uint16_t pwm_right = (right < 0) ? -right : right;
if (pwm_left > 1000) pwm_left = 1000;
if (pwm_right > 1000) pwm_right = 1000;
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwm_left);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, pwm_right);
}
/**
* @brief ????(???)
*/
int get_distance(void) {
return 45; // ???? 45cm
}
/**
* @brief LCD ???(???,??????)
*/
void lcd1602_init(void) {}
/**
* @brief ?????
*/
void lcd1602_show_string(uint8_t x, uint8_t y, uint8_t *str) {
(void)x; (void)y; (void)str;
}
/**
* @brief ????
*/
void lcd1602_show_char(uint8_t x, uint8_t y, uint8_t c) {
(void)x; (void)y; (void)c;
}
/* Main ?? =========================================================*/
int main(void) {
HAL_Init();
/* =============== ????? AFIO ???? TIM3 =============== */
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_AFIO_REMAP_TIM3_PARTIAL(); // PA6=CH1, PA7=CH2 ? ???? PB0/PB1
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();
/* ?? PWM ??(PA6=??, PA7=??)*/
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // PA6
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2); // PA7
/* ??????(??? MX_GPIO_Init ???)*/
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef gpio = {0};
gpio.Pin = BEEP_Pin;
gpio.Mode = GPIO_MODE_OUTPUT_PP;
gpio.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(BEEP_GPIO_Port, &gpio);
/* LCD ??? */
lcd1602_init();
lcd1602_show_string(0, 0, (uint8_t *)"Intelligence Car");
lcd1602_show_string(0, 1, (uint8_t *)"MS:TZMS JL:xxxCM");
/* ??? */
while (1) {
/* ======== ????(PA0)======== */
uint8_t key = HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin);
if (lastKey == 1 && key == 0) {
HAL_Delay(20);
if (HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == 0) {
runMode = (runMode + 1) % 4;
beep_once();
if (runMode == 3) set_motor_speed(0, 0);
update_mode_display();
while (HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == 0);
}
}
lastKey = key;
/* ======== ? 30ms ???????? ======== */
if (HAL_GetTick() - tick30ms >= 30) {
tick30ms = HAL_GetTick();
distance = get_distance();
if (distance > 999) distance = 999;
lcd1602_show_char(11, 1, '0' + distance / 100);
lcd1602_show_char(12, 1, '0' + (distance / 10) % 10);
lcd1602_show_char(13, 1, '0' + distance % 10);
}
/* ======== ?????? ======== */
update_line_sensor_state();
/* ======== C/D????????? ======== */
uint8_t turningNow = (carBodyState == 2 || carBodyState == 3);
if (beepCooldown > 0) beepCooldown--;
if (!wasTurning && turningNow) {
eventCount++;
if (beepCooldown == 0) {
beep_twice();
beepCooldown = 100; // ??
}
}
if (eventCount >= 2) eventCount = 0;
wasTurning = turningNow;
/* ======== ?????? ======== */
switch (runMode) {
case 0: patrol_mode(); break;
case 1: obstacle_avoidance_mode(); break;
case 2: hybrid_mode(); break;
default: set_motor_speed(0, 0); break;
}
HAL_Delay(1); // ????
}
}
/* ?????? =====================================================*/
void update_line_sensor_state(void) {
leftState = HAL_GPIO_ReadPin(IR_L_GPIO_Port, IR_L_Pin);
centreState = HAL_GPIO_ReadPin(IR_M_GPIO_Port, IR_M_Pin);
rightState = HAL_GPIO_ReadPin(IR_R_GPIO_Port, IR_R_Pin);
if (centreState == 1) {
carBodyState = 0; // ??
} else if (leftState == 1 && rightState == 0) {
carBodyState = 2; // ??
} else if (leftState == 0 && rightState == 1) {
carBodyState = 3; // ??
} else {
carBodyState = 0; // ????
}
}
void patrol_mode(void) {
switch (carBodyState) {
case 0: set_motor_speed(800, 800); break; // ??
case 2: set_motor_speed(400, 700); break; // ?? ? ????
case 3: set_motor_speed(700, 400); break; // ?? ? ????
default: set_motor_speed(0, 0); break;
}
}
void obstacle_avoidance_mode(void) {
if (get_distance() < DISTANCE_THRESHOLD) {
beep_once();
set_motor_speed(0, 0); HAL_Delay(200);
set_motor_speed(-500, 500); HAL_Delay(300); // ??
set_motor_speed(600, 600); HAL_Delay(600); // ??
set_motor_speed(500, -500); HAL_Delay(300); // ??
while (get_distance() < DISTANCE_THRESHOLD) {
set_motor_speed(500, 500);
HAL_Delay(100);
}
beep_once();
} else {
set_motor_speed(600, 600); // ????
}
}
void hybrid_mode(void) {
if (get_distance() < HYBRID_DIST) {
beep_once();
set_motor_speed(0, 0); HAL_Delay(300);
set_motor_speed(-500, 500); HAL_Delay(400); // ??
set_motor_speed(600, 600); HAL_Delay(1000); // ??
set_motor_speed(500, -500); HAL_Delay(150); // ??
while (!leftState && !rightState) {
update_line_sensor_state();
set_motor_speed(500, 500);
HAL_Delay(80);
}
beep_once();
} else {
patrol_mode();
}
}
void update_mode_display(void) {
const char* modeStr[] = {"XX", "BZ", "XB", "TZ"};
snprintf(showBuffer, sizeof(showBuffer), "MS:%s JL:%03dCM",
modeStr[runMode], distance);
lcd1602_show_string(0, 1, (uint8_t *)showBuffer);
}
/* ?????? =====================================================*/
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
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; // 8MHz * 9 = 72MHz
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
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();
}
}
/* ?????? =====================================================*/
void Error_Handler(void) {
__disable_irq();
while (1) {
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_Delay(200);
}
}
修改程序使运行更顺畅