797 lines
20 KiB
C
797 lines
20 KiB
C
/* USER CODE BEGIN Header */
|
||
/**
|
||
******************************************************************************
|
||
* @file ht24lc02_eeprom.c
|
||
* @author Motor Control SDK Team, Yuwell Software XiangenWang
|
||
* @brief Voice Recognition Module Initialization Section,
|
||
including peripheral initialization and message node insertion, etc.
|
||
* @version 1.0
|
||
* @changelog version 1.0 初始版本 2025.11.17
|
||
- 新增:新建第一个版本的软件,待完善解析命令后的程序执行部分
|
||
******************************************************************************
|
||
* @attention
|
||
*
|
||
* <h2><center>© Copyright (c) 2025 Yuwell Software Danyang.Jiangsu.China.
|
||
* All rights reserved.</center></h2>
|
||
*
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted, provided that the following conditions are met:
|
||
*
|
||
* 1. Redistribution of source code must retain the above copyright notice,
|
||
* this list of conditions and the following disclaimer.
|
||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||
* this list of conditions and the following disclaimer in the documentation
|
||
* and/or other materials provided with the distribution.
|
||
* 3. Neither the name of Yuwell Software nor the names of other
|
||
* contributors to this software may be used to endorse or promote products
|
||
* derived from this software without specific written permission.
|
||
* 4. This software, including modifications and/or derivative works of this
|
||
* software, must execute solely and exclusively on microcontroller or
|
||
* microprocessor devices manufactured by or for Yuwell Software.
|
||
* 5. Redistribution and use of this software other than as permitted under
|
||
* this license is void and will automatically terminate your rights under
|
||
* this license.
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED BY Yuwell Software AND CONTRIBUTORS "AS IS"
|
||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||
* SHALL Yuwell Software OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
*
|
||
******************************************************************************
|
||
*/
|
||
/* USER CODE END Header */
|
||
#include "ht24lc02_eeprom.h"
|
||
|
||
#define HT24LC02_SDA_SET() FL_GPIO_SetOutputPin(EEPROM_24LC02_SDA_GROUP,EEPROM_24LC02_SDA_PIN)
|
||
#define HT24LC02_SCL_SET() FL_GPIO_SetOutputPin(EEPROM_24LC02_SCL_GROUP,EEPROM_24LC02_SCL_PIN)
|
||
|
||
#define HT24LC02_SDA_CLR() FL_GPIO_ResetOutputPin(EEPROM_24LC02_SDA_GROUP,EEPROM_24LC02_SDA_PIN)
|
||
#define HT24LC02_SCL_CLR() FL_GPIO_ResetOutputPin(EEPROM_24LC02_SCL_GROUP,EEPROM_24LC02_SCL_PIN)
|
||
|
||
#define EEPROM_WP_DISABLE() FL_GPIO_ResetOutputPin(EEPROM_24LC02_WP_GROUP,EEPROM_24LC02_WP_PIN)
|
||
#define EEPROM_WP_ENABLE() FL_GPIO_SetOutputPin(EEPROM_24LC02_WP_GROUP,EEPROM_24LC02_WP_PIN)
|
||
|
||
|
||
|
||
|
||
// 存储每个uint32_t数据的起始地址数组(共64个元素,索引0~63对应块0~块63)
|
||
const uint8_t eeprom_start_addr[BLOCK_NUM] =
|
||
{
|
||
0x00, 0x04, 0x08, 0x0C, // 块0~块3:地址0x00~0x0F(前16字节)
|
||
0x10, 0x14, 0x18, 0x1C, // 块4~块7:地址0x10~0x1F
|
||
0x20, 0x24, 0x28, 0x2C, // 块8~块11:地址0x20~0x2F
|
||
0x30, 0x34, 0x38, 0x3C, // 块12~块15:地址0x30~0x3F
|
||
0x40, 0x44, 0x48, 0x4C, // 块16~块19:地址0x40~0x4F
|
||
0x50, 0x54, 0x58, 0x5C, // 块20~块23:地址0x50~0x5F
|
||
0x60, 0x64, 0x68, 0x6C, // 块24~块27:地址0x60~0x6F
|
||
0x70, 0x74, 0x78, 0x7C, // 块28~块31:地址0x70~0x7F
|
||
0x80, 0x84, 0x88, 0x8C, // 块32~块35:地址0x80~0x8F
|
||
0x90, 0x94, 0x98, 0x9C, // 块36~块39:地址0x90~0x9F
|
||
0xA0, 0xA4, 0xA8, 0xAC, // 块40~块43:地址0xA0~0xAF
|
||
0xB0, 0xB4, 0xB8, 0xBC, // 块44~块47:地址0xB0~0xBF
|
||
0xC0, 0xC4, 0xC8, 0xCC, // 块48~块51:地址0xC0~0xCF
|
||
0xD0, 0xD4, 0xD8, 0xDC, // 块52~块55:地址0xD0~0xDF
|
||
0xE0, 0xE4, 0xE8, 0xEC, // 块56~块59:地址0xE0~0xEF
|
||
0xF0, 0xF4, 0xF8, 0xFC // 块60~块63:地址0xF0~0xFF(最后16字节)
|
||
};
|
||
|
||
|
||
typedef enum
|
||
{
|
||
ACK,
|
||
NACK
|
||
}TYPE_ACK;
|
||
|
||
typedef enum
|
||
{
|
||
INPUT,
|
||
OUTPUT
|
||
}SDA_MODE;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/************************************************** 静态子函数定义 **************************************************/
|
||
|
||
/**
|
||
* @brief 延时以适配I2C时序
|
||
* @param us 需要延时的微秒数
|
||
* @retval NONE
|
||
* @note
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void i2c_delay_us(uint32_t us)
|
||
{
|
||
FL_DelayUs(us); // 需根据MCU主频校准,确保实际延时≈1us
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief SDA引脚输入或输出模式配置
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note 为什么开漏输出无法读到数据呢?
|
||
* 真是让人头大
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void i2c_sda_mode_set(SDA_MODE mode)
|
||
{
|
||
FL_GPIO_InitTypeDef GPIO_InitStruct;
|
||
|
||
if(mode == INPUT)
|
||
{
|
||
GPIO_InitStruct.pin = EEPROM_24LC02_SDA_PIN;
|
||
GPIO_InitStruct.mode = FL_GPIO_MODE_INPUT;
|
||
GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_OPENDRAIN;
|
||
GPIO_InitStruct.pull = FL_DISABLE;
|
||
GPIO_InitStruct.remapPin = FL_DISABLE;
|
||
GPIO_InitStruct.analogSwitch = FL_DISABLE;
|
||
|
||
FL_GPIO_Init(EEPROM_24LC02_SDA_GROUP, &GPIO_InitStruct);
|
||
}else{
|
||
GPIO_InitStruct.pin = EEPROM_24LC02_SDA_PIN; // 每次发送接收之前我还得把IO口初始化?
|
||
GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT; // 那我要开漏输出何用?
|
||
GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_OPENDRAIN;
|
||
GPIO_InitStruct.pull = FL_DISABLE;
|
||
GPIO_InitStruct.remapPin = FL_DISABLE;
|
||
GPIO_InitStruct.analogSwitch = FL_DISABLE;
|
||
|
||
FL_GPIO_Init(EEPROM_24LC02_SDA_GROUP, &GPIO_InitStruct);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 发送起始条件(SDA高→低,SCL保持高)
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void i2c_start(void)
|
||
{
|
||
i2c_sda_mode_set(OUTPUT);
|
||
HT24LC02_SDA_SET();
|
||
HT24LC02_SCL_SET();
|
||
|
||
i2c_delay_us(1);
|
||
HT24LC02_SDA_CLR();
|
||
i2c_delay_us(1);
|
||
HT24LC02_SCL_CLR();
|
||
i2c_delay_us(1);
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 发送停止条件(SDA低→高,SCL保持高)
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void i2c_stop(void)
|
||
{
|
||
i2c_sda_mode_set(OUTPUT);
|
||
HT24LC02_SDA_CLR();
|
||
HT24LC02_SCL_CLR();
|
||
i2c_delay_us(1); // 满足t_SU:STO最小250ns
|
||
HT24LC02_SCL_SET();
|
||
i2c_delay_us(1); // 满足t_SU:STO最小250ns
|
||
HT24LC02_SDA_SET();
|
||
i2c_delay_us(1);
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 发送1字节数据
|
||
* @param dat 要发送的数据
|
||
* @retval NONE
|
||
* @note
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void i2c_sendByte(uint8_t dat)
|
||
{
|
||
|
||
uint8_t i;
|
||
|
||
i2c_sda_mode_set(OUTPUT);
|
||
|
||
for(i = 0; i < 8; i++)
|
||
{
|
||
HT24LC02_SCL_CLR();
|
||
i2c_delay_us(1);
|
||
|
||
if(dat & 0x80)
|
||
{
|
||
HT24LC02_SDA_SET();
|
||
}else{
|
||
HT24LC02_SDA_CLR();
|
||
}
|
||
|
||
i2c_delay_us(1); // 满足t_SU:DAT最小100ns
|
||
HT24LC02_SCL_SET();
|
||
i2c_delay_us(1); // 满足t_HIGH最小400ns
|
||
dat <<= 1;
|
||
}
|
||
HT24LC02_SCL_CLR();
|
||
i2c_delay_us(1);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 接收1字节数据
|
||
* @param ack 接受一个字节的数据
|
||
* @retval NONE
|
||
* @note
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static uint8_t i2c_recvByte(TYPE_ACK ack)
|
||
{
|
||
uint8_t dat = 0;
|
||
uint32_t EEcount = 0;
|
||
|
||
i2c_sda_mode_set(OUTPUT);
|
||
HT24LC02_SDA_SET(); // 释放SDA
|
||
|
||
i2c_sda_mode_set(INPUT);
|
||
for(uint8_t i=0; i<8; i++)
|
||
{
|
||
HT24LC02_SCL_CLR();
|
||
i2c_delay_us(1);
|
||
HT24LC02_SCL_SET();
|
||
i2c_delay_us(5); // 满足t_AA最大600ns
|
||
dat <<= 1;
|
||
|
||
if(FL_GPIO_GetInputPin(EEPROM_24LC02_SDA_GROUP,EEPROM_24LC02_SDA_PIN))
|
||
{
|
||
dat |= 0x01;
|
||
EEcount++;
|
||
}
|
||
}
|
||
HT24LC02_SCL_CLR();
|
||
i2c_delay_us(1);
|
||
|
||
i2c_sda_mode_set(OUTPUT);
|
||
// 发送ACK/NACK
|
||
if(ack == ACK)
|
||
{
|
||
HT24LC02_SDA_CLR();
|
||
}else{
|
||
HT24LC02_SDA_SET();
|
||
}
|
||
|
||
HT24LC02_SCL_SET();
|
||
i2c_delay_us(1);
|
||
HT24LC02_SCL_CLR();
|
||
i2c_delay_us(1);
|
||
|
||
return dat;
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 等待从机ACK
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static TYPE_ACK i2c_waitAck(void)
|
||
{
|
||
TYPE_ACK ack = NACK;
|
||
i2c_sda_mode_set(OUTPUT);
|
||
|
||
HT24LC02_SDA_SET(); // 释放SDA
|
||
HT24LC02_SCL_CLR();
|
||
i2c_delay_us(1);
|
||
HT24LC02_SCL_SET();
|
||
i2c_delay_us(1);
|
||
|
||
i2c_sda_mode_set(INPUT);
|
||
if(!FL_GPIO_GetInputPin(EEPROM_24LC02_SDA_GROUP,EEPROM_24LC02_SDA_PIN))
|
||
{
|
||
ack = ACK; // 检测到低电平为ACK
|
||
}
|
||
|
||
HT24LC02_SCL_CLR();
|
||
i2c_delay_us(1);
|
||
|
||
return ack;
|
||
}
|
||
|
||
|
||
|
||
/************************************************** 外部API函数函数定义 **************************************************/
|
||
/**
|
||
* @brief 将多个字节数据写入到EEPROM中
|
||
* @param data 要写入数据的起始地址
|
||
addr 芯片存储数据的地址
|
||
len 数据总长度
|
||
* @retval NONE
|
||
* @note 注意EEPROM使用规则 不可跨页写入
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void ht24lc02_multiByte_write(uint8_t* data,uint16_t addr,uint8_t len)
|
||
{
|
||
uint8_t i;
|
||
|
||
if((addr + len) > HT24LC02_ADDR_MAX)
|
||
{
|
||
return;
|
||
}
|
||
|
||
i2c_start();
|
||
i2c_sendByte(HT24LC02_ADDR | 0x00); // 写命令(0x00)
|
||
if (i2c_waitAck())
|
||
{
|
||
i2c_stop(); // 未收到ACK,释放总线
|
||
return;
|
||
}
|
||
|
||
i2c_sendByte(addr & 0xFF);
|
||
if (i2c_waitAck())
|
||
{
|
||
i2c_stop(); // 未收到ACK,释放总线
|
||
return;
|
||
}
|
||
|
||
for(i = 0;i < len;i++)
|
||
{
|
||
|
||
i2c_sendByte(data[i]);
|
||
if (i2c_waitAck())
|
||
{
|
||
i2c_stop(); // 未收到ACK,释放总线
|
||
return;
|
||
}
|
||
}
|
||
|
||
i2c_stop();
|
||
i2c_delay_us(5000);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 将多个字节数据读取
|
||
* @param data 要读取数据的起始地址
|
||
addr 芯片存储数据的地址
|
||
len 数据总长度
|
||
* @retval NONE
|
||
* @note 注意EEPROM使用规则 不可跨页读取
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void ht24lc02_multiByte_read(uint8_t* data,uint16_t addr,uint8_t len)
|
||
{
|
||
uint8_t i;
|
||
|
||
if((addr + len) > HT24LC02_ADDR_MAX)
|
||
{
|
||
return;
|
||
}
|
||
|
||
i2c_start();
|
||
// 发送器件地址+写命令(先指定要读取的“专属地址”)
|
||
i2c_sendByte(HT24LC02_ADDR | 0x00);
|
||
if (i2c_waitAck())
|
||
{
|
||
i2c_stop(); // 未收到ACK,发送Stop释放总线
|
||
return;
|
||
}
|
||
|
||
i2c_sendByte(addr);
|
||
if (i2c_waitAck())
|
||
{
|
||
i2c_stop(); // 未收到ACK,释放总线
|
||
return;
|
||
}
|
||
|
||
i2c_start(); // 重复起始条件,切换为读命令
|
||
|
||
i2c_sendByte(HT24LC02_ADDR | 0x01); // 读命令(0x01)
|
||
if (i2c_waitAck())
|
||
{
|
||
i2c_stop(); // 未收到ACK,释放总线
|
||
return;
|
||
}
|
||
|
||
for(i = 0; i < len; i++)
|
||
{
|
||
|
||
if(i == (len-1))
|
||
{
|
||
data[i] = i2c_recvByte(NACK);
|
||
}else{
|
||
|
||
data[i] = i2c_recvByte(ACK);
|
||
}
|
||
|
||
}
|
||
i2c_stop();
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 将4个字节数据写入到EEPROM中
|
||
* @param word 要写入数据
|
||
addr_index 芯片存储数据的地址
|
||
* @retval NONE
|
||
* @note 注意EEPROM使用规则 不可跨页写入
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
void ht24lc02_word_write(uint32_t word, uint8_t addr_index)
|
||
{
|
||
uint8_t data[4];
|
||
uint8_t i;
|
||
|
||
for(i = 0; i < 4; i++)
|
||
{
|
||
data[3-i] = (word >> (i*8)) & 0xFF;
|
||
}
|
||
|
||
ht24lc02_multiByte_write(data, eeprom_start_addr[addr_index], 4);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 将4个字节数据读取到外部
|
||
* @param data 要读取数据的起始地址
|
||
addr 芯片存储数据的地址
|
||
* @retval NONE
|
||
* @note 注意EEPROM使用规则 不可跨页读取
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void ht24lc02_word_read(uint32_t* ptr_word, uint8_t addr_index)
|
||
{
|
||
uint8_t data[4];
|
||
uint32_t world = 0;;
|
||
uint8_t i;
|
||
|
||
ht24lc02_multiByte_read(data, eeprom_start_addr[addr_index], 4);
|
||
|
||
for(i = 0; i < 4; i++)
|
||
{
|
||
world += (data[3-i] << (i*8));
|
||
}
|
||
*ptr_word = world;
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 获取总累时 小时数
|
||
* @param NONE
|
||
* @retval 返回uint32_t 类型的四个字节的累时数据
|
||
* @note NONE
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static uint32_t ht24lc02_get_total_hours(void)
|
||
{
|
||
uint32_t totalTime = 0;
|
||
ht24lc02_word_read(&totalTime, INDEX_TOTAL_HOURS);
|
||
return totalTime;
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 获取总累时 分钟数
|
||
* @param NONE
|
||
* @retval 返回uint32_t 类型的四个字节的累时数据
|
||
* @note NONE
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static uint32_t ht24lc02_get_total_minutes(void)
|
||
{
|
||
uint32_t totalTime = 0;
|
||
ht24lc02_word_read(&totalTime, INDEX_TOTAL_MINUTES);
|
||
return totalTime;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 设定总累时 小时数
|
||
* @param 设置uint32_t 类型的四个字节的累时数据
|
||
* @retval NONE
|
||
* @note NONE
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void ht24lc02_set_total_hours(uint32_t hours)
|
||
{
|
||
if(hours > 19999)
|
||
{
|
||
hours = 19999;
|
||
}
|
||
ht24lc02_word_write(hours, INDEX_TOTAL_HOURS);
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 设定总累时 分钟数
|
||
* @param 设置uint32_t 类型的四个字节的累时数据
|
||
* @retval NONE
|
||
* @note NONE
|
||
* @author 王向恩
|
||
* @data 2025.11.19
|
||
*/
|
||
static void ht24lc02_set_total_minutes(uint32_t minutes)
|
||
{
|
||
ht24lc02_word_write(minutes, INDEX_TOTAL_MINUTES);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 根据地址获取四个字节数据
|
||
* @param 数据存储地址的索引值
|
||
* @retval 存储的uint16_t数据
|
||
* @note NONE
|
||
* @author 王向恩
|
||
* @data 2025.12.03
|
||
*/
|
||
static uint32_t ht24lc02_get_uint32_by_index(uint8_t addr_index)
|
||
{
|
||
uint32_t ret = 0;
|
||
uint8_t data[4];
|
||
uint8_t i;
|
||
|
||
ht24lc02_multiByte_read(data, eeprom_start_addr[addr_index], 4);
|
||
|
||
|
||
for(i = 0; i < 4; i++)
|
||
{
|
||
ret += (data[3-i] << (i*8));
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
|
||
|
||
/************************** 对外导出的API函数 *************************/
|
||
/**
|
||
* @brief 初始化EERPOM对应的硬件并向队列中下发一个当前累时数据
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note NONE
|
||
* @author 王向恩
|
||
* @data 2025.11.25
|
||
*/
|
||
void eeprom_ht24lc02_init(void)
|
||
{
|
||
|
||
FL_GPIO_InitTypeDef GPIO_InitStruct;
|
||
MsgQueueItem queue_item;
|
||
MsgQueueItem filter_item;
|
||
|
||
GPIO_InitStruct.pin = EEPROM_24LC02_WP_PIN;
|
||
GPIO_InitStruct.mode = FL_GPIO_MODE_OUTPUT;
|
||
GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
|
||
GPIO_InitStruct.pull = FL_ENABLE;
|
||
GPIO_InitStruct.remapPin = FL_DISABLE;
|
||
GPIO_InitStruct.analogSwitch = FL_DISABLE;
|
||
|
||
FL_GPIO_Init(EEPROM_24LC02_WP_GROUP, &GPIO_InitStruct); // 配置WP为输出模式
|
||
|
||
GPIO_InitStruct.pin = EEPROM_24LC02_SCL_PIN;
|
||
FL_GPIO_Init(EEPROM_24LC02_SCL_GROUP, &GPIO_InitStruct); // 配置SCL为输出模式
|
||
|
||
GPIO_InitStruct.pin = EEPROM_24LC02_SDA_PIN;
|
||
GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_OPENDRAIN;
|
||
FL_GPIO_Init(EEPROM_24LC02_SDA_GROUP, &GPIO_InitStruct); // 配置SDA为开漏输出模式
|
||
|
||
// 向当前队列中插入包含累时的信息
|
||
queue_item.type = MSG_TYPE_TIME_SEND;
|
||
queue_item.data.hour_meter.hour = ht24lc02_get_total_hours(); // 获取当前累时 小时数
|
||
queue_item.data.hour_meter.minute = ht24lc02_get_total_minutes(); // 获取当前累时 分钟数
|
||
|
||
insert_queue_node_in_head(&global_queue, queue_item);
|
||
|
||
// 向当前队列中插入包含报警点的信息
|
||
queue_item.type = MSG_TYPE_AD_BOUNDARY_SEND;
|
||
queue_item.data.adc_boundary.elec_low_boundary = EEPROM_E3_ELEC_LOW_VALUE; // E3 电流过小,通过程序给定
|
||
queue_item.data.adc_boundary.elec_high_boundary = ht24lc02_get_uint32_by_index(INDEX_E4_ELEC_HIGH); // E4 电流过大读取EEPROM中的值
|
||
|
||
queue_item.data.adc_boundary.ntc_low_boundary = 0; // NTC太低不管他 给他随意值
|
||
queue_item.data.adc_boundary.ntc_high_boundary = EEPROM_E5_NTC_HIGH_VALUE; // E5 通过程序给个值
|
||
|
||
queue_item.data.adc_boundary.press_low_boundary = ht24lc02_get_uint32_by_index(INDEX_E1_PRESS_LOW); // E1 读取EEPROM中标定的值
|
||
queue_item.data.adc_boundary.press_high_boundary = ht24lc02_get_uint32_by_index(INDEX_E2_PRESS_HIGH); // E2 读取EEPROM中标定的值
|
||
|
||
queue_item.data.adc_boundary.net220v_low_boundary = ht24lc02_get_uint32_by_index(INDEX_E7_220V_LOW); // E7 读取EEPROM中的值
|
||
queue_item.data.adc_boundary.net220v_high_boundary = 0; // 不使用 随便给个值
|
||
|
||
insert_queue_node_in_head(&global_queue, queue_item);
|
||
|
||
|
||
|
||
// 判定是否曾发生过清洁/更换滤清器事件
|
||
filter_item.type = MSG_TYPE_FILTER_SERVER;
|
||
|
||
filter_item.data.filter_server.last_clean_filter_hours = ht24lc02_get_uint32_by_index(INDEX_LAST_CLEAN_FILTER_HOURS);
|
||
filter_item.data.filter_server.last_replace_filter_hours = ht24lc02_get_uint32_by_index(INDEX_LAST_REPLACE_FILTER_HOURS);
|
||
|
||
filter_item.data.filter_server.clean_filter_time_need_stored = false;
|
||
filter_item.data.filter_server.replace_filter_time_need_stored = false;
|
||
|
||
insert_queue_node_in_head(&global_queue, filter_item);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 根据队列内容向EEPROM中存入当前小时数或分钟数
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note 放入定时器任务中周期性执行
|
||
* @author 王向恩
|
||
* @data 2025.11.25
|
||
*/
|
||
void eeprom_ht24lc02_save_task(MessageQueue* queue)
|
||
{
|
||
uint32_t hours = 0;
|
||
uint32_t minutes = 0;
|
||
MsgQueueItem queue_item;
|
||
MsgQueueItem adc_item;
|
||
MsgQueueItem carlib_item;
|
||
MsgQueueItem filter_item;
|
||
bool result = false;
|
||
|
||
result = remove_queue_node_by_type(&global_queue, MSG_TYPE_HOUR_SAVE, &queue_item); // 取出队列中对应类型的数据
|
||
if(result)
|
||
{
|
||
hours = queue_item.data.hour_meter.hour;
|
||
ht24lc02_set_total_hours(hours);
|
||
}
|
||
|
||
result = remove_queue_node_by_type(&global_queue, MSG_TYPE_MINUTE_SAVE, &queue_item); // 取出队列中对应类型的数据
|
||
if(result)
|
||
{
|
||
|
||
minutes = queue_item.data.hour_meter.minute;
|
||
ht24lc02_set_total_minutes(minutes);
|
||
|
||
}
|
||
|
||
// 检测是否发生464事件
|
||
if(xOxygenEventGroupCheckBit(&global_event, EVENT_464_CLEAR))
|
||
{
|
||
|
||
// 清空该事件并下发蓝色灯慢闪事件
|
||
vOxygenEventGroupClearBits(&global_event, EVENT_464_CLEAR);
|
||
|
||
// 此处放置清空EEPROM累时的代码
|
||
ht24lc02_set_total_minutes(0);
|
||
ht24lc02_set_total_hours(0);
|
||
|
||
vOxygenEventGroupSetBits(&global_event, EVENT_BLUE_BLINK);
|
||
}
|
||
|
||
|
||
// 检测是否需要存储上次清理/更换滤清器的时间
|
||
if(remove_queue_node_by_type(&global_queue, MSG_TYPE_FILTER_TIME_SAVE, &filter_item))
|
||
{
|
||
if(filter_item.data.filter_server.clean_filter_time_need_stored)
|
||
{
|
||
|
||
ht24lc02_word_write(filter_item.data.filter_server.last_clean_filter_hours, INDEX_LAST_CLEAN_FILTER_HOURS);
|
||
filter_item.data.filter_server.clean_filter_time_need_stored = false;
|
||
}
|
||
if(filter_item.data.filter_server.replace_filter_time_need_stored)
|
||
{
|
||
|
||
ht24lc02_word_write(filter_item.data.filter_server.last_replace_filter_hours, INDEX_LAST_REPLACE_FILTER_HOURS);
|
||
filter_item.data.filter_server.clean_filter_time_need_stored = false;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
// 读取E1 E2 E4 E7边界值并存储
|
||
peek_queue_node_by_type(&global_queue, MSG_TYPE_AD_SAMPLING, &adc_item); // 读取队列中的ADC采样值
|
||
if(remove_queue_node_by_type(&global_queue, MSG_TYPE_CARLIB_SAVE, &carlib_item)) // 取出队列中对应类型的数据
|
||
{
|
||
switch(carlib_item.data.carlib_data.netcode)
|
||
{
|
||
case NETCODE_E1_CALIB:
|
||
ht24lc02_word_write(adc_item.data.adc_data.real_press, INDEX_E1_PRESS_LOW);
|
||
|
||
// 闪烁OK灯标识存储完毕
|
||
vOxygenEventGroupSetBits(&global_event, EVENT_OK_BLINK);
|
||
break;
|
||
|
||
case NETCODE_E2_CALIB:
|
||
ht24lc02_word_write(adc_item.data.adc_data.real_press, INDEX_E2_PRESS_HIGH);
|
||
|
||
// 闪烁OK灯标识存储完毕
|
||
vOxygenEventGroupSetBits(&global_event, EVENT_OK_BLINK);
|
||
break;
|
||
|
||
case NETCODE_E4_CALIB:
|
||
ht24lc02_word_write(adc_item.data.adc_data.real_elec, INDEX_E4_ELEC_HIGH);
|
||
|
||
// 闪烁OK灯标识存储完毕
|
||
vOxygenEventGroupSetBits(&global_event, EVENT_OK_BLINK);
|
||
break;
|
||
|
||
case NETCODE_E7_CALIB:
|
||
// 需要存储E7边界数值
|
||
ht24lc02_word_write(adc_item.data.adc_data.real_220V, INDEX_E7_220V_LOW);
|
||
|
||
// 闪烁OK灯标识存储完毕
|
||
vOxygenEventGroupSetBits(&global_event, EVENT_OK_BLINK);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/************************ (C) COPYRIGHT YUWELL *****END OF FILE****/
|
||
|