优化整定,DHCP有问题待优化

This commit is contained in:
冯佳
2026-03-09 15:34:18 +08:00
parent 20597d22e5
commit 925df72fa0
30 changed files with 2556 additions and 2002 deletions

57
drivers/hal/hal.c Normal file
View File

@ -0,0 +1,57 @@
/*
* 硬件抽象层实现
* 功能:实现硬件抽象层的初始化和操作结构体获取
* 依赖硬件STM32F407VE
* 跨平台适配点:通过不同平台的实现文件适配不同硬件
*/
#include "hal.h"
/* 前向声明平台特定的硬件抽象层实现 */
extern const hal_uart_ops_t stm32f4_uart_ops;
extern const hal_i2c_ops_t stm32f4_i2c_ops;
extern const hal_eth_ops_t stm32f4_eth_ops;
/* 硬件抽象层操作结构体 */
static const hal_ops_t hal_ops = {
.uart = &stm32f4_uart_ops,
.i2c = &stm32f4_i2c_ops,
.eth = &stm32f4_eth_ops
};
/**
* @brief 硬件抽象层初始化
* @return hal_status_t: 操作结果
* @note 初始化所有硬件抽象层组件
*/
hal_status_t hal_init(void)
{
hal_status_t status = HAL_STATUS_OK;
/* 初始化串口 */
if (hal_ops.uart->init(HAL_UART_BAUDRATE_115200) != HAL_STATUS_OK) {
status = HAL_STATUS_ERROR;
}
/* 初始化I2C */
if (hal_ops.i2c->init(HAL_I2C_CLOCK_SPEED_100K) != HAL_STATUS_OK) {
status = HAL_STATUS_ERROR;
}
/* 初始化以太网 */
if (hal_ops.eth->init() != HAL_STATUS_OK) {
status = HAL_STATUS_ERROR;
}
return status;
}
/**
* @brief 获取硬件抽象层操作结构体
* @return const hal_ops_t*: 硬件抽象层操作结构体指针
* @note 返回硬件抽象层操作结构体,用于访问各种硬件操作
*/
const hal_ops_t *hal_get_ops(void)
{
return &hal_ops;
}

74
drivers/hal/hal.h Normal file
View File

@ -0,0 +1,74 @@
/*
* 硬件抽象层通用接口
* 功能定义硬件抽象层的通用接口包括串口、I2C和以太网驱动
* 依赖硬件STM32F407VE
* 跨平台适配点:通过不同平台的实现文件适配不同硬件
*/
#ifndef HAL_H
#define HAL_H
#include <stdint.h>
#include "osal.h"
/* 硬件抽象层错误码 */
typedef enum {
HAL_STATUS_OK = 0,
HAL_STATUS_ERROR = -1,
HAL_STATUS_BUSY = -2,
HAL_STATUS_TIMEOUT = -3
} hal_status_t;
/* 串口波特率定义 */
typedef enum {
HAL_UART_BAUDRATE_9600 = 9600,
HAL_UART_BAUDRATE_115200 = 115200,
HAL_UART_BAUDRATE_460800 = 460800,
HAL_UART_BAUDRATE_921600 = 921600
} hal_uart_baudrate_t;
/* I2C时钟速度定义 */
typedef enum {
HAL_I2C_CLOCK_SPEED_100K = 100000,
HAL_I2C_CLOCK_SPEED_400K = 400000
} hal_i2c_clock_speed_t;
/* 串口硬件抽象层接口 */
typedef struct {
hal_status_t (*init)(hal_uart_baudrate_t baudrate);
hal_status_t (*deinit)(void);
hal_status_t (*send)(const uint8_t *data, uint32_t len);
hal_status_t (*recv)(uint8_t *data, uint32_t len, uint32_t timeout);
} hal_uart_ops_t;
/* I2C硬件抽象层接口 */
typedef struct {
hal_status_t (*init)(hal_i2c_clock_speed_t clock_speed);
hal_status_t (*deinit)(void);
hal_status_t (*master_transmit)(uint16_t dev_addr, const uint8_t *data, uint32_t len, uint32_t timeout);
hal_status_t (*master_receive)(uint16_t dev_addr, uint8_t *data, uint32_t len, uint32_t timeout);
} hal_i2c_ops_t;
/* 以太网硬件抽象层接口 */
typedef struct {
hal_status_t (*init)(void);
hal_status_t (*deinit)(void);
hal_status_t (*send)(const uint8_t *data, uint32_t len);
hal_status_t (*recv)(uint8_t *data, uint32_t *len, uint32_t timeout);
hal_status_t (*get_link_status)(void);
} hal_eth_ops_t;
/* 硬件抽象层操作结构体 */
typedef struct {
const hal_uart_ops_t *uart;
const hal_i2c_ops_t *i2c;
const hal_eth_ops_t *eth;
} hal_ops_t;
/* 硬件抽象层初始化函数 */
extern hal_status_t hal_init(void);
/* 获取硬件抽象层操作结构体 */
extern const hal_ops_t *hal_get_ops(void);
#endif /* HAL_H */

View File

@ -0,0 +1,444 @@
/*
* STM32F4以太网硬件抽象层实现
* 功能实现STM32F4平台的以太网硬件抽象层
* 依赖硬件STM32F407VE
* 跨平台适配点:通过硬件抽象层接口适配不同平台
*/
#include "hal.h"
#include "stm32f4xx_hal.h"
#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/timeouts.h"
#include "netif/etharp.h"
#include "lwip/ethip6.h"
#include <string.h>
/* 以太网句柄 */
static ETH_HandleTypeDef heth;
static uint32_t g_phy_address = 0; /* 存储PHY地址 */
static uint32_t g_last_link_check_time = 0; /* 上次链接状态检测时间 */
static uint32_t g_link_check_interval = 1000; /* 链接状态检测间隔 (ms) */
static uint8_t g_link_state_stable = 0; /* 链接状态稳定性标志 */
static uint8_t g_link_state_counter = 0; /* 链接状态计数器,用于防抖 */
/* DMA描述符和缓冲区 */
/* 优化缓冲区对齐方式,提高内存访问效率 */
__attribute__((section(".RxDecripSection"))) __attribute__((aligned(32))) static ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB];
__attribute__((section(".TxDecripSection"))) __attribute__((aligned(32))) static ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB];
__attribute__((section(".RxArraySection"))) __attribute__((aligned(32))) static uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
__attribute__((section(".TxArraySection"))) __attribute__((aligned(32))) static uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
/* 信号量 */
static osal_sem_t s_xSemaphore = NULL;
/**
* @brief 检测并配置PHY
* @return HAL_StatusTypeDef: 操作结果
* @note 负责检测PHY地址并进行配置
*/
static hal_status_t detect_and_configure_phy(void)
{
uint32_t phy_id1 = 0, phy_id2 = 0;
uint8_t detected_phy_addr = 0xFF; /* 无效的初始值 */
uint32_t regvalue;
/* 优先检查常见的PHY地址减少遍历次数 */
uint8_t common_phy_addresses[] = {0, 1, 2, 3, 16, 17, 18, 19, 20};
uint8_t common_phy_count = sizeof(common_phy_addresses) / sizeof(common_phy_addresses[0]);
/* 先检查常见地址 */
for(uint8_t i = 0; i < common_phy_count; i++) {
uint8_t addr = common_phy_addresses[i];
/* 读取PHY ID寄存器通常是Reg 2和3 */
if(HAL_ETH_ReadPHYRegister(&heth, addr, 2, &phy_id1) == HAL_OK &&
HAL_ETH_ReadPHYRegister(&heth, addr, 3, &phy_id2) == HAL_OK) {
if((phy_id1 != 0xFFFF) && (phy_id1 != 0x0000) && (phy_id1 != 0)) {
detected_phy_addr = addr;
osal_log_i("Found PHY at Address %d (ID: %04x %04x)", addr, phy_id1, phy_id2);
goto phy_found;
}
}
}
/* 如果常见地址没找到,再遍历所有可能的地址 */
for(uint8_t addr = 0; addr <= 31; addr++) {
/* 跳过已经检查过的常见地址 */
uint8_t skip = 0;
for(uint8_t i = 0; i < common_phy_count; i++) {
if(addr == common_phy_addresses[i]) {
skip = 1;
break;
}
}
if(skip) continue;
/* 读取PHY ID寄存器通常是Reg 2和3 */
if(HAL_ETH_ReadPHYRegister(&heth, addr, 2, &phy_id1) == HAL_OK &&
HAL_ETH_ReadPHYRegister(&heth, addr, 3, &phy_id2) == HAL_OK) {
if((phy_id1 != 0xFFFF) && (phy_id1 != 0x0000) && (phy_id1 != 0)) {
detected_phy_addr = addr;
osal_log_i("Found PHY at Address %d (ID: %04x %04x)", addr, phy_id1, phy_id2);
goto phy_found;
}
}
}
phy_found:
if (detected_phy_addr != 0xFF)
{
g_phy_address = detected_phy_addr;
/* PHY软复位 */
osal_log_i("Resetting PHY at address %d...", g_phy_address);
/* 写入复位位 */
HAL_ETH_WritePHYRegister(&heth, g_phy_address, PHY_BCR, PHY_RESET);
/* 等待复位完成 */
uint32_t tickstart = osal_tick_get();
uint32_t reset_timeout = 200; // 优化为200ms超时
do {
HAL_ETH_ReadPHYRegister(&heth, g_phy_address, PHY_BCR, &regvalue);
if((regvalue & PHY_RESET) == 0) break;
} while ((osal_tick_get() - tickstart) < reset_timeout); // 200ms超时
/* 添加延迟以确保PHY稳定 */
osal_thread_mdelay(50); // 优化为50ms延迟
return HAL_STATUS_OK;
}
else
{
osal_log_e("No PHY found!");
return HAL_STATUS_ERROR;
}
}
/**
* @brief 配置MAC
* @param macConf: MAC配置结构体指针
* @return 无
* @note 负责配置MAC的双工模式、速度和校验和等
*/
static void configure_mac(ETH_MACConfigTypeDef *macConf)
{
HAL_ETH_GetMACConfig(&heth, macConf);
macConf->DuplexMode = ETH_FULLDUPLEX_MODE;
macConf->Speed = ETH_SPEED_100M;
macConf->ChecksumOffload = ENABLE; /* 启用硬件校验和 */
HAL_ETH_SetMACConfig(&heth, macConf);
}
/**
* @brief 以太网初始化
* @return hal_status_t: 操作结果
* @note 初始化以太网硬件
*/
static hal_status_t stm32f4_eth_init(void)
{
/* 使用固定MAC地址避免冲突/过滤 */
uint8_t macaddress[6] = { 0x00, 0x80, 0xE1, 0x00, 0x00, 0x55 };
ETH_MACConfigTypeDef macConf;
HAL_StatusTypeDef hal_eth_init_status;
osal_log_i("MAC: %02x:%02x:%02x:%02x:%02x:%02x",
macaddress[0], macaddress[1], macaddress[2],
macaddress[3], macaddress[4], macaddress[5]);
/* 初始化ETH句柄 */
heth.Instance = ETH;
heth.Init.MACAddr = macaddress;
heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
heth.Init.TxDesc = DMATxDscrTab;
heth.Init.RxDesc = DMARxDscrTab;
heth.Init.RxBuffLen = ETH_RX_BUF_SIZE;
/* 初始化ETHMAC、DMA、GPIO通过MSP以启用MDC/MDIO */
hal_eth_init_status = HAL_ETH_Init(&heth);
if (hal_eth_init_status == HAL_OK)
{
/* 检测并配置PHY */
if (detect_and_configure_phy() == HAL_STATUS_OK)
{
/* 配置MAC */
configure_mac(&macConf);
/* 手动启用混杂模式,因为它不在结构体中 */
heth.Instance->MACFFR |= ETH_MACFFR_PM;
/* 启动ETH中断 */
HAL_ETH_Start_IT(&heth);
/* 创建信号量 */
s_xSemaphore = osal_sem_create("eth_sem", 0);
return HAL_STATUS_OK;
}
}
else
{
osal_log_e("HAL_ETH_Init failed");
}
return HAL_STATUS_ERROR;
}
/**
* @brief 以太网反初始化
* @return hal_status_t: 操作结果
* @note 反初始化以太网硬件
*/
static hal_status_t stm32f4_eth_deinit(void)
{
/* 停止ETH */
HAL_ETH_Stop(&heth);
/* 反初始化ETH */
if (HAL_ETH_DeInit(&heth) != HAL_OK) {
return HAL_STATUS_ERROR;
}
/* 删除信号量 */
if (s_xSemaphore != NULL) {
osal_sem_delete(s_xSemaphore);
s_xSemaphore = NULL;
}
return HAL_STATUS_OK;
}
/**
* @brief 以太网发送数据
* @param data: 数据指针
* @param len: 数据长度
* @return hal_status_t: 操作结果
* @note 发送数据
*/
static hal_status_t stm32f4_eth_send(const uint8_t *data, uint32_t len)
{
ETH_TxPacketConfigTypeDef txConfig;
ETH_BufferTypeDef txBuffer;
memset(&txConfig, 0, sizeof(ETH_TxPacketConfigTypeDef));
/* 启用硬件校验和插入 */
txConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
txConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
txConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
txBuffer.buffer = (uint8_t*)data;
txBuffer.len = len;
txBuffer.next = NULL;
txConfig.Length = len;
txConfig.TxBuffer = &txBuffer;
if (HAL_ETH_Transmit(&heth, &txConfig, 10) == HAL_OK) {
return HAL_STATUS_OK;
} else {
return HAL_STATUS_ERROR;
}
}
/**
* @brief 以太网接收数据
* @param data: 数据指针
* @param len: 数据长度指针
* @param timeout: 超时时间
* @return hal_status_t: 操作结果
* @note 接收数据
*/
static hal_status_t stm32f4_eth_recv(uint8_t *data, uint32_t *len, uint32_t timeout)
{
uint8_t *buffer = NULL;
uint32_t rxLength = 0;
if (s_xSemaphore == NULL) {
return HAL_STATUS_ERROR;
}
if (osal_sem_take(s_xSemaphore, timeout) != OSAL_OK) {
return HAL_STATUS_TIMEOUT;
}
if (HAL_ETH_ReadData(&heth, (void**)&buffer) == HAL_OK)
{
/* Get the received frame length from Rx descriptor list */
rxLength = heth.RxDescList.RxDataLength;
if (rxLength > 0 && buffer != NULL && data != NULL && len != NULL) {
memcpy(data, buffer, rxLength);
*len = rxLength;
return HAL_STATUS_OK;
}
}
return HAL_STATUS_ERROR;
}
/**
* @brief 获取以太网链接状态
* @return hal_status_t: 操作结果
* @note 获取以太网链接状态
*/
static hal_status_t stm32f4_eth_get_link_status(void)
{
uint32_t regvalue = 0;
uint32_t current_time = osal_tick_get();
/* 实现时间间隔控制减少PHY寄存器读取 */
if ((current_time - g_last_link_check_time) < g_link_check_interval)
{
return g_link_state_stable ? HAL_STATUS_OK : HAL_STATUS_ERROR;
}
g_last_link_check_time = current_time;
/* 检查PHY地址是否有效 */
if (g_phy_address == 0 || g_phy_address > 31) {
osal_log_e("Invalid PHY address: %d", g_phy_address);
g_link_state_stable = 0;
g_link_state_counter = 0;
return HAL_STATUS_ERROR;
}
/* 使用配置的PHY地址读取状态寄存器 */
HAL_StatusTypeDef status = HAL_ETH_ReadPHYRegister(&heth, g_phy_address, PHY_BSR, &regvalue);
if (status != HAL_OK) {
osal_log_e("Failed to read PHY register, status=%d", status);
g_link_state_counter--;
if (g_link_state_counter <= 0) {
g_link_state_counter = 0;
g_link_state_stable = 0;
}
return HAL_STATUS_ERROR;
}
osal_log_i("PHY BSR=0x%04x, LinkStatus=%d", regvalue, (regvalue & PHY_LINKED_STATUS) != 0);
if ((regvalue & PHY_LINKED_STATUS) != 0)
{
/* 链接状态防抖 */
g_link_state_counter++;
if (g_link_state_counter >= 3) /* 连续3次检测到链接状态为up */
{
g_link_state_stable = 1;
}
return HAL_STATUS_OK;
}
else
{
/* 链接状态防抖 */
g_link_state_counter--;
if (g_link_state_counter <= 0) /* 连续3次检测到链接状态为down */
{
g_link_state_counter = 0;
g_link_state_stable = 0;
}
return HAL_STATUS_ERROR;
}
}
/* 以太网硬件抽象层操作结构体 */
const hal_eth_ops_t stm32f4_eth_ops = {
.init = stm32f4_eth_init,
.deinit = stm32f4_eth_deinit,
.send = stm32f4_eth_send,
.recv = stm32f4_eth_recv,
.get_link_status = stm32f4_eth_get_link_status
};
/**
* @brief 以太网Rx完成回调
* @param heth: 以太网句柄
* @return 无
* @note 以太网接收完成回调函数
*/
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
(void)heth;
if (s_xSemaphore != NULL)
{
osal_sem_release(s_xSemaphore);
}
}
/**
* @brief 以太网Rx分配回调
* @param buff: 缓冲区指针
* @return 无
* @note 以太网接收缓冲区分配回调函数
*/
void HAL_ETH_RxAllocateCallback(uint8_t **buff)
{
static int rx_idx = 0;
*buff = Rx_Buff[rx_idx];
rx_idx = (rx_idx + 1) % ETH_RXBUFNB;
}
/**
* @brief 以太网Rx链接回调
* @param pStart: 开始指针
* @param pEnd: 结束指针
* @param buff: 缓冲区指针
* @param Length: 长度
* @return 无
* @note 以太网接收链接回调函数
*/
void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length)
{
(void)Length;
*pStart = (void *)buff;
*pEnd = (void *)buff;
}
/**
* @brief 以太网中断处理函数
* @return 无
* @note 以太网中断处理函数
*/
void ETH_IRQHandler(void)
{
/* 直接调用HAL中断处理函数不使用全局临界区
* HAL_ETH_IRQHandler内部已经有适当的中断保护机制
*/
HAL_ETH_IRQHandler(&heth);
}
/**
* @brief 以太网MSP初始化
* @param heth: 以太网句柄
* @return 无
* @note 初始化以太网的MSP
*/
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
{
(void)heth;
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_ETH_CLK_ENABLE();
/* PA1, PA2, PA7 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* PC1, PC4, PC5 */
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/* PB11, PB12, PB13 */
GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
HAL_NVIC_SetPriority(ETH_IRQn, 0x07, 0);
HAL_NVIC_EnableIRQ(ETH_IRQn);
}

View File

@ -0,0 +1,144 @@
/*
* STM32F4 I2C硬件抽象层实现
* 功能实现STM32F4平台的I2C硬件抽象层
* 依赖硬件STM32F407VE
* 跨平台适配点:通过硬件抽象层接口适配不同平台
*/
#include "hal.h"
#include "stm32f4xx_hal.h"
/* I2C句柄 */
static I2C_HandleTypeDef hi2c1;
/**
* @brief I2C初始化
* @param clock_speed: 时钟速度
* @return hal_status_t: 操作结果
* @note 初始化I2C硬件
*/
static hal_status_t stm32f4_i2c_init(hal_i2c_clock_speed_t clock_speed)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = clock_speed;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
return HAL_STATUS_ERROR;
}
return HAL_STATUS_OK;
}
/**
* @brief I2C反初始化
* @return hal_status_t: 操作结果
* @note 反初始化I2C硬件
*/
static hal_status_t stm32f4_i2c_deinit(void)
{
if (HAL_I2C_DeInit(&hi2c1) != HAL_OK) {
return HAL_STATUS_ERROR;
}
return HAL_STATUS_OK;
}
/**
* @brief I2C主模式发送数据
* @param dev_addr: 设备地址
* @param data: 数据指针
* @param len: 数据长度
* @param timeout: 超时时间
* @return hal_status_t: 操作结果
* @note 发送数据,使用阻塞方式
*/
static hal_status_t stm32f4_i2c_master_transmit(uint16_t dev_addr, const uint8_t *data, uint32_t len, uint32_t timeout)
{
if (HAL_I2C_Master_Transmit(&hi2c1, dev_addr, (uint8_t *)data, len, timeout) != HAL_OK) {
return HAL_STATUS_ERROR;
}
return HAL_STATUS_OK;
}
/**
* @brief I2C主模式接收数据
* @param dev_addr: 设备地址
* @param data: 数据指针
* @param len: 数据长度
* @param timeout: 超时时间
* @return hal_status_t: 操作结果
* @note 接收数据,使用阻塞方式
*/
static hal_status_t stm32f4_i2c_master_receive(uint16_t dev_addr, uint8_t *data, uint32_t len, uint32_t timeout)
{
if (HAL_I2C_Master_Receive(&hi2c1, dev_addr, data, len, timeout) != HAL_OK) {
return HAL_STATUS_ERROR;
}
return HAL_STATUS_OK;
}
/* I2C硬件抽象层操作结构体 */
const hal_i2c_ops_t stm32f4_i2c_ops = {
.init = stm32f4_i2c_init,
.deinit = stm32f4_i2c_deinit,
.master_transmit = stm32f4_i2c_master_transmit,
.master_receive = stm32f4_i2c_master_receive
};
/**
* @brief I2C MSP初始化
* @param i2cHandle: I2C句柄
* @return 无
* @note 初始化I2C的MSP
*/
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(i2cHandle->Instance==I2C1)
{
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
}
/**
* @brief I2C MSP反初始化
* @param i2cHandle: I2C句柄
* @return 无
* @note 反初始化I2C的MSP
*/
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{
if(i2cHandle->Instance==I2C1)
{
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);
}
}

View File

@ -0,0 +1,140 @@
/*
* STM32F4串口硬件抽象层实现
* 功能实现STM32F4平台的串口硬件抽象层
* 依赖硬件STM32F407VE
* 跨平台适配点:通过硬件抽象层接口适配不同平台
*/
#include "hal.h"
#include "stm32f4xx_hal.h"
/* 串口句柄 */
static UART_HandleTypeDef huart1;
/**
* @brief 串口初始化
* @param baudrate: 波特率
* @return hal_status_t: 操作结果
* @note 初始化串口硬件
*/
static hal_status_t stm32f4_uart_init(hal_uart_baudrate_t baudrate)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = baudrate;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK) {
return HAL_STATUS_ERROR;
}
return HAL_STATUS_OK;
}
/**
* @brief 串口反初始化
* @return hal_status_t: 操作结果
* @note 反初始化串口硬件
*/
static hal_status_t stm32f4_uart_deinit(void)
{
if (HAL_UART_DeInit(&huart1) != HAL_OK) {
return HAL_STATUS_ERROR;
}
return HAL_STATUS_OK;
}
/**
* @brief 串口发送数据
* @param data: 数据指针
* @param len: 数据长度
* @return hal_status_t: 操作结果
* @note 发送数据,使用阻塞方式
*/
static hal_status_t stm32f4_uart_send(const uint8_t *data, uint32_t len)
{
if (HAL_UART_Transmit(&huart1, (uint8_t *)data, len, 1000) != HAL_OK) {
return HAL_STATUS_ERROR;
}
return HAL_STATUS_OK;
}
/**
* @brief 串口接收数据
* @param data: 数据指针
* @param len: 数据长度
* @param timeout: 超时时间
* @return hal_status_t: 操作结果
* @note 接收数据,使用阻塞方式
*/
static hal_status_t stm32f4_uart_recv(uint8_t *data, uint32_t len, uint32_t timeout)
{
if (HAL_UART_Receive(&huart1, data, len, timeout) != HAL_OK) {
return HAL_STATUS_ERROR;
}
return HAL_STATUS_OK;
}
/* 串口硬件抽象层操作结构体 */
const hal_uart_ops_t stm32f4_uart_ops = {
.init = stm32f4_uart_init,
.deinit = stm32f4_uart_deinit,
.send = stm32f4_uart_send,
.recv = stm32f4_uart_recv
};
/**
* @brief UART MSP初始化
* @param uartHandle: UART句柄
* @return 无
* @note 初始化UART的MSP
*/
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART1)
{
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
}
/**
* @brief UART MSP反初始化
* @param uartHandle: UART句柄
* @return 无
* @note 反初始化UART的MSP
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART1)
{
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
}
}