TiSmartCar/example/2025_main.cpp
Boen_Shi 8be2866433 feat(base): 初始化 MSPM0 开发环境
- 添加头文件和配置文件支持
- 更新.gitignore忽略编译和IDE相关文件
- 添加基础的bsp代码
2026-07-16 14:45:26 +08:00

401 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <ti_msp_dl_config.h>
#include <FreeRTOS.h>
#include <task.h>
#include <Print.h>
#include <Encoder.h>
#include <Imu.h>
#include <Motor.h>
#include <TrackerMpu.h>
#include <TrackerGpio.h>
#include <2025_include_user/Beep.h>
#include <Host.h>
#include <Key.h>
#include <Led.h>
#include <Servo.h>
#include <Stepmotor.h>
#include <Oled.hpp>
#include <OledMenuDriver.h>
#include <OledMenuPaint.h>
#include <TrackerGpio.h>
#include <TrackerGpio.h>
/************ 外部中断测试部分 ************/
extern "C" void GROUP1_IRQHandler() {
//读取Group1的中断寄存器并清除中断标志位
switch (DL_Interrupt_getPendingGroup(DL_INTERRUPT_GROUP_1)) {
//检查是否是KEY的GPIOB端口中断注意是INT_IIDX不是PIN_22_IIDX
case Key_GPIOA_INT_IIDX:
case GPIO_MULTIPLE_GPIOB_INT_IIDX: {
const uint32_t statusA = DL_GPIO_getPendingInterrupt(GPIOA);
const uint32_t statusB = DL_GPIO_getPendingInterrupt(GPIOB);
// print("%d\n", statusA);
// print("%d\n", statusB);
if (statusA == KEY1_PIN_ID + 1) {
Key::keys[KEY1].state = 1;
} else if (statusB == KEY2_PIN_ID + 1) {
Key::keys[KEY2].state = 1;
} else if (statusB == KEY3_PIN_ID + 1) {
Key::keys[KEY3].state = 1;
} else if (statusB == KEY4_PIN_ID + 1) {
Key::keys[KEY4].state = 1;
}
// TrackerGpio::inject(Tracker_Track1_PIN, DL_GPIO_readPins(Tracker_Track1_PORT, Tracker_Track1_PIN) > 0);
// TrackerGpio::inject(Tracker_Track2_PIN, DL_GPIO_readPins(Tracker_Track2_PORT, Tracker_Track2_PIN) > 0);
// TrackerGpio::inject(Tracker_Track3_PIN, DL_GPIO_readPins(Tracker_Track3_PORT, Tracker_Track3_PIN) > 0);
// TrackerGpio::inject(Tracker_Track4_PIN, DL_GPIO_readPins(Tracker_Track4_PORT, Tracker_Track4_PIN) > 0);
// TrackerGpio::inject(Tracker_Track5_PIN, DL_GPIO_readPins(Tracker_Track5_PORT, Tracker_Track5_PIN) > 0);
// TrackerGpio::inject(Tracker_Track6_PIN, DL_GPIO_readPins(Tracker_Track6_PORT, Tracker_Track6_PIN) > 0);
// TrackerGpio::inject(Tracker_Track7_PIN, DL_GPIO_readPins(Tracker_Track7_PORT, Tracker_Track7_PIN) > 0);
DL_GPIO_clearInterruptStatus(GPIOA, statusA);
DL_GPIO_clearInterruptStatus(GPIOB, statusB);
break;
}
default:
break;
}
}
/************ FreeRtos 任务定义区 ************/
[[noreturn]] void vLedTask(void *pvParameters) {
while (true) {
Led::on(LED0);
// DL_GPIO_setPins(Lights_PORT, Lights_Light_PIN);
vTaskDelay(pdMS_TO_TICKS(500)); // 每500毫秒切换一次LED状态
Led::off(LED0);
// DL_GPIO_clearPins(Lights_PORT, Lights_Light_PIN);
vTaskDelay(pdMS_TO_TICKS(500)); // 每500毫秒切换一次LE+D状态
}
}
[[noreturn]] void vOledTask(void *pvParameters) {
MenuDriver::init();
MenuPaint::Init();
while (true) {
const int direction = (int) Host::get("Direction", 0);
if (Key::getState(KEY1 || direction == 2)) {
MenuPaint::ScrollUp();
}
if (Key::getState(KEY2) || direction == 8) {
MenuPaint::ScrollDown();
}
if (Key::getState(KEY3) || direction == 4) {
MenuPaint::Enter();
}
if (Key::getState(KEY4) || direction == 6) {
MenuPaint::Exit();
}
MenuPaint::Paint();
vTaskDelay(pdMS_TO_TICKS(10));
}
}
[[noreturn]] void vTestTask(void *pvParameters) {
while (true) {
// print("Ctrl: %f\n", Host::get("Ctrl", 0.0));
// print("x: %f\n", Host::get("x", 0.0));
// print("y: %f\n", Host::get("y", 0.0));
// Motor::setSpeed(3000, 3000);
// TrackerGpio::Data data = TrackerGpio::getData(); // 每位数据0 表示压线1 表示空白
// const char *d = data.data;
//
// print("Data:%d,%d,%d,%d,%d,%d,%d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6]);
// vTaskDelay(pdMS_TO_TICKS(100));
}
}
static uint8_t turn_limit = 0;
[[noreturn]] void vTrackerTask(void *pvParameters) {
// 计算偏移量(简单加权)
// 左侧为正,右侧为负
constexpr float weights[7] = {-2.1, -1.5, -0.8, 0, 0.8, 1.5, 2.1};
constexpr int base_speed = 4000; // 基础速度
constexpr int adjust_speed = 2000; // 差速调整速度
while (true) {
if (turn_limit <= 0) {
for (uint8_t i = 0; i < 5; i++) {
if (MenuPaint::GetSwitchState(i) == 1) {
turn_limit = 4 * (i + 1) + 1;
}
}
Motor::stop();
vTaskDelay(pdMS_TO_TICKS(50));
continue;
}
// 读取循迹传感器数据
TrackerGpio::Data data = TrackerGpio::getData(); // 每位数据0 表示压线1 表示空白
const char *d = data.data;
float error = 0;
int sum = 0;
for (int i = 0; i < 7; ++i) {
if (d[i] == 0) {
// 压到线
error += weights[i];
sum++;
}
}
if (sum == 0) {
turn_limit--;
if (turn_limit <= 0) {
Motor::stop();
vTaskDelay(pdMS_TO_TICKS(50));
continue;
}
uint8_t is_speed = (MenuPaint::GetSwitchState(5) == 1) ? 1 : 0;
uint8_t speed = is_speed ? 210 : 160;
Motor::setLeftSpeed(0);
Motor::setRightSpeed(speed * 10);
while (true) {
data = TrackerGpio::getData(); // 每位数据0 表示压线1 表示空白
const char *inner_d = data.data;
if (inner_d[3] == 0 || inner_d[2] == 0 || inner_d[1] == 0 || inner_d[0] == 0)
break;
Motor::setLeftSpeed(0);
Motor::setRightSpeed(speed * 10);
vTaskDelay(pdMS_TO_TICKS(50));
}
} else {
int left_speed = base_speed;
int right_speed = base_speed;
error = error / sum;
// 差速控制,误差越大,左右轮速度差越大
left_speed = (int) (base_speed - error * adjust_speed / 4);
right_speed = (int) (base_speed + error * adjust_speed / 4);
// 限制最大最小速度
if (left_speed > 10000) left_speed = 10000;
if (left_speed < -10000) left_speed = -10000;
if (right_speed > 10000) right_speed = 10000;
if (right_speed < -10000) right_speed = -10000;
// 设置电机速度
Motor::setLeftSpeed(left_speed);
Motor::setRightSpeed(right_speed);
vTaskDelay(pdMS_TO_TICKS(50));
}
}
}
[[noreturn]] void vStepMotorTask(void *pvParameters) {
// // PID参数根据实际调试再微调
//
// const float integral_limit = 500.0f; // 积分限幅,避免积分快速累积
// const float DEAD_ZONE = 10.0f; // 误差死区误差在±5像素内不动作
//
// float integral = 0.0f;
// float last_error = 0.0f;
vTaskDelay(pdMS_TO_TICKS(500));
while (true) {
// DL_TimerG_setCaptureCompareValue(Servo_INST, (uint32_t)800, GPIO_Servo_C0_IDX);
Servo::SetUpAngle(Host::getWithoutClean("angle", 87.0));
// Servo::SetDownAngle(120);
// // if (MenuPaint::GetSwitchState(5) == 0 || MenuPaint::GetSwitchState(6) == 0) {
// // vTaskDelay(pdMS_TO_TICKS(100));
// // continue;
// // }
//
// const double Kp = Host::getWithoutClean("kp", 0.2);
// const double Ki = Host::getWithoutClean("ki", 0.0005);
// const double Kd = Host::getWithoutClean("kd", 0.006);
// const double t_ = Host::posX; // 获取像素误差范围0~240
// const uint8_t direction = (t_ > 0) ? 1 : 0;
// const double error = t_ > 0 ? t_ : -t_;
//
//
// print("Kp: %f, Ki: %f, Kd: %f\n", Kp, Ki, Kd);
//
// // 死区处理
// if (fabs(error) < DEAD_ZONE) {
// StepMotor::setPosition(0, 32, 0.0f, 0); // 停止动作
// integral = 0; // 死区内积分归零,避免积累
// // while (true) {
// // // TODO 激光ON
// // vTaskDelay(pdMS_TO_TICKS(1000));
// // // TODO 激光OFF
// // }
// } else {
// // 积分项累加 & 限幅
// integral += error;
// if (integral > integral_limit) integral = integral_limit;
// if (integral < -integral_limit) integral = -integral_limit;
//
// // 微分项
// float derivative = error - last_error;
//
// // PID输出
// float output = Kp * error + Ki * integral + Kd * derivative;
//
// // 限制输出范围0.3° ~ 2.0°)
// if (output < 0.3f) output = 0.3f;
// if (output > 4.0f) output = 4.0f;
//
// // 控制步进电机
// StepMotor::setPosition(direction, 32, output, -10);
// // print("Motor: speed=%f, direction=%d\n", output, direction);
//
// last_error = error; // 保存上次误差
// }
vTaskDelay(pdMS_TO_TICKS(500));
}
}
/***************** 主函数 ******************/
int main() {
/*** SysConfig 初始化 ***/
SYSCFG_DL_init();
/*** 模块初始化 ***/
Print_init();
Encoder::init();
// Imu::init();
Motor::init();
// TrackerMpu::init();
// Beep::init();
// Led::init();
Host::init();
Key::init();
// StepMotor::init();
/*** FreeRtos 任务初始化 ***/
xTaskCreate(vLedTask, "TestLedTask", 32, nullptr, 1, nullptr);
xTaskCreate(vOledTask, "vOledTask", 128, nullptr, 1, nullptr);
// xTaskCreate(vTestTask, "vTestTask", 512, nullptr, 1, nullptr);
xTaskCreate(vTrackerTask, "vTrackerTask", 256, nullptr, 1, nullptr);
xTaskCreate(vStepMotorTask, "vStepMotorTask", 32, nullptr, 1, nullptr);
/*** 启动 FreeRtos ***/
vTaskStartScheduler();
return 0;
}
/************ FreeRtos 错误处理部分 ************/
#ifdef __cplusplus
extern "C" {
#endif
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
/* 栈溢出时的处理代码 */
/* 例如,打印错误信息并重置系统 */
/* 参数:
* xTask - 发生栈溢出的任务句柄
* pcTaskName - 发生栈溢出的任务名称
*/
/* 通常在这里添加一些错误处理和系统恢复的代码 */
while (1) {
/* 可以在此处添加错误处理代码如闪烁LED或输出调试信息 */
}
}
/* 在全局范围内定义存储空间 */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE];
/* 实现所需的函数 */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize) {
/* 传递静态分配的空闲任务数据结构的地址 */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* 传递静态分配的空闲任务堆栈的地址 */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* 传递堆栈大小 */
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/* 为定时器任务定义静态内存 */
static StaticTask_t xTimerTaskTCB;
static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH];
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize) {
/* 传递静态分配的定时器任务数据结构的地址 */
*ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
/* 传递静态分配的定时器任务堆栈的地址 */
*ppxTimerTaskStackBuffer = uxTimerTaskStack;
/* 传递堆栈大小 */
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
#ifdef __cplusplus
}
#endif
// [[noreturn]] void vStepMotorTask(void *pvParameters) {
// while (true) {
// double speed = Host::posX;
// uint8_t direction = 1;
//
// if (Host::x_count <= 0) {
// speed = 0.0;
// } else {
// Host::x_count--;
// if (Host::x_count == 0) {
// Host::posX = 0.0; // 用完后置零
// }
// }
//
// direction = speed >= 0 ? 1 : 0;
// speed = speed >= 0 ? speed : -speed;
// StepMotor::setSpeed(direction, 32, float(speed));
// print("Motor: speed=%f, direction=%d\n", speed, direction);
//
// vTaskDelay(pdMS_TO_TICKS(70));
// }
// }
// [[noreturn]] void vStepMotorTask(void *pvParameters) {
// while (true) {
// int error = (int) Host::posX;
// uint8_t direction = error > 0;
// if (error > 5 || error < -5) {
// StepMotor::setPosition(direction, 32, 0.5, 10);
// }
//
// vTaskDelay(pdMS_TO_TICKS(93));
// }
// }
// print("FunA: %d\n", MenuPaint::GetSwitchState(0));
// print("FunB: %d\n", MenuPaint::GetSwitchState(1));
// if (MenuPaint::GetSwitchState(0) == 1) {
// Beep::start();
// } else {
// Beep::stop();
// }
// [[noreturn]] void vTrackerTask(void *pvParameters) {
// while (true) {
// print("Tracker!\n");
// const TrackerGpio::Data data = TrackerGpio::getData();
// print("Tracker: %d, %d, %d, %d, %d, %d, %d\n", data.data[0], data.data[1], data.data[2], data.data[3], data.data[4], data.data[5], data.data[6]);
// vTaskDelay(pdMS_TO_TICKS(1000));
// }
// }