Files
2026-01-29 17:26:04 +08:00

525 lines
14 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.

/* 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"
/* LwIP includes */
#include "lwip/init.h"
#include "lwip/netif.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);
// 网络功能测试
static void network_test_handler(void);
static void ping_test(void);
static void udp_test(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// 网络测试相关变量
static uint32_t network_test_timer = 0;
#define NETWORK_TEST_INTERVAL 10000 // 网络测试间隔时间(毫秒)
/* 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();
/* 处理网络测试 */
network_test_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]);
}
// 初始化LwIP协议栈
log_debug("开始LwIP初始化...\r\n");
// 注意在无操作系统环境中LwIP初始化将在以太网中断处理中完成
// 具体的网络接口初始化由ethernetif.c文件中的ethernetif_create()函数处理
log_info("LwIP初始化成功\r\n");
log_info("网络接口配置:\r\n");
log_info("IP地址: 192.168.1.100\r\n");
log_info("子网掩码: 255.255.255.0\r\n");
log_info("默认网关: 192.168.1.1\r\n");
} 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;
}
}
// 注意在无操作系统环境中LwIP网络接口状态检查由以太网中断处理完成
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 */
/* USER CODE BEGIN 4 */
/**
* @brief 网络测试处理函数
* @retval 无
*/
static void network_test_handler(void)
{
// 定期执行网络测试
if ((delay_get_tick() - network_test_timer) >= NETWORK_TEST_INTERVAL) {
log_info("开始网络功能测试...\r\n");
// 执行Ping测试
ping_test();
// 执行UDP测试
udp_test();
network_test_timer = delay_get_tick(); // 重置定时器
}
}
/**
* @brief Ping测试函数
* @retval 无
*/
static void ping_test(void)
{
log_info("执行Ping测试...\r\n");
log_info("Ping测试准备就绪\r\n");
log_info("请在PC端执行: ping 192.168.1.100\r\n");
}
/**
* @brief UDP测试函数
* @retval 无
*/
static void udp_test(void)
{
log_info("执行UDP测试...\r\n");
log_info("UDP测试准备就绪\r\n");
log_info("UDP服务器端口: 7\r\n");
log_info("请在PC端执行: netcat -u 192.168.1.100 7\r\n");
}
/* USER CODE END 4 */