Files
stm32f407ve_black/APP/Src/main.c
2026-01-29 16:22:04 +08:00

445 lines
12 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.

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : 主程序文件
* @author : Auto-generated
* @date : 2026-01-29
******************************************************************************
* @attention
*
* 本文件包含STM32F407VET6开发板的主程序逻辑
* 包括系统初始化、外设配置和主循环处理
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "led.h"
#include "delay.h"
#include "uart.h"
#include "logging.h"
#include "bsp_init.h"
#include "bsp_config.h"
#include "bsp_w25qxx.h"
#include "bsp_key.h"
#include "bsp_eth.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
// LED闪烁间隔时间毫秒
#define LED_TOGGLE_INTERVAL 500
// 以太网状态检查间隔时间(毫秒)
#define ETH_CHECK_INTERVAL 5000
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
// LED实例
static led_t led;
// 定时器变量(用于非阻塞延时)
static uint32_t led_toggle_timer = 0;
static uint32_t eth_check_timer = 0;
static uint8_t last_link_status = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
// 初始化系统外设
static void system_peripherals_init(void);
// 初始化以太网
static void ethernet_init(void);
// 初始化LED
static void led_init_system(void);
// 初始化W25QXX存储芯片
static void w25qxx_init_system(void);
// 处理按键事件
static void key_events_handler(void);
// 处理LED闪烁
static void led_blink_handler(void);
// 处理以太网状态检查
static void ethernet_status_handler(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief 应用程序入口点
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU配置--------------------------------------------------------*/
/* 重置所有外设初始化Flash接口和SysTick */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* 配置系统时钟 */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* 初始化板级支持包 */
bsp_init();
/* 初始化系统外设 */
system_peripherals_init();
/* 无限循环 */
/* USER CODE BEGIN WHILE */
while (1)
{
/* 更新按键状态应定期调用例如每10ms */
bsp_key_update();
/* 处理按键事件 */
key_events_handler();
/* 处理LED闪烁 */
led_blink_handler();
/* 处理以太网状态检查 */
ethernet_status_handler();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief 系统外设初始化函数
* @retval 无
*/
static void system_peripherals_init(void)
{
// 初始化延时函数
delay_init();
// 初始化日志系统
logging_init();
// 设置日志级别为调试
logging_set_level(LOG_LEVEL_DEBUG);
// 发送欢迎消息
log_info("STM32F407VET6 系统初始化完成\r\n");
log_info("LED每500ms闪烁一次\r\n");
log_info("按键检测已启用\r\n");
log_debug("调试日志已启用\r\n");
// 初始化以太网
ethernet_init();
// 初始化LED
led_init_system();
// 初始化按键
bsp_key_init();
log_info("按键初始化完成\r\n");
// 初始化W25QXX
w25qxx_init_system();
}
/**
* @brief 以太网初始化函数
* @retval 无
*/
static void ethernet_init(void)
{
log_debug("开始以太网初始化...\r\n");
// 获取板级配置信息
const bsp_board_config_t* board_config = bsp_get_board_config();
bsp_eth_config_t eth_config = board_config->eth;
// 初始化以太网
if (bsp_eth_init(&eth_config) == HAL_RET_OK) {
log_info("以太网初始化成功\r\n");
// 获取以太网状态
bsp_eth_status_t eth_status;
if (bsp_eth_get_status(&eth_status) == HAL_RET_OK) {
log_info("以太网PHY ID: 0x%04X 0x%04X\r\n", eth_status.phy_id1, eth_status.phy_id2);
log_info("以太网连接状态: %s\r\n", eth_status.link_up ? "UP" : "DOWN");
if (eth_status.link_up) {
log_info("以太网速度: %lu Mbps\r\n", eth_status.speed);
log_info("以太网双工模式: %s\r\n", eth_status.duplex ? "全双工" : "半双工");
last_link_status = 1;
}
}
// 获取MAC地址
hal_eth_mac_addr_t mac_addr;
if (bsp_eth_get_mac_addr(&mac_addr) == HAL_RET_OK) {
log_info("以太网MAC地址: %02X:%02X:%02X:%02X:%02X:%02X\r\n",
mac_addr.byte[0], mac_addr.byte[1], mac_addr.byte[2],
mac_addr.byte[3], mac_addr.byte[4], mac_addr.byte[5]);
}
} else {
log_error("以太网初始化失败\r\n");
}
}
/**
* @brief LED初始化函数
* @retval 无
*/
static void led_init_system(void)
{
// 获取板级配置信息
const bsp_board_config_t* board_config = bsp_get_board_config();
// 从板级配置中获取LED配置
led_config_t led_config = {
.gpio_port = board_config->leds.leds[0].port,
.gpio_pin = board_config->leds.leds[0].pin
};
// 初始化LED
led_init(&led, &led_config);
log_info("LED初始化完成\r\n");
}
/**
* @brief W25QXX初始化函数
* @retval 无
*/
static void w25qxx_init_system(void)
{
log_debug("开始W25QXX初始化...\r\n");
// 初始化W25QXX
if (bsp_w25qxx_init()) {
log_info("W25QXX初始化成功\r\n");
// 获取设备信息
w25qxx_device_info_t device_info;
if (bsp_w25qxx_get_device_info(&device_info)) {
log_info("W25QXX制造商ID: 0x%02X\r\n", device_info.manufacturer_id);
log_info("W25QXX设备ID: 0x%04X\r\n", device_info.device_id);
log_info("W25QXX容量: %lu 字节\r\n", device_info.capacity);
log_info("W25QXX页大小: %u 字节\r\n", device_info.page_size);
log_info("W25QXX扇区大小: %lu 字节\r\n", device_info.sector_size);
log_info("W25QXX块大小: %lu 字节\r\n", device_info.block_size);
}
} else {
log_error("W25QXX初始化失败\r\n");
/* 即使初始化失败也尝试读取设备信息以调试SPI连接 */
w25qxx_device_info_t device_info;
if (bsp_w25qxx_get_device_info(&device_info)) {
log_error("调试 - 读取ID: 制造商=0x%02X, 设备=0x%04X\r\n",
device_info.manufacturer_id, device_info.device_id);
}
}
}
/**
* @brief 按键事件处理函数
* @retval 无
*/
static void key_events_handler(void)
{
/* KEY0事件 */
if (bsp_key_get_press_event(BSP_KEY_ID_KEY0)) {
log_info("KEY0按下\r\n");
}
if (bsp_key_get_release_event(BSP_KEY_ID_KEY0)) {
log_info("KEY0释放\r\n");
}
if (bsp_key_get_short_press_event(BSP_KEY_ID_KEY0)) {
log_info("KEY0短按\r\n");
}
if (bsp_key_get_long_press_event(BSP_KEY_ID_KEY0)) {
log_info("KEY0长按\r\n");
}
if (bsp_key_get_repeat_event(BSP_KEY_ID_KEY0)) {
log_info("KEY0重复按下\r\n");
}
/* KEY1事件 */
if (bsp_key_get_press_event(BSP_KEY_ID_KEY1)) {
log_info("KEY1按下\r\n");
}
if (bsp_key_get_release_event(BSP_KEY_ID_KEY1)) {
log_info("KEY1释放\r\n");
}
if (bsp_key_get_short_press_event(BSP_KEY_ID_KEY1)) {
log_info("KEY1短按\r\n");
}
if (bsp_key_get_long_press_event(BSP_KEY_ID_KEY1)) {
log_info("KEY1长按\r\n");
}
if (bsp_key_get_repeat_event(BSP_KEY_ID_KEY1)) {
log_info("KEY1重复按下\r\n");
}
/* WK_UP事件 */
if (bsp_key_get_press_event(BSP_KEY_ID_WKUP)) {
log_info("WK_UP按下\r\n");
}
if (bsp_key_get_release_event(BSP_KEY_ID_WKUP)) {
log_info("WK_UP释放\r\n");
}
if (bsp_key_get_short_press_event(BSP_KEY_ID_WKUP)) {
log_info("WK_UP短按\r\n");
}
if (bsp_key_get_long_press_event(BSP_KEY_ID_WKUP)) {
log_info("WK_UP长按\r\n");
}
if (bsp_key_get_repeat_event(BSP_KEY_ID_WKUP)) {
log_info("WK_UP重复按下\r\n");
}
}
/**
* @brief LED闪烁处理函数
* @retval 无
*/
static void led_blink_handler(void)
{
// 使用非阻塞定时器实现LED闪烁
if ((delay_get_tick() - led_toggle_timer) >= LED_TOGGLE_INTERVAL) {
led_toggle(&led); // 切换LED状态
log_debug("LED状态切换\r\n");
led_toggle_timer = delay_get_tick(); // 重置定时器
}
}
/**
* @brief 以太网状态处理函数
* @retval 无
*/
static void ethernet_status_handler(void)
{
// 定期检查以太网连接状态
if ((delay_get_tick() - eth_check_timer) >= ETH_CHECK_INTERVAL) {
uint8_t link_up;
if (bsp_eth_check_link(&link_up) == HAL_RET_OK) {
if (link_up != last_link_status) {
log_info("以太网连接状态改变: %s\r\n", link_up ? "UP" : "DOWN");
if (link_up) {
bsp_eth_status_t eth_status;
if (bsp_eth_get_status(&eth_status) == HAL_RET_OK) {
log_info("以太网速度: %lu Mbps\r\n", eth_status.speed);
log_info("以太网双工模式: %s\r\n", eth_status.duplex ? "全双工" : "半双工");
}
}
last_link_status = link_up;
}
}
eth_check_timer = delay_get_tick(); // 重置定时器
}
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
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_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief 错误处理函数
* @retval 无
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* 用户可以添加自己的实现来报告HAL错误返回状态 */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief 报告assert_param错误发生的源文件名和行号
* @param file: 指向源文件名的指针
* @param line: assert_param错误的源行号
* @retval 无
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* 用户可以添加自己的实现来报告文件名和行号,
例如: printf("参数值错误: 文件 %s 第 %d 行\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */