Files
32343 843447835d Initial commit: TC264 smart car project with IPS200 menu system
- IPS200 display menu with real-time status and parameter settings
- Camera image processing and line tracking
- IMU attitude solution and PID control
- WiFi SPI oscilloscope data transmission
2026-05-10 21:38:49 +08:00

217 lines
7.9 KiB
C
Raw Permalink 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.
/*********************************************************************************************************************
* TC264 Opensourec Library (TC264开源库)是一个基于官方 SDK 接口的底层开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是 TC264开源库的一部分
*
* TC264开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPL(GNU General Public License,GNU通用公共许可证)的条款
* 即 GPL 的第3版(或 GPL3.0),或(根据您的选择)任何更高的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能有所帮助,但不提供任何保证
* 甚至没有默示的适销性或适用于特定用途的保证
* 有关更多详情,请参阅 GPL
*
* 您应该已经与本开源库一起收到一份 GPL 的副本
* 如果没有,请访问 <https://www.gnu.org/licenses/>
*
* 文件名称 cpu0_main
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹下的 version 文件 版本说明
* 开发环境 ADS v1.10.2
* 目标平台 TC264D
* 购买地址 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 pudding first version
* 2025-05-01 移植 整合摄像头+电机+编码器+IMU+显示菜单+电池检测
********************************************************************************************************************/
#include "zf_common_headfile.h"
#include "attitude_solution.h"
#include "user_menu.h"
#include "user_menu_device.h"
#include "user_image_process.h"
#include "user_line_process.h"
#include "pid_control.h"
#pragma section all "cpu0_dsram"
// *************************** 硬件引脚定义 ***************************
// 编码器定义 (直接使用驱动库中的枚举值)
// TIM4编码器 — 硬件固定引脚, 仅支持方向模式
#define ENCODER_1_A (TIM4_ENCODER_CH1_P02_8)
#define ENCODER_1_B (TIM4_ENCODER_CH2_P00_9)
// TIM6编码器 — 硬件固定引脚, 仅支持方向模式
#define ENCODER_2_A (TIM6_ENCODER_CH1_P20_3)
#define ENCODER_2_B (TIM6_ENCODER_CH2_P20_0)
// 电机驱动定义 (宏定义在 pid_control.h 中, 此处不再重复)
#define MOTOR_PWM_FREQ (17000)
// 编码器数据
volatile int16 encoder_data_1 = 0;
volatile int16 encoder_data_2 = 0;
// IMU校准标志 (定义在 isr.c)
extern volatile uint8 gyro_calib_ok;
// LED
#define LED (P21_5)
// 系统运行标志
bool car_running = FALSE;
// **************************** 主函数 ****************************
int core0_main(void)
{
clock_init();
debug_init();
// cpu0_dsram 段不会被启动代码自动清零,必须手动初始化
encoder_data_1 = 0;
encoder_data_2 = 0;
car_running = FALSE;
// ==================== 硬件初始化 ====================
// 1. 电池电压检测ADC初始化
adc_init(VOLTAGE_PORT, ADC_12BIT);
// 2. 摄像头初始化 (MT9V03X 单摄像头模式)
// 初始化前清零摄像头状态与缓冲区,避免 cpu0_dsram 段中的随机值干扰
mt9v03x_finish_flag_1 = 0;
mt9v03x_finish_flag_2 = 0;
memset(mt9v03x_image_1, 0, sizeof(mt9v03x_image_1));
memset(mt9v03x_image_2, 0, sizeof(mt9v03x_image_2));
system_delay_ms(800);
if(mt9v03x_double_init(mt9v03x_1))
{
printf("\r\n MT9V03X init failed, retrying...");
for(int retry = 0; retry < 3; retry++)
{
system_delay_ms(800);
if(mt9v03x_double_init(mt9v03x_1) == 0)
break;
printf("\r\n MT9V03X retry %d/3 failed", retry + 1);
}
}
// 关闭 EXTI CH5 (P15_8),该引脚同时连接摄像头2 PCLK 和 WiFi INT,
// 在单摄像头模式下关闭此中断,避免 WiFi 通信产生虚假中断导致画面撕裂
exti_disable(ERU_CH5_REQ1_P15_8);
// 3. 电机驱动GPIO与PWM初始化
gpio_init(MOTOR_DIR1, GPO, GPIO_HIGH, GPO_PUSH_PULL);
gpio_init(MOTOR_DIR2, GPO, GPIO_HIGH, GPO_PUSH_PULL);
pwm_init(MOTOR_PWM1, MOTOR_PWM_FREQ, 0);
pwm_init(MOTOR_PWM2, MOTOR_PWM_FREQ, 0);
pwm_init(VACUUM_PWM, MOTOR_PWM_FREQ, 0); /* 真空泵 */
// 4. 编码器初始化 (方向模式: A相计数 + B相判向)
encoder_dir_init(TIM4_ENCODER, ENCODER_1_A, ENCODER_1_B);
encoder_dir_init(TIM6_ENCODER, ENCODER_2_A, ENCODER_2_B);
encoder_clear_count(TIM4_ENCODER);
encoder_clear_count(TIM6_ENCODER);
// 5. IMU初始化 (IMU660RB,单次初始化)
gpio_init(LED, GPO, GPIO_HIGH, GPO_PUSH_PULL);
if(imu660rb_init() != 0)
{
printf("\r\n IMU660RB init failed.");
}
// 6. 蜂鸣器初始化
gpio_init(BEEP_PIN, GPO, GPIO_LOW, GPO_PUSH_PULL);
// 7. 按键初始化
key_init(20);
// 7.5. 姿态解算初始化 (四元数复位, 须在PIT定时器启动前完成)
attitude_init();
// 7.6. 四轮车速度环与转向环PID初始化
//
// 左/右速度环 (内环, 100ms): 各自编码器速度 → 各自PWM基础值
// 输出限幅为死区之外的调节余量,最终输出会叠加 MOTOR_PWM_DEADBAND
pid_init(&g_pid_speed_left, 0.0f, 1.0f, 0.0f, SPEED_PID_OUT_MAX, -SPEED_PID_OUT_MAX, 100.0f, 1); /* 增量式 */
pid_init(&g_pid_speed_right, 0.0f, 1.0f, 0.0f, SPEED_PID_OUT_MAX, -SPEED_PID_OUT_MAX, 100.0f, 1); /* 增量式 */
// 转向环 (并行, 帧周期): 摄像头中线偏差 → PWM差速
// P项: 中线偏差驱动转向, D项: gyro_z 阻尼抑制过冲
// 输出限幅 ±2000 (差速PWM)
pid_init(&g_pid_steering, 0.0f, 0.0f, 0.0f, 2000.0f, -2000.0f, 0.0f, 0); /* 位置式 */
// 8. PIT定时器初始化
// CCU60_CH0: IMU数据采集 (5ms周期)
// CCU61_CH0: 编码器读取 (100ms周期)
pit_ms_init(CCU60_CH0, 5);
pit_ms_init(CCU61_CH0, 100);
// 9. 显示菜单初始化
user_menu_init();
// ==================== 主循环 ====================
cpu_wait_event_ready();
while (TRUE)
{
/* 陀螺仪校准完成后自动启用速度环与转向环控制 */
if(gyro_calib_ok == 1 && !g_control_enabled)
{
g_control_enabled = TRUE;
printf("\r\n PID control enabled.");
}
// 摄像头帧同步触发
if(mt9v03x_finish_flag_1)
{
uint32 t_frame_start; /* 帧处理起始时刻 (us) */
mt9v03x_finish_flag_1 = 0;
t_frame_start = system_getval_us();
/* 复制帧到共享内存, 并在 CPU0 内完成图像处理 (二值化+边界+中线) */
memcpy(camera_frame_buffer, (const uint8 *)mt9v03x_image_1,
(uint32)(MT9V03X_1_H * MT9V03X_1_W));
/* 大津法二值化 */
int otsu_thr = user_otsu_threshold(camera_frame_buffer, MT9V03X_1_W, MT9V03X_1_H);
user_image_binarize(camera_frame_buffer, image_binary_1,
MT9V03X_1_W, MT9V03X_1_H, otsu_thr);
/* 二值化图像降噪 */
user_image_denoise(image_binary_1, MT9V03X_1_W, MT9V03X_1_H);
/* 边界追踪 + 中线提取 */
line_process_run((uint8 *)image_binary_1);
/* 转向环: 下半部分加权中线偏差 + 陀螺仪 yaw rate → PWM差速 */
if(g_control_enabled && center_line_num > 0)
{
float line_dev = line_compute_weighted_deviation(
(uint16)(MT9V03X_1_W * 0.5f),
(uint16)(MT9V03X_1_H / 2));
cascade_steering_loop(line_dev, g_gyro_z_dps);
}
// 运行菜单循环 (含按键处理、数据显示、图像显示)
user_menu_loop();
// 低电量蜂鸣报警
//low_battery_alarm_check();
// CPU占用率监测: 记录本帧处理耗时
cpu_usage_record_frame(system_getval_us() - t_frame_start);
}
}
}
#pragma section all restore