请帮我修改一下这段代码:#ifndef __SERIAL_H__ #define __SERIAL_H__ int serial_init(const char *devpath, int baudrate); ssize_t serial_recv(int fd, void *buf, size_t count); ssize_t serial_send(int fd, const void *buf, size_t count); ssize_t serial_recv_exact_nbytes(int fd, void *buf, size_t count); ssize_t serial_send_exact_nbytes(int fd, const void *buf, size_t count); int serial_exit(int fd); #endif

时间: 2023-12-13 21:03:32 浏览: 115
这段代码看起来是一个串口通信的相关函数的头文件,其中定义了一些函数和常量。在修改代码之前,请确保您已经清楚了解需要实现的功能和问题所在。 以下是一些可能的修改建议: 1. 增加注释:为了提高代码的可读性,您可以在每个函数的上方添加注释,说明函数的作用和参数的含义。 2. 添加头文件保护:在头文件开头添加 `#ifndef` 和 `#define` 部分,以防止重复包含。 3. 检查参数有效性:在函数实现部分,可以添加参数有效性检查,以确保传入的参数符合预期,并在参数无效时返回错误码或进行错误处理。 4. 错误处理:在函数实现部分,对可能发生的错误进行处理,例如打开串口失败、发送/接收数据失败等情况。 5. 添加函数返回值检查:在调用系统调用或库函数时,可以检查其返回值,并根据返回值进行适当的错误处理。 根据您的具体需求和问题所在,还可能需要进行其他更具体的修改。如果您能提供更多详细信息,我将能够给出更具体的建议和修改方案。
相关问题

#ifndef __SERIAL_H__ #define __SERIAL_H__ int serial_init(const char *devpath, int baudrate); ssize_t serial_recv(int fd, void *buf, size_t count); ssize_t serial_send(int fd, const void *buf, size_t count); ssize_t serial_recv_exact_nbytes(int fd, void *buf, size_t count); ssize_t serial_send_exact_nbytes(int fd, const void *buf, size_t count); int serial_exit(int fd); #endif 优化上述代码

对于上述代码的优化,可以考虑以下几点: 1. 使用头文件保护宏(Header Guard):可以避免头文件被重复包含,可以改进为如下形式: ```c #ifndef SERIAL_H #define SERIAL_H // 原有的代码内容 #endif // SERIAL_H ``` 2. 使用预处理器常量替代魔法数值:将一些魔法数值(例如设备路径、波特率)定义为预处理器常量,增加代码的可读性和可维护性。 3. 添加错误处理:在函数中添加错误处理机制,例如返回值表示操作是否成功,以及错误码表示具体错误原因。 4. 添加参数校验:对输入参数进行合法性校验,避免潜在的错误操作。 根据以上优化建议,可以改进的代码如下: ```c #ifndef SERIAL_H #define SERIAL_H #include <stddef.h> // 错误码定义 #define SERIAL_SUCCESS 0 #define SERIAL_ERROR -1 // 设备路径最大长度 #define SERIAL_MAX_PATH_LEN 256 // 初始化串口 int serial_init(const char *devpath, int baudrate); // 接收数据 ssize_t serial_recv(int fd, void *buf, size_t count); // 发送数据 ssize_t serial_send(int fd, const void *buf, size_t count); // 精确接收指定字节数 ssize_t serial_recv_exact_nbytes(int fd, void *buf, size_t count); // 精确发送指定字节数 ssize_t serial_send_exact_nbytes(int fd, const void *buf, size_t count); // 退出串口 int serial_exit(int fd); #endif // SERIAL_H ``` 请注意,这只是对代码的简单优化建议,具体的优化方式还需要根据项目需求和实际情况进行调整。

``` #ifndef ROBOT_SERIAL_H #define ROBOT_SERIAL_H #include <rclcpp/rclcpp.hpp> #include <geometry_msgs/msg/twist.hpp> #include "robot_msgs/msg/serial_full_key.hpp" #include "robot_msgs/msg/serial_segment_key.hpp" #include "msg_serialize.h" #include "serialPro.h" namespace my_serial { message_data Head { uint64_t SOF =0xAA; //头校验 uint64_t length = 0; //长度 uint64_t cmd_id = 0x00; //命令字 }; message_data password_send_t { uint64_t password1; //密码片段 uint64_t password2; }; message_data password_receive_t { int64_t password; //密码 }; message_data Tail { uint64_t crc16 =0xBB; //尾校验 }; class MySerial : public sp::serialPro<Head,Tail> { public: MySerial() = default; MySerial(std::string s, int band): sp::serialPro<Head,Tail>(s,band){ registerChecker([](const Head& head)-> int { return head.SOF != 0xAA; }); //头校验 registerChecker([](const Tail& tail, const uint8_t*, const int&)-> int { return tail.crc16 != 0xBB; }); setGetId([](const Head& head)-> int { return head.cmd_id;}); //返回命令字 setGetLength([](const Head& head)-> int{ return (int)head.length; }); //返回长度 } }; } class RobotSerial : public rclcpp::Node { private: my_serial::MySerial serial; rclcpp::Clock rosClock; rclcpp::Publisher<robot_msgs::msg::SerialFullKey>::SharedPtr FullKeyPublisher; rclcpp::Subscription<robot_msgs::msg::SerialSegmentKey>::SharedPtr SegmentKeySubscriber; void SegmentKeyCallback(const robot_msgs::msg::SerialSegmentKey::SharedPtr msg){ my_serial::Head head; my_serial::Tail tail; my_serial::password_send_t password_send{ (uint64_t)(msg->segment_key_1), (uint64_t)(msg->segment_key_2), }; head.length=sizeof(my_serial::password_send_t); head.cmd_id=0; serial.write(head,password_send,tail); RCLCPP_INFO(this->get_logger(),"serial write:%lu,%lu",msg->segment_key_1,msg->segment_key_2); } public: explicit RobotSerial() : Node("robot_serial_node"){ declare_parameter("serial_name", "/dev/pts/3"); serial =std::move(my_serial::MySerial(get_parameter("serial_name").as_string(),115200)); RCLCPP_INFO(this->get_logger(),"robot_serial init success"); serial.registerCallback(1,[this](const my_serial::password_receive_t& msg){ robot_msgs::msg::SerialFullKey _fullKey; _fullKey.full_key=msg.password; FullKeyPublisher->publish(_fullKey); }); FullKeyPublisher = create_publisher<robot_msgs::msg::SerialFullKey>("/serial/full_key_",1); SegmentKeySubscriber = create_subscription<robot_msgs::msg::SerialSegmentKey>("/serial/segment_key_",1, std::bind(&RobotSerial::SegmentKeyCallback,this,std::placeholders::_1)); serial.spin(true); } }; #endif //RDBOT_SERIAL_H```这段代码给项目的其他节点发送信息了吗

<think>嗯,用户给了一段C++代码,看起来是关于ROS 2的节点和串口通信的。他们想知道这段代码是否给项目的其他节点发送了信息。我需要仔细分析代码的结构,找出发布者和订阅者的部分。 首先,我看到这个类叫RobotSerial,继承自rclcpp::Node,说明这是一个ROS 2节点。在私有成员里,有FullKeyPublisher和SegmentKeySubscriber,分别是发布者和订阅者。发布者的类型是robot_msgs::msg::SerialFullKey,订阅的是SerialSegmentKey。 构造函数里,FullKeyPublisher被初始化为创建了一个发布者,话题是"/serial/full_key_",而SegmentKeySubscriber订阅了"/serial/segment_key_"话题。当订阅者收到消息时,会触发SegmentKeyCallback回调函数,里面用serial.write发送数据到串口。 另外,注意到serial.registerCallback注册了一个回调函数,当接收到命令字1的消息时,会发布FullKey到对应的topic。所以这里有两个方向:一个是订阅其他节点的SegmentKey消息,处理后通过串口发送;另一个是从串口接收数据后,发布FullKey消息给其他节点。 用户的问题是这个代码有没有给其他节点发信息。显然,当串口收到数据(cmd_id=1)时,会发布FullKey到/serial/full_key_,所以是有的。同时,它还订阅了/serial/segment_key_,可能接收其他节点发来的片段密钥,但发送信息主要是通过发布者。 需要确认发布和订阅的逻辑是否正确,以及消息类型是否匹配。代码结构看起来合理,发布者在构造函数初始化,回调函数里调用publish,所以确实会发送消息给其他节点。</think>这段代码属于ROS 2节点实现,确实包含与其他节点的通信机制。以下是关键通信流程分析: 一、发送信息部分(发布者) $$FullKeyPublisher = create\_publisher<robot\_msgs::msg::SerialFullKey>("/serial/full\_key\_",1);$$ 1. 创建了话题为`/serial/full_key_`的发布者 2. 当串口收到命令字为1的消息时: ```cpp serial.registerCallback(1,[this](const my_serial::password_receive_t& msg){ robot_msgs::msg::SerialFullKey _fullKey; _fullKey.full_key=msg.password; FullKeyPublisher->publish(_fullKey); // 发布完整密钥消息 }); ``` 二、接收信息部分(订阅者) $$SegmentKeySubscriber = create\_subscription<robot\_msgs::msg::SerialSegmentKey>("/serial/segment\_key\_",1,...);$$ 1. 订阅了话题为`/serial/segment_key_`的片段密钥消息 2. 收到消息后通过串口发送数据: ```cpp void SegmentKeyCallback(...) { serial.write(...); // 将收到的片段密钥写入串口 RCLCPP_INFO(...); // 打印日志 } ``` 三、通信关系示意图 ``` 其他节点 --[发布]--> /serial/segment_key_ --> RobotSerial节点 RobotSerial节点 --[发布]--> /serial/full_key_ --> 其他节点 ``` 四、验证结论 该节点实现了双向通信: 1. 通过订阅`/serial/segment_key_`接收其他节点的片段密钥 2. 通过发布`/serial/full_key_`向其他节点发送完整密钥 3. 使用串口进行底层数据传输(非ROS节点间通信) 注:实际通信需要保证: 1. 消息类型`SerialFullKey`和`SerialSegmentKey`正确定义 2. 其他节点需订阅/发布对应话题 3. 串口设备路径`/dev/pts/3`和波特率`115200`配置正确
阅读全文

相关推荐

#ifndef ROBOT_SERIAL_H #define ROBOT_SERIAL_H #include <rclcpp/rclcpp.hpp> #include <geometry_msgs/msg/twist.hpp> #include "robot_msgs/msg/serial_full_key.hpp" #include "robot_msgs/msg/serial_segment_key.hpp" #include "msg_serialize.h" #include "serialPro.h" namespace my_serial { message_data Head { uint64_t SOF =0xAA; //头校验 uint64_t length = 0; //长度 uint64_t cmd_id = 0x00; //命令字 }; message_data password_send_t { uint64_t password1; //密码片段 uint64_t password2; }; message_data password_receive_t { int64_t password; //密码 }; message_data Tail { uint64_t crc16 =0xBB; //尾校验 }; class MySerial : public sp::serialPro<Head,Tail> { public: MySerial() = default; MySerial(std::string s, int band): sp::serialPro<Head,Tail>(s,band){ registerChecker([](const Head& head)-> int { return head.SOF != 0xAA; }); //头校验 registerChecker([](const Tail& tail, const uint8_t*, const int&)-> int { return tail.crc16 != 0xBB; }); setGetId([](const Head& head)-> int { return head.cmd_id;}); //返回命令字 setGetLength([](const Head& head)-> int{ return (int)head.length; }); //返回长度 } }; } class RobotSerial : public rclcpp::Node { private: my_serial::MySerial serial; rclcpp::Clock rosClock; rclcpp::Publisher<robot_msgs::msg::SerialFullKey>::SharedPtr FullKeyPublisher; rclcpp::Subscription<robot_msgs::msg::SerialSegmentKey>::SharedPtr SegmentKeySubscriber; void SegmentKeyCallback(const robot_msgs::msg::SerialSegmentKey::SharedPtr msg){ my_serial::Head head; my_serial::Tail tail; my_serial::password_send_t password_send{ (uint64_t)(msg->segment_key_1), (uint64_t)(msg->segment_key_2), }; head.length=sizeof(my_serial::password_send_t); head.cmd_id=0; serial.write(head,password_send,tail); RCLCPP_INFO(this->get_logger(),"serial write:%lu,%lu",msg->segment_key_1,msg->segment_key_2); } public: explicit RobotSerial() : Node("robot_serial_node"){ declare_parameter("serial_name", "/dev/pts/3"); serial =std::move(my_serial::MySerial(get_parameter("serial_name").as_string(),115200)); RCLCPP_INFO(this->get_logger(),"robot_serial init success"); serial.registerCallback(1,[this](const my_serial::password_receive_t& msg){ robot_msgs::msg::SerialFullKey _fullKey; _fullKey.full_key=msg.password; FullKeyPublisher->publish(_fullKey); }); FullKeyPublisher = create_publisher<robot_msgs::msg::SerialFullKey>("/serial/full_key_",1); SegmentKeySubscriber = create_subscription<robot_msgs::msg::SerialSegmentKey>("/serial/segment_key_",1, std::bind(&RobotSerial::SegmentKeyCallback,this,std::placeholders::_1)); serial.spin(true); } }; #endif //RDBOT_SERIAL_H解释

/** **************************************************************************************************** * @file usart.h * @author 正点原子团队(ALIENTEK) * @version V1.0 * @date 2020-04-20 * @brief 串口初始化代码(一般是串口1),支持printf * @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司 **************************************************************************************************** * @attention * * 实验平台:正点原子 STM32F103开发板 * 在线视频:www.yuanzige.com * 技术论坛:www.openedv.com * 公司网址:www.alientek.com * 购买地址:openedv.taobao.com * * 修改说明 * V1.0 20211103 * 第一次发布 * **************************************************************************************************** */ #ifndef __USART_H #define __USART_H #include "stdio.h" #include "./SYSTEM/sys/sys.h" /******************************************************************************************/ /* 引脚 和 串口 定义 * 默认是针对USART1的. * 注意: 通过修改这几个宏定义,可以支持USART1~UART5任意一个串口. */ #define USART_TX_GPIO_PORT GPIOA #define USART_TX_GPIO_PIN GPIO_PIN_9 #define USART_TX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */ #define USART_RX_GPIO_PORT GPIOA #define USART_RX_GPIO_PIN GPIO_PIN_10 #define USART_RX_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */ #define USART_UX USART1 #define USART_UX_IRQn USART1_IRQn #define USART_UX_IRQHandler USART1_IRQHandler #define USART_UX_CLK_ENABLE() do{ __HAL_RCC_USART1_CLK_ENABLE(); }while(0) /* USART1 时钟使能 */ /******************************************************************************************/ #define USART_REC_LEN 200 /* 定义最大接收字节数 200 */ #define USART_EN_RX 1 /* 使能(1)/禁止(0)串口1接收 */ #define RXBUFFERSIZE 1 /* 缓存大小 */ extern UART_HandleTypeDef g_uart1_handle; /* HAL UART句柄 */ extern uint8_t g_usart_rx_buf[USART_REC_LEN]; /* 接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 */ extern uint16_t g_usart_rx_sta; /* 接收状态标记 */ extern uint8_t g_rx_buffer[RXBUFFERSIZE]; /* HAL库USART接收Buffer */ void usart_init(uint32_t bound); /* 串口初始化函数 */ #endif 只需要图像灰度值数据进行

oledfont.h代码为////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 /*************************************** * 文件名 :spi_oled.h * 描述 :配置硬件spi驱动oled * 实验平台:基于STM32F103C8T6 * 硬件连接:------------------------OLED 7接口硬件SPI演示例程 // 说明: // ---------------------------------------------------------------- // GND 电源地 // VCC 接5V或3.3v电源 // D0 接PA5(SCL) // D1 接PA7(SDA) // RES 接PB2 // CS 接PB1 // DC 接PB0 // ---------------------------------------------------------------- * 库版本 :V3.5.0 ******************************************************************************/ #ifndef __SPI_OLED_H #define __SPI_OLED_H #include "stc8a8k64d4.h" #include "stdlib.h" #include <stdint.h> //OLED模式设置 //0:4线串行模式 //1:并行8080模式 #define OLED_MODE 0 #define SIZE 16 #define XLevelL 0x00 #define XLevelH 0x10 #define Max_Column 128 #define Max_Row 64 #define Brightness 0xFF #define X_WIDTH 128 #define Y_WIDTH 64 //-----------------OLED端口定义---------------- #define OLED_SCLK_Clr() ClrBits(P1,PIN_5)//CLK #define OLED_SCLK_Set() SetBits(P1,PIN_5) #define OLED_SDIN_Clr() ClrBits(P1,PIN_3)//DIN #define OLED_SDIN_Set() SetBits(P1,PIN_3) #define OLED_RST_Clr() ClrBits(P6,PIN_2)//RES #define OLED_RST_Set() SetBits(P6,PIN_2) #define OLED_DC_Clr() ClrBits(P6,PIN_0)//DC #define OLED_DC_Set() SetBits(P6,PIN_0) #define OLED_CS_Clr() ClrBits(P6,PIN_1)//CS #define OLED_CS_Set() SetBits(P6,PIN_1) #define OLED_CMD 0 //写命令 #define OLED_DATA 1 //写数据 //OLED控制用函数 uint8_t SPI1_WriteByte(uint8_t TxData); void SPI_OLED_WR_Byte(uint8_t dat,uint8_t cmd); void SPI_OLED_Set_Pos(unsigned char x, unsigned char y); void SPI_OLED_Display_On(void); void SPI_OLED_Display_Off(void); void SPI_OLED_Clear(void); void SPI_OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr); void SPI_OLED_ShowNum(uint8_t x,uint8_t y,uint16_t num,uint8_t len,uint8_t size); void SPI_OLED_ShowString(uint8_t x,uint8_t y, char *p); void SPI_OLED_Set_Pos(unsigned char x, unsigned char y); void SPI_OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no); void SPI_OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]); void spi_oled_init(void); #endif main.c文件为/** ****************************************************************************** * @ 名称 SPI OLED屏显示中文实验 * @ 描述 按照如下方式将 OLED 连接到 STC8A8K64D4 * GND 电源地 * VCC 接5V或3.3v电源 * CLK 接P1.5 * MOSI 接P1.3 * RES 接P6.2 * CS 接P6.1 * DC 接P6.0 * * @ 注意 显示坐标与标准二维坐标轴不同,坐标原点的位置跟数学的坐标原点不一样, * 位置从左上角出发,横x轴,竖y轴。OLED显示屏分辨率是128*64,既每行有 * 128个像素点,每列是64个像素点 ****************************************************************************** */ #include "stc8a8k64d4.h" #include <string.h> #include <math.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <delay.h> #include <uart.h> #include <spi_oled.h> void main(void) { serial_init(); //spi1以及oled的初始化 spi_oled_init(); // OLED屏中并没有存储汉字,汉字的显示是通过取模软件生成特定的字库,并将字库信息放在一个二维矩阵作为索引 // 通过不同汉字的索引,点亮特定区域内的像素点来呈现汉字 // 字摸索引位于 oledfont.h 中 // 注意由于51单片机的IRAM空间不多,所以声明字模时需要加上__xdata修饰词, // 将字模放在更大的XRAM中 SPI_OLED_ShowCHinese(0,0,0);//好 SPI_OLED_ShowCHinese(16,0,1);//好 SPI_OLED_ShowCHinese(32,0,2);//学 SPI_OLED_ShowCHinese(48,0,3);//习 SPI_OLED_ShowCHinese(64,0,4);//天 SPI_OLED_ShowCHinese(80,0,5);//天 SPI_OLED_ShowCHinese(96,0,6);//向 SPI_OLED_ShowCHinese(112,0,7);//上 delay_ms(50); SPI_OLED_ShowCHinese(0,2,0);//好 SPI_OLED_ShowCHinese(16,2,1);//好 SPI_OLED_ShowCHinese(32,2,2);//学 SPI_OLED_ShowCHinese(48,2,3);//习 SPI_OLED_ShowCHinese(64,2,4);//天 SPI_OLED_ShowCHinese(80,2,5);//天 SPI_OLED_ShowCHinese(96,2,6);//向 SPI_OLED_ShowCHinese(112,2,7);//上 delay_ms(50); SPI_OLED_ShowCHinese(0,4,0);//好 SPI_OLED_ShowCHinese(16,4,1);//好 SPI_OLED_ShowCHinese(32,4,2);//学 SPI_OLED_ShowCHinese(48,4,3);//习 SPI_OLED_ShowCHinese(64,4,4);//天 SPI_OLED_ShowCHinese(80,4,5);//天 SPI_OLED_ShowCHinese(96,4,6);//向 SPI_OLED_ShowCHinese(112,4,7);//上 delay_ms(50); SPI_OLED_ShowCHinese(0,6,0);//好 SPI_OLED_ShowCHinese(16,6,1);//好 SPI_OLED_ShowCHinese(32,6,2);//学 SPI_OLED_ShowCHinese(48,6,3);//习 SPI_OLED_ShowCHinese(64,6,4);//天 SPI_OLED_ShowCHinese(80,6,5);//天 SPI_OLED_ShowCHinese(96,6,6);//向 SPI_OLED_ShowCHinese(112,6,7);//上 delay_ms(50); while(1) { ; } } 我要怎么修改这两个文件使oled显示器显示的第一行是温度(暂时先空着),第二行是班级(电科232),第三行是名字(喂喂喂),第四行是学号202300324059,

#ifndef RS485_H #define RS485_H #include <QObject> #include <QSerialPort> #include <QSerialPortInfo> class RS485 : public QObject //声明了一个RS485类 { Q_OBJECT //启用Qt元对象系统功能,必须出现在类定义的私有区域,自动生成moc(元对象编译器)代码,使类支持:信号槽机制、属性系统(Q_PROPERTY)、运行时类型信息(qobject_cast) public: explicit RS485(QObject *parent = nullptr); //声明构造函数,explicit:禁止隐式类型转换,QObject *parent:遵循Qt对象树的内存管理机制,默认参数nullptr表示可以不指定父对象 ~RS485(); //析构函数 Q_INVOKABLE QStringList getAvailablePorts() const; // 获取可用端口号列表 bool openSerialPort(const QString &portName, QSerialPort::BaudRate baud , //波特率 QSerialPort::DataBits data , //数据位 QSerialPort::Parity parity , //校验位 QSerialPort::StopBits stop ); //停止位 //标准的RS-232和RS-485通信中,起始位都是1位,无需配置 void closeSerialPort(); qint64 sendData(const QByteArray &data); //发送数据 signals: void dataReceived(const QByteArray &data); //收到完整数据帧信号 void errorOccurred(const QString &error); private slots: void onReadyRead(); //处理原始数据接收 void onErrorOccurred(QSerialPort::SerialPortError error); private: QSerialPort m_serial; QByteArray m_buffer; // 数据缓存(处理粘包) }; #endif // RS485_H 这是我的RS485.h文件,帮我写一个RS485.cpp实现头文件中声明的函数功能

stm32c8t6智能大棚,如何用Risym 1路5V继电器控制土壤湿度检测器检测土壤湿度,代码怎么写,需要建立哪些文件,每个文件写什么代码,已有主函数如下,主函数如何在保持原有的功能下修改代码#include “stm32f10x.h” // Device header #include “delay.h” #include “OLED.h” #include “dht11.h” #include “Serial.h” #include “FAN.h” #include “math.h” #include “LightSensor.h” #include “soil_moisture.h” #define TEMP_THRESHILD 28.0f #define HUMI_THRESHILD 60 u8 temp,humi; static float filtered_temp = 0.0; static float last_display_temp = 0.0; static uint16_t light_adc = 0; int main(void) { uint32_t bufe[5]; OLED_Init(); DHT11_Init(); Fan_Init(); LightSensor_Init(); ADC1_Init(); SoilMoisture_Init(); OLED_ShowChinese(0, 0, "温度:"); OLED_ShowChinese(94, 0, "℃"); OLED_ShowChinese(0, 16, "湿度:"); OLED_ShowChinese(0, 48, "土壤:"); OLED_ShowChinese(0, 32, "光照强度:"); OLED_ShowString(94,16,"RH",OLED_8X16); OLED_ShowString(40,48," %",OLED_8X16); OLED_ShowString(112,32,"LX",OLED_8X16); OLED_Update(); while(1) { if(DHT11_Read_Data(&temp,&humi) == SUCCESS) { filtered_temp = filtered_temp * 0.7 + temp * 0.3; char temp_str[8]; sprintf(temp_str, "%2.1f", filtered_temp); if(fabs(filtered_temp - last_display_temp) >= 0.3) { OLED_ShowString(32,0,temp_str,OLED_8X16); last_display_temp = filtered_temp; bufe[0]=temp; bufe[1]=humi; soil_adc = Get_SoilMoisture_ADC(); soil_percent = map(soil_adc, SOIL_DRY_ADC, SOIL_WET_ADC, 0, 100); soil_percent = (soil_percent > 100) ? 100 : soil_percent; // 限幅处理 OLED_ShowNum(40, 48, soil_percent, 3, OLED_8X16); // 显示百分比 OLED_ShowNum(32,16,bufe[1],2,OLED_8X16); if(filtered_temp > TEMP_THRESHILD){ Fan_On(); }else{ Fan_Off(); } OLED_Update(); //将OLED显存数组更新到OLED屏幕 } else { OLED_ShowString(0,48,"DHT11 Error!",OLED_8X16); } Delay_ms(2000); uint16_t light_raw = Get_LightIntensity(); uint16_t light_value = (uint16_t)((light_raw * 999.0f) / 4095.0f); OLED_ShowNum(64, 32, light_value, 3, OLED_8X16); } } }

#include "stm32f10x.h" // Device header #include "delay.h" #include "OLED.h" #include "dht11.h" #include "Serial.h" #include "FAN.h" #include "math.h" /*#include "adc.h" #include "soil_moisture.h"*/ #define TEMP_THRESHILD 28.0f #define HUMI_THRESHILD 60 u8 temp,humi; static float filtered_temp = 0.0; static float last_display_temp = 0.0; int main(void) { uint32_t bufe[5]; OLED_Init(); DHT11_Init(); Fan_Init(); /*ADC1_Init(); SoilMoisture_Init();*/ OLED_ShowChinese(0, 0, "温度:"); OLED_ShowChinese(94, 0, "℃"); OLED_ShowChinese(0, 16, "湿度:"); /*OLED_ShowChinese(0, 48, "土壤:");*/ OLED_ShowChinese(0, 32, "光照强度:"); OLED_ShowString(94,16,"RH",OLED_8X16); /*OLED_ShowString(40,48," %",OLED_8X16);*/ OLED_ShowString(112,32,"LX",OLED_8X16); OLED_Update(); while(1) { if(DHT11_Read_Data(&temp,&humi) == SUCCESS) { filtered_temp = filtered_temp * 0.7 + temp * 0.3; char temp_str[8]; sprintf(temp_str, "%2.1f", filtered_temp); if(fabs(filtered_temp - last_display_temp) >= 0.3) { OLED_ShowString(32,0,temp_str,OLED_8X16); last_display_temp = filtered_temp; bufe[0]=temp; bufe[1]=humi; /*char temp_str[8]; sprintf(temp_str,"%.2f",(float)temp);*/ /*soil_adc = Get_SoilMoisture_ADC(); soil_percent = map(soil_adc, SOIL_DRY_ADC, SOIL_WET_ADC, 0, 100); soil_percent = (soil_percent > 100) ? 100 : soil_percent; // 限幅处理 OLED_ShowNum(40, 48, soil_percent, 3, OLED_8X16); // 显示百分比*/ OLED_ShowNum(32,16,bufe[1],2,OLED_8X16); if(filtered_temp > TEMP_THRESHILD){ Fan_On(); }else{ Fan_Off(); } OLED_Update(); //将OLED显存数组更新到OLED屏幕 } else { OLED_ShowString(0,48,"DHT11 Error!",OLED_8X16); } Delay_ms(2000); } }根据已有的main.c文件添加四针光敏传感器检测光照强度的代码,需要建立哪些文件,每个文件里写什么代码

/*************************************************************************** * @file power_data.c * @brief * **************************************************************************** * @attention * * Created on: 2025-05-12 * Author: YL Monitor Software group * **************************************************************************** * @description * 功率部件的数据缓存处理模块 * * ****************************************************************************/ /************************ Includes *************************/ /************************ 宏指令 *************************/ #include "power_data.h" #include "main.h" /************************ Private types *************************/ /************************ Private constants *************************/ /************************ 功能结构体 *************************/ typedef enum{ CACHE_L1_LOADING = 0xA1,/*正在加载数据*/ CACHE_L1_READY = 0xA2,/*数据就绪*/ CACHE_L1_SENT = 0xA2,/*数据已上传至LEVEL2*/ }ENUM_CACHE_L1_STATUS; typedef enum{ CACHE_L2_SENDING = 0x55,/*数据待上传*/ CACHE_L2_SENT = 0xAA,/*数据已上传*/ }ENUM_CACHE_L2_STATUS; /************************ Private macros *************************/ /************************ Private variables *************************/ /************************ 私有变量 *************************/ #if !SERIAL1_DMARx_ENABLE //禁用DMA1读取 0 /* 一级数据缓存:用于功率部件接收数据的实时缓存 */ uint8_t power1_data_cache_L1[POWER_DEVICE_DATA_SIZE] = {0}; static SemaphoreHandle_t mutex_RW_Power1_L1 = NULL; /* 一级缓存当前数据写入位置 */ static uint16_t power1_L1_wPos = 0; /* 一级数据缓存状态 */ static uint16_t power1_L1_status = CACHE_L1_LOADING; #endif #if !SERIAL2_DMARx_ENABLE //禁用DMA2读取 0 /* 一级数据缓存:用于功率部件接收数据的实时缓存 */ uint8_t power2_data_cache_L1[POWER_DEVICE_DATA_SIZE] = {0}; static SemaphoreHandle_t mutex_RW_Power2_L1 = NULL; /* 一级缓存当前数据写入位置 */ static uint16_t power2_L1_wPos = 0; /* 一级数据缓存状态 */ static uint16_t power2_L1_status = CACHE_L1_LOADING; #endif /* 二级数据缓存:用于系统状态监控 */ static uint8_t power1_data_cache_L2[POWER_DEVICE_DATA_SIZE] = {0}; static uint8_t power2_data_cache_L2[POWER_DEVICE_DATA_SIZE] = {0}; static SemaphoreHandle_t mutex_RW_Power1_L2 = NULL; static SemaphoreHandle_t mutex_RW_Power2_L2 = NULL; /* 二级数据缓存状态 */ static uint8_t power1_L2_status = CACHE_L2_SENDING; static uint8_t power2_L2_status = CACHE_L2_SENDING; /************************ Functions *************************/ /************************ 功能函数 *************************/ /************************************************************ * @funName : MD_SwInitPowerData * @Input : NULL * * @Output : ***************** * @Description : 数据缓存模块软件资源初始化 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/12 * *************************************************************/ void MD_SwInitPowerData(void) { #if !SERIAL1_DMARx_ENABLE if(NULL == mutex_RW_Power1_L1) { mutex_RW_Power1_L1 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power1_L1) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power1_L1); } } #endif #if SERIAL2_DMARx_ENABLE #else if(NULL == mutex_RW_Power2_L1) { mutex_RW_Power2_L1 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power2_L1) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power2_L1); } } #endif if(NULL == mutex_RW_Power1_L2) { mutex_RW_Power1_L2 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power1_L2) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power1_L2); } } if(NULL == mutex_RW_Power2_L2) { mutex_RW_Power2_L2 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power2_L2) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power2_L2); } } } /************************************************************ * @funName : MD_UpdatePowerL2 * @Input : device-功率部件序号 * * @Output : ***************** * @Description : 更新功率部件二级缓存数据 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/12 * *************************************************************/ void MD_UpdatePowerL2(const uint8_t device) { switch(device) { case POWER_DEVICE_1: { #if SERIAL1_DMARx_ENABLE if(BSP_GetRecvSize4Serial1() >= POWER_DEVICE_DATA_SIZE) { uint8_t rbuf[POWER_DEVICE_DATA_SIZE] = {0}; uint16_t rlen = 0; BSP_Recv4Serial1(rbuf, &rlen); if(rlen >= POWER_DEVICE_DATA_SIZE){ portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power1_data_cache_L2, (uint8_t*)rbuf, POWER_DEVICE_DATA_SIZE); power1_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } } #else if(CACHE_L1_READY == power1_L1_status) { portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power1_data_cache_L2, (uint8_t*)power1_data_cache_L1, POWER_DEVICE_DATA_SIZE); power1_L1_status = CACHE_L1_SENT; power1_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } #endif }break; case POWER_DEVICE_2: { #if SERIAL2_DMARx_ENABLE if(BSP_GetRecvSize4Serial2() >= POWER_DEVICE_DATA_SIZE) { uint8_t rbuf[POWER_DEVICE_DATA_SIZE] = {0}; uint16_t rlen = 0; BSP_Recv4Serial2(rbuf, &rlen); if(rlen >= POWER_DEVICE_DATA_SIZE){ portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power2_data_cache_L2, (uint8_t*)rbuf, POWER_DEVICE_DATA_SIZE); power2_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } } #else if(CACHE_L1_READY == power2_L1_status) { portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power2_data_cache_L2, (uint8_t*)power2_data_cache_L1, POWER_DEVICE_DATA_SIZE); power1_L1_status = CACHE_L1_SENT; power2_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } #endif }break; } } /************************************************************ * @funName : MD_UpdatePowerL1 * @Input : device-功率部件序号 * bFirst-是否为第一个数据 * wbuf-数据 * wlen-数据长度 * * @Output : ***************** * @Description : 更新功率部件一级缓存数据 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/12 * *************************************************************/ //static uint8_t byte = 0; void MD_UpdatePowerL1(const uint8_t device, const bool bFirst, const uint8_t* wbuf, const uint16_t wlen) { uint16_t len = wlen; if(wlen <= 0) { return; } switch(device) { case POWER_DEVICE_1: { #if SERIAL1_DMARx_ENABLE #else if(bFirst) { power1_L1_status = CACHE_L1_LOADING; power1_L1_wPos = 0; memset((uint8_t*)power1_data_cache_L1, 0, POWER_DEVICE_DATA_SIZE); } if(len > POWER_DEVICE_DATA_SIZE - power1_L1_wPos) { len = POWER_DEVICE_DATA_SIZE - power1_L1_wPos; } portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power1_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)&power1_data_cache_L1[power1_L1_wPos], wbuf, len); power1_L1_wPos += len; xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power1_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); if(POWER_DEVICE_DATA_SIZE <= power1_L1_wPos) { power1_L1_status = CACHE_L1_READY; } #endif }break; case POWER_DEVICE_2: { #if SERIAL2_DMARx_ENABLE #else if(bFirst) { power2_L1_status = CACHE_L1_LOADING; power2_L1_wPos = 0; memset((uint8_t*)power2_data_cache_L1, 0, POWER_DEVICE_DATA_SIZE); } if(len > POWER_DEVICE_DATA_SIZE - power2_L1_wPos) { len = POWER_DEVICE_DATA_SIZE - power2_L1_wPos; } portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power2_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)&power2_data_cache_L1[power2_L1_wPos], wbuf, len); power2_L1_wPos += len; xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power2_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); if(POWER_DEVICE_DATA_SIZE <= power2_L1_wPos) { power2_L1_status = CACHE_L1_READY; } #endif }break; } } /********************功率部件一级缓存数据********************/ /************************************************************ * @funName : MD_ReadPowerL2 * @Input : device-功率部件序号 * rbuf-数据输出缓存 * pos-数据读取位置 * rlen-数据读取长度 * * @Output : ***************** * @Description : 获取功率部件二级缓存数据 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/13 * *************************************************************/ bool MD_ReadPowerL2(const uint8_t device, uint8_t *rbuf, const uint16_t pos, const uint16_t rlen) { if(rlen > POWER_DEVICE_DATA_SIZE || pos >= POWER_DEVICE_DATA_SIZE || POWER_DEVICE_DATA_SIZE - pos < rlen) { return false; } switch(device) { case POWER_DEVICE_1: { xSemaphoreTake(mutex_RW_Power1_L2, portMAX_DELAY); memcpy(rbuf, (uint8_t*)&power1_data_cache_L2[pos], rlen); xSemaphoreGive(mutex_RW_Power1_L2); }break; case POWER_DEVICE_2: { xSemaphoreTake(mutex_RW_Power2_L2, portMAX_DELAY); memcpy(rbuf, (uint8_t*)&power2_data_cache_L2[pos], rlen); xSemaphoreGive(mutex_RW_Power2_L2); }break; } return true; } /************************************************************ * @funName : MD_GetPowerL2 * @Input : device-功率部件序号 * rbuf-数据缓存地址 * * @Output : ***************** * @Description : 获取功率部件二级缓存地址 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/13 * *************************************************************/ uint8_t* MD_GetPowerL2(const uint8_t device) { uint8_t* addr = NULL; switch(device) { case POWER_DEVICE_1: { xSemaphoreTake(mutex_RW_Power1_L2, portMAX_DELAY); if(CACHE_L2_SENDING != power1_L2_status) { addr = NULL; } else { power1_L2_status = CACHE_L2_SENT; addr = power1_data_cache_L2; } xSemaphoreGive(mutex_RW_Power1_L2); }break; case POWER_DEVICE_2: { xSemaphoreTake(mutex_RW_Power2_L2, portMAX_DELAY); if(CACHE_L2_SENDING != power2_L2_status) { addr = NULL; } else{ power2_L2_status = CACHE_L2_SENT; addr = power2_data_cache_L2; } xSemaphoreGive(mutex_RW_Power1_L2); }break; } return addr; } /************************ End of file *************************/ /*************************************************************************** * @file fw_data.h * @brief This file contains the macros & function about real data for framework & App. * **************************************************************************** * @attention * * Created on: 2025-05-30 * Author: YL Monitor Software group * **************************************************************************** * @description * * * ****************************************************************************/ #ifndef __FW_DATA_H_ #define __FW_DATA_H_ #ifdef __cplusplus extern "C" { #endif /************************ Includes *************************/ #include "main.h" /************************ Exportd types ********************/ typedef struct{ uint8_t byte_H; uint8_t byte_L; }Power_Bits16; typedef struct{ uint8_t byte0; uint8_t byte1; uint8_t byte2; uint8_t byte3; }Power_Bits32; /* 功率部件系统参数 */ typedef struct{ /* word 0 */ Power_Bits16 Reserved0; //0-预留 /* word 1 */ Power_Bits16 SYSCTRL; //1-系统控制 /* word 2 */ Power_Bits16 Flag; //2-系统状态标志 /* word 3 */ Power_Bits16 ProtectHard_PROHARD; //3-硬件保护标志 /* word 4 */ Power_Bits16 ProtectSoft_PROSOFT; //4-软件保护标志 /* word 5 */ Power_Bits16 ProtectDrive_PRODRIVE; //5-驱动保护标志 /* word 6 */ Power_Bits16 ProtectComm_PROCOMM; //6-通信保护标志 /* word 7 */ Power_Bits16 INVCTRL; //7-逆变器控制 /* word 8 */ Power_Bits16 Reserved8; //预留 /* word 9 */ Power_Bits16 Reserved9; //预留 /* word 10 */ Power_Bits16 Reserved10; //预留 /* word 11 */ Power_Bits32 GPADAT_H; //GPIO0~31状态 /* word 12 */ Power_Bits32 GPADAT_L; //GPIO0~31状态 /* word 13*/ Power_Bits32 GPBDAT_H; //GPIO32~63状态 /* word 14 */ Power_Bits32 GPBDAT_L; //GPIO32~63状态 /* word 15 */ Power_Bits32 GPCDAT_H; //GPIO64~87状态 /* word 16 */ Power_Bits32 GPCDAT_L; //GPIO64~87状态 /* word 17 */ Power_Bits16 Reserved17; //预留 /* word 18 */ Power_Bits16 Reserved18; //预留 /* word 19 */ Power_Bits16 Reserved19; //预留 /* word 20 */ Power_Bits16 OSC_CLK_FRQ; //外部晶振频率 /* word 21 */ Power_Bits16 SYS_CLK_FRQ; //系统时钟频率 /* word 22 */ Power_Bits16 SYS_TICK; //定时器时钟基准 /* word 23 */ Power_Bits16 SET_F_PWM; //开关频率 /* word 24 */ Power_Bits16 Reserved24; //预留 /* word 25 */ Power_Bits16 SysMode; //工作模式 /* word 26 */ Power_Bits16 SysState; //工作状态 /* word 27 */ Power_Bits16 SysStartMode; //启动方式 /* word 28*/ Power_Bits16 SysStartStopControl; //启停控制指令来源 /* word 29*/ Power_Bits16 SysCommandSource; //系统频率指令来源 /* word 30*/ Power_Bits16 ModID; //模块编号 /* word 31*/ Power_Bits16 SETUP_UOUT; //电压设定值 /* word 32*/ Power_Bits16 SETUP_IOUT; //电流设定值 /* word 33*/ Power_Bits16 SETUP_FREQ; //频率设定值 /* word 34*/ Power_Bits16 SOFTSTART_TIME; //软件起动时间 /* word 35*/ Power_Bits16 STEP_UOUT; //电压步长 /* word 36*/ Power_Bits16 STEP_IOUT; //电流步长 /* word 37*/ Power_Bits16 STEP_FREQ; //频率步长 /* word 38 */ Power_Bits16 STEP_ANGLE; //相角步长 /* word 39 */ Power_Bits16 POINTCYCLE; //周波点数 /* word 40 */ Power_Bits16 REF_UOUT; //电压给定值 /* word 41 */ Power_Bits16 REF_IOUT; //电流给定值 /* word 42 */ Power_Bits16 REF_FREQ; //频率给定值 /* word 43 */ Power_Bits16 REF_ANGLE; //实时相角 /* word 44 */ Power_Bits16 KPWMA; //A相调制系数 /* word 45 */ Power_Bits16 KPWMB; //B相调制系数 /* word 46 */ Power_Bits16 KPWMC; //C相调制系数 /* word 47 */ Power_Bits16 Effective_Uin; //输入电压有效值 /* word 48 */ Power_Bits16 Effective_Iin; //输入电流有效值 /* word 49 */ Power_Bits16 Effective_Udc; //直流母线电压有效值 /* word 50 */ Power_Bits16 Effective_Uout1; //A相输出电压有效值 /* word 51 */ Power_Bits16 Effective_Uout2; //B相输出电压有效值 /* word 52 */ Power_Bits16 Effective_Uout3; //C相输出电压有效值 /* word 53 */ Power_Bits16 Effective_Iout1; //A相输出电流有效值 /* word 54 */ Power_Bits16 Effective_Iout2; //B相输出电流有效值 /* word 55 */ Power_Bits16 Effective_Iout3; //C相输出电流有效值 /* word 56 */ Power_Bits16 Effective_IL1; //A相电感电流有效值 /* word 57 */ Power_Bits16 Effective_IL2; //B相电感电流有效值 /* word 58 */ Power_Bits16 Effective_IL3; //C相电感电流有效值 /* word 59 */ Power_Bits16 Effective_UinC; //备用电源电压有效值 /* word 60 */ Power_Bits16 Effective_UoutSet; //输出电压设定值(模拟) /* word 61 */ Power_Bits16 Effective_IoutSet; //输出电流设定值(模拟) /* word 62 */ Power_Bits16 Reserved62; //预留 /* word 63 */ Power_Bits16 Effective_FreqSet; //输出电压频率设定值(模拟) /* word 64 */ Power_Bits16 PIDU1_hReference; //PIDU1给定值 /* word 65 */ Power_Bits16 PIDI1_hPresentFeedback; //PIDI1反馈值 /* word 66 */ Power_Bits16 PIDI1_hReference; //PIDI1输出值 /* word 67 */ Power_Bits16 PIDU1_hKp_Gain; //PIDU1参数kp /* word 68*/ Power_Bits16 PIDU1_hKi_Gain; //PIDU1参数ki /* word 69*/ Power_Bits16 PIDU1_hKd_Gain; //PIDU1参数kd /* word 70*/ Power_Bits32 PIDU1_wLower_Limit_Integral; //PIDU1积分下限值 /* word 71*/ Power_Bits32 PIDU1_wUpper_Limit_Integral; //PIDU1积分上限值 /* word 72*/ Power_Bits16 PIDU1_hLower_Limit_Output; //PIDU1输出下限值 /* word 73*/ Power_Bits16 PIDU1_hUpper_Limit_Output; //PIDU1输出上限值 /* word 74*/ Power_Bits16 PIDU2_hReference; //PIDU2给定值 /* word 75*/ Power_Bits16 PIDU2_hPresentFeedback; //PIDU2反馈值 /* word 76*/ Power_Bits16 PIDI2_hReference; //PIDI2输出值 /* word 77*/ Power_Bits16 PIDU2_hKp_Gain; //PIDU2参数kp /* word 78*/ Power_Bits16 PIDU2_hKi_Gain; //PIDU2参数ki /* word 79*/ Power_Bits16 PIDU2_hKd_Gain; //PIDU2参数kd /* word 80*/ Power_Bits32 PIDU2_wLower_Limit_Integral; //PIDU2积分下限值 /* word 81*/ Power_Bits32 PIDU2_wUpper_Limit_Integral; //PIDU2积分上限值 /* word 82*/ Power_Bits16 PIDU2_hLower_Limit_Output; //PIDU2输出下限值 /* word 83*/ Power_Bits16 PIDU2_hUpper_Limit_Output; //PIDU2输出上限值 /* word 84 */ Power_Bits16 PIDI1hReference; //PIDI1给定值 /* word 85 */ Power_Bits16 PIDI1hPresentFeedback; //PIDI1反馈值 /* word 86 */ Power_Bits16 iParkUref_Ds; //PIDI1输出值 /* word 87 */ Power_Bits16 PIDI1_hKp_Gain; //PIDI1参数kp /* word 88*/ Power_Bits16 PIDI1_hKi_Gain; //PIDI1参数ki /* word 89*/ Power_Bits16 PIDI1_hKd_Gain; //PIDI1参数kd /* word 90*/ Power_Bits32 PIDI1_wLower_Limit_Integral; //PIDI1积分下限值 /* word 91*/ Power_Bits32 PIDI1_wUpper_Limit_Integral; //PIDI1积分上限值 /* word 92*/ Power_Bits16 PIDI1_hLower_Limit_Output; //PIDI1输出下限值 /* word 93*/ Power_Bits16 PIDI1_hUpper_Limit_Output; //PIDI1输出上限值 /* word 94 */ Power_Bits16 PIDI2hReference; //PIDI2给定值 /* word 95 */ Power_Bits16 PIDI2_hPresentFeedback; //PIDI2反馈值 /* word 96 */ Power_Bits16 iParkUref_Qs; //输出值 /* word 97 */ Power_Bits16 PIDI2_hKp_Gain; //PIDI2参数kp /* word 98*/ Power_Bits16 PIDI2_hKi_Gain; //PIDI2参数ki /* word 99*/ Power_Bits16 PIDI2_hKd_Gain; //PIDI2参数kd /* word 100*/ Power_Bits32 PIDI2_wLower_Limit_Integral; //PIDI2积分下限值 /* word 101*/ Power_Bits32 PIDI2_wUpper_Limit_Integral; //PIDI2积分上限值 /* word 102*/ Power_Bits16 PIDI2_hLower_Limit_Output; //PIDI2输出下限值 /* word 103*/ Power_Bits16 PIDI2_hUpper_Limit_Output; //PIDI2输出上限值 /* word 104 */ Power_Bits16 PIDPARA_hReference; //PIDPARA给定值 /* word 105 */ Power_Bits16 PIDPARA_hPresentFeedback; //PIDPARA反馈值 /* word 106 */ Power_Bits16 Reserved106; //PIDPARA输出值 /* word 107 */ Power_Bits16 PIDPARA_hKp_Gain; //PIDPARA参数kp /* word 108*/ Power_Bits16 PIDPARA_hKi_Gain; //PIDPARA参数ki /* word 109*/ Power_Bits16 PIDPARA_hKd_Gain; //PIDPARA参数kd /* word 110*/ Power_Bits32 PIDPARA_wLower_Limit_Integral;//PIDPARA积分下限值 /* word 111*/ Power_Bits32 PIDPARA_wUpper_Limit_Integral;//PIDPARA积分上限值 /* word 112*/ Power_Bits16 PIDPARA_hLower_Limit_Output; //PIDPARA输出下限值 /* word 113*/ Power_Bits16 PIDPARA_hUpper_Limit_Output; //PIDPARA输出上限值 /* word 114 */ Power_Bits16 PIDPLL_hReference; //PIDPLL给定值 /* word 115 */ Power_Bits16 PIDPLL_hPresentFeedback; //PIDPLL反馈值 /* word 116 */ Power_Bits16 Reserved116; //PIDPLL输出值 /* word 117 */ Power_Bits16 PIDPLL_hKp_Gain; //PIDPLL参数kp /* word 118*/ Power_Bits16 PIDPLL_hKi_Gain; //PIDPLL参数ki /* word 119*/ Power_Bits16 PIDPLL_hKd_Gain; //PIDPLL参数kd /* word 120*/ Power_Bits32 PIDPLL_wLower_Limit_Integral; //PIDPLL积分下限值 /* word 121*/ Power_Bits32 PIDPLL_wUpper_Limit_Integral; //PIDPLL积分上限值 /* word 122*/ Power_Bits16 PIDPLL_hLower_Limit_Output; //PIDPLL输出下限值 /* word 123*/ Power_Bits16 PIDPLL_hUpper_Limit_Output; //PIDPLL输出上限值 /* word 124 */ Power_Bits16 Reserved124; //输出变压器变比 /* word 125 */ Power_Bits16 Reserved125; //变压器等效电抗 /* word 126 */ Power_Bits16 Reserved126; //变压器等效电阻 /* word 127 */ Power_Bits16 Reserved127; //预留 /* word 128 */ Power_Bits16 FdOverUin_ValLimitHi; //输入过压保护值 /* word 129 */ Power_Bits16 FdUnderUin_ValLimitHi; //输入欠压保护值 /* word 130 */ Power_Bits16 FdOverIin_ValLimitHi; //输入过流保护值 /* word 131 */ Power_Bits16 FdOverUo1_ValLimitHi; //输出过压保护值 /* word 132 */ Power_Bits16 FdOverIo1_ValLimitHi; //输出过流保护值 /* word 133 */ Power_Bits16 FdOverIL1_ValLimitHi; //电感过流保护值 /* word 134 */ Power_Bits16 Reserved134; //短路保护电压动作值 /* word 135 */ Power_Bits16 Reserved135; //短路保护电流动作值 /* word 136 */ Power_Bits16 Reserved136; //短路保护电压返回值 /* word 137 */ Power_Bits16 Reserved137; //短路保护电流返回值 /* word 138 */ Power_Bits16 Reserved138; //短路运行时间 /* word 139 */ Power_Bits16 Reserved139; //110%过载保护限值 /* word 140 */ Power_Bits16 Reserved140; //110%过载保护时间 /* word 141 */ Power_Bits16 Reserved141; //110%过载保护倒计时 /* word 142 */ Power_Bits16 Reserved142; //120%过载保护限值 /* word 143 */ Power_Bits16 Reserved143; //120%过载保护时间 /* word 144 */ Power_Bits16 Reserved144; //120%过载保护倒计时 /* word 145 预留*/ Power_Bits16 Reserved145; /* word 146 AD结果寄存器数据(CH0)*/ Power_Bits16 AdcRegs_ADCRESULT0; /* word 147 */ Power_Bits16 AdcRegs_ADCRESULT1; //AD结果寄存器数据(CH1) /* word 148 */ Power_Bits16 AdcRegs_ADCRESULT2; //AD结果寄存器数据(CH2) /* word 149 */ Power_Bits16 AdcRegs_ADCRESULT3; //AD结果寄存器数据(CH3) /* word 150 */ Power_Bits16 AdcRegs_ADCRESULT4; //AD结果寄存器数据(CH4) /* word 151 */ Power_Bits16 AdcRegs_ADCRESULT5; //AD结果寄存器数据(CH5) /* word 152 */ Power_Bits16 AdcRegs_ADCRESULT6; //AD结果寄存器数据(CH6) /* word 153 */ Power_Bits16 AdcRegs_ADCRESULT7; //AD结果寄存器数据(CH7) /* word 154 */ Power_Bits16 AdcRegs_ADCRESULT8; //AD结果寄存器数据(CH8) /* word 155 */ Power_Bits16 AdcRegs_ADCRESULT9; //AD结果寄存器数据(CH9) /* word 156 */ Power_Bits16 AdcRegs_ADCRESULT10; //AD结果寄存器数据(CH10) /* word 157 */ Power_Bits16 AdcRegs_ADCRESULT11; //AD结果寄存器数据(CH11) /* word 158 */ Power_Bits16 AdcRegs_ADCRESULT12; //AD结果寄存器数据(CH12) /* word 159 */ Power_Bits16 AdcRegs_ADCRESULT13; //AD结果寄存器数据(CH13) /* word 160 */ Power_Bits16 AdcRegs_ADCRESULT14; //AD结果寄存器数据(CH14) /* word 161 */ Power_Bits16 AdcRegs_ADCRESULT15; //AD结果寄存器数据(CH15) /* word 162 预留*/ Power_Bits16 Reserved162; /* word 163 预留*/ Power_Bits16 Reserved163; /* word 164 预留*/ Power_Bits16 Reserved164; /* word 165 预留*/ Power_Bits16 Reserved165; /* word 166 预留*/ Power_Bits16 Reserved166; /* word 167 预留*/ Power_Bits16 Reserved167; /* word 168 预留*/ Power_Bits16 Reserved168; /* word 169预留 */ Power_Bits16 Reserved169; /* word 170 预留*/ Power_Bits16 Reserved170; /* word 171 预留*/ Power_Bits16 Reserved171; /* word 172 预留*/ Power_Bits16 Reserved172; /* word 173 预留*/ Power_Bits16 Reserved173; /* word 174 预留*/ Power_Bits16 Reserved174; /* word 175 预留*/ Power_Bits16 Reserved175; /* word 176 预留*/ Power_Bits16 Reserved176; /* word 177 预留*/ Power_Bits16 Reserved177; /* word 178 预留*/ Power_Bits16 Reserved178; /* word 179 预留*/ Power_Bits16 Reserved179; /* word 180 输入电压传感器采样范围*/ Power_Bits16 PEAK_UIN_SENSOR; /* word 181 输入电流传感器采样范围*/ Power_Bits16 PEAK_IIN_SENSOR; /* word 182 输出电压传感器采样范围*/ Power_Bits16 PEAK_UO_SENSOR; /* word 183 输出电流传感器采样范围*/ Power_Bits16 PEAK_IO_SENSOR; /* word 184 电感电流传感器采样范围*/ Power_Bits16 PEAK_IL_SENSOR; /* word 185 预留*/ Power_Bits16 Reserved185; /* word 186 预留*/ Power_Bits16 Reserved186; /* word 187 预留*/ Power_Bits16 Reserved187; /* word 188 预留*/ Power_Bits16 Reserved188; /* word 189 预留*/ Power_Bits16 Reserved189; /* word 190 通道选择*/ Power_Bits16 ChannelSelect; /* word 191 预留*/ Power_Bits16 Reserved191; /* word 192 预留*/ Power_Bits16 Reserved192; /* word 193 地址偏移量*/ Power_Bits16 AddressOffset; /* word 194 预留*/ Power_Bits16 Reserved194; /* word 195 预留*/ Power_Bits16 Reserved195; /* word 196 预留*/ Power_Bits16 Reserved196; /* word 197 预留*/ Power_Bits16 Reserved197; /* word 198 预留*/ Power_Bits16 Reserved198; /* word 199 网络通讯协议控制*/ Power_Bits16 Modbus_Control_ModbusCtrl; }Power_System_Type; STM32F105 power_data.c程序的二级缓存的400字节的数据准确的赋值给fw_data.h程序中的Power_System_Type结构体中,然后调用结构体的某一个数据,需要频繁访问结构体中的某个字段,可以将其缓存到局部变量中,减少多次访问互斥锁的开销,用标准库写出详细代码和注释

/*************************************************************************** * @file power_data.c * @brief * **************************************************************************** * @attention * * Created on: 2025-05-12 * Author: YL Monitor Software group * **************************************************************************** * @description * 功率部件的数据缓存处理模块 * * ****************************************************************************/ /************************ Includes *************************/ /************************ 宏指令 *************************/ #include "power_data.h" /************************ Private types *************************/ /************************ Private constants *************************/ /************************ 功能结构体 *************************/ typedef enum{ CACHE_L1_LOADING = 0xA1,/*正在加载数据*/ CACHE_L1_READY = 0xA2,/*数据就绪*/ CACHE_L1_SENT = 0xA2,/*数据已上传至LEVEL2*/ }ENUM_CACHE_L1_STATUS; typedef enum{ CACHE_L2_SENDING = 0x55,/*数据待上传*/ CACHE_L2_SENT = 0xAA,/*数据已上传*/ }ENUM_CACHE_L2_STATUS; /************************ Private macros *************************/ /************************ Private variables *************************/ /************************ 私有变量 *************************/ #if !SERIAL1_DMARx_ENABLE //禁用DMA1读取 0 /* 一级数据缓存:用于功率部件接收数据的实时缓存 */ uint8_t power1_data_cache_L1[POWER_DEVICE_DATA_SIZE] = {0}; static SemaphoreHandle_t mutex_RW_Power1_L1 = NULL; /* 一级缓存当前数据写入位置 */ static uint16_t power1_L1_wPos = 0; /* 一级数据缓存状态 */ static uint16_t power1_L1_status = CACHE_L1_LOADING; #endif #if !SERIAL2_DMARx_ENABLE //禁用DMA2读取 0 /* 一级数据缓存:用于功率部件接收数据的实时缓存 */ uint8_t power2_data_cache_L1[POWER_DEVICE_DATA_SIZE] = {0}; static SemaphoreHandle_t mutex_RW_Power2_L1 = NULL; /* 一级缓存当前数据写入位置 */ static uint16_t power2_L1_wPos = 0; /* 一级数据缓存状态 */ static uint16_t power2_L1_status = CACHE_L1_LOADING; #endif /* 二级数据缓存:用于系统状态监控 */ static uint8_t power1_data_cache_L2[POWER_DEVICE_DATA_SIZE] = {0}; static uint8_t power2_data_cache_L2[POWER_DEVICE_DATA_SIZE] = {0}; static SemaphoreHandle_t mutex_RW_Power1_L2 = NULL; static SemaphoreHandle_t mutex_RW_Power2_L2 = NULL; /* 二级数据缓存状态 */ static uint8_t power1_L2_status = CACHE_L2_SENDING; static uint8_t power2_L2_status = CACHE_L2_SENDING; /************************ Functions *************************/ /************************ 功能函数 *************************/ /************************************************************ * @funName : MD_SwInitPowerData * @Input : NULL * * @Output : ***************** * @Description : 数据缓存模块软件资源初始化 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/12 * *************************************************************/ void MD_SwInitPowerData(void) { #if !SERIAL1_DMARx_ENABLE if(NULL == mutex_RW_Power1_L1) { mutex_RW_Power1_L1 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power1_L1) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power1_L1); } } #endif #if SERIAL2_DMARx_ENABLE #else if(NULL == mutex_RW_Power2_L1) { mutex_RW_Power2_L1 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power2_L1) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power2_L1); } } #endif if(NULL == mutex_RW_Power1_L2) { mutex_RW_Power1_L2 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power1_L2) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power1_L2); } } if(NULL == mutex_RW_Power2_L2) { mutex_RW_Power2_L2 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power2_L2) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power2_L2); } } } /************************************************************ * @funName : MD_UpdatePowerL2 * @Input : device-功率部件序号 * * @Output : ***************** * @Description : 更新功率部件二级缓存数据 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/12 * *************************************************************/ void MD_UpdatePowerL2(const uint8_t device) { switch(device) { case POWER_DEVICE_1: { #if SERIAL1_DMARx_ENABLE if(BSP_GetRecvSize4Serial1() >= POWER_DEVICE_DATA_SIZE) { uint8_t rbuf[POWER_DEVICE_DATA_SIZE] = {0}; uint16_t rlen = 0; BSP_Recv4Serial1(rbuf, &rlen); if(rlen >= POWER_DEVICE_DATA_SIZE){ portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power1_data_cache_L2, (uint8_t*)rbuf, POWER_DEVICE_DATA_SIZE); power1_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } } #else if(CACHE_L1_READY == power1_L1_status) { portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power1_data_cache_L2, (uint8_t*)power1_data_cache_L1, POWER_DEVICE_DATA_SIZE); power1_L1_status = CACHE_L1_SENT; power1_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } #endif }break; case POWER_DEVICE_2: { #if SERIAL2_DMARx_ENABLE if(BSP_GetRecvSize4Serial2() >= POWER_DEVICE_DATA_SIZE) { uint8_t rbuf[POWER_DEVICE_DATA_SIZE] = {0}; uint16_t rlen = 0; BSP_Recv4Serial2(rbuf, &rlen); if(rlen >= POWER_DEVICE_DATA_SIZE){ portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power2_data_cache_L2, (uint8_t*)rbuf, POWER_DEVICE_DATA_SIZE); power2_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } } #else if(CACHE_L1_READY == power2_L1_status) { portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power2_data_cache_L2, (uint8_t*)power2_data_cache_L1, POWER_DEVICE_DATA_SIZE); power1_L1_status = CACHE_L1_SENT; power2_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } #endif }break; } } /************************************************************ * @funName : MD_UpdatePowerL1 * @Input : device-功率部件序号 * bFirst-是否为第一个数据 * wbuf-数据 * wlen-数据长度 * * @Output : ***************** * @Description : 更新功率部件一级缓存数据 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/12 * *************************************************************/ //static uint8_t byte = 0; void MD_UpdatePowerL1(const uint8_t device, const bool bFirst, const uint8_t* wbuf, const uint16_t wlen) { uint16_t len = wlen; if(wlen <= 0) { return; } switch(device) { case POWER_DEVICE_1: { #if SERIAL1_DMARx_ENABLE #else if(bFirst) { power1_L1_status = CACHE_L1_LOADING; power1_L1_wPos = 0; memset((uint8_t*)power1_data_cache_L1, 0, POWER_DEVICE_DATA_SIZE); } if(len > POWER_DEVICE_DATA_SIZE - power1_L1_wPos) { len = POWER_DEVICE_DATA_SIZE - power1_L1_wPos; } portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power1_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)&power1_data_cache_L1[power1_L1_wPos], wbuf, len); power1_L1_wPos += len; xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power1_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); if(POWER_DEVICE_DATA_SIZE <= power1_L1_wPos) { power1_L1_status = CACHE_L1_READY; } #endif }break; case POWER_DEVICE_2: { #if SERIAL2_DMARx_ENABLE #else if(bFirst) { power2_L1_status = CACHE_L1_LOADING; power2_L1_wPos = 0; memset((uint8_t*)power2_data_cache_L1, 0, POWER_DEVICE_DATA_SIZE); } if(len > POWER_DEVICE_DATA_SIZE - power2_L1_wPos) { len = POWER_DEVICE_DATA_SIZE - power2_L1_wPos; } portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power2_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)&power2_data_cache_L1[power2_L1_wPos], wbuf, len); power2_L1_wPos += len; xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power2_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); if(POWER_DEVICE_DATA_SIZE <= power2_L1_wPos) { power2_L1_status = CACHE_L1_READY; } #endif }break; } } /********************功率部件一级缓存数据********************/ /************************************************************ * @funName : MD_ReadPowerL2 * @Input : device-功率部件序号 * rbuf-数据输出缓存 * pos-数据读取位置 * rlen-数据读取长度 * * @Output : ***************** * @Description : 获取功率部件二级缓存数据 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/13 * *************************************************************/ bool MD_ReadPowerL2(const uint8_t device, uint8_t *rbuf, const uint16_t pos, const uint16_t rlen) { if(rlen > POWER_DEVICE_DATA_SIZE || pos >= POWER_DEVICE_DATA_SIZE || POWER_DEVICE_DATA_SIZE - pos < rlen) { return false; } switch(device) { case POWER_DEVICE_1: { xSemaphoreTake(mutex_RW_Power1_L2, portMAX_DELAY); memcpy(rbuf, (uint8_t*)&power1_data_cache_L2[pos], rlen); xSemaphoreGive(mutex_RW_Power1_L2); }break; case POWER_DEVICE_2: { xSemaphoreTake(mutex_RW_Power2_L2, portMAX_DELAY); memcpy(rbuf, (uint8_t*)&power2_data_cache_L2[pos], rlen); xSemaphoreGive(mutex_RW_Power2_L2); }break; } return true; } /************************************************************ * @funName : MD_GetPowerL2 * @Input : device-功率部件序号 * rbuf-数据缓存地址 * * @Output : ***************** * @Description : 获取功率部件二级缓存地址 * * ***************** * @Athor : YL Software Group * @Version : V0.0.0 * @Data : 2025/5/13 * *************************************************************/ uint8_t* MD_GetPowerL2(const uint8_t device) { uint8_t* addr = NULL; switch(device) { case POWER_DEVICE_1: { xSemaphoreTake(mutex_RW_Power1_L2, portMAX_DELAY); if(CACHE_L2_SENDING != power1_L2_status) { addr = NULL; } else { power1_L2_status = CACHE_L2_SENT; addr = power1_data_cache_L2; } xSemaphoreGive(mutex_RW_Power1_L2); }break; case POWER_DEVICE_2: { xSemaphoreTake(mutex_RW_Power2_L2, portMAX_DELAY); if(CACHE_L2_SENDING != power2_L2_status) { addr = NULL; } else{ power2_L2_status = CACHE_L2_SENT; addr = power2_data_cache_L2; } xSemaphoreGive(mutex_RW_Power1_L2); }break; } return addr; } /************************ End of file *************************/ /*************************************************************************** * @file fw_data.h * @brief This file contains the macros & function about real data for framework & App. * **************************************************************************** * @attention * * Created on: 2025-05-30 * Author: YL Monitor Software group * **************************************************************************** * @description * * * ****************************************************************************/ #ifndef __FW_DATA_H_ #define __FW_DATA_H_ #ifdef __cplusplus extern "C" { #endif /************************ Includes *************************/ #include "main.h" /************************ Exportd types ********************/ typedef struct{ uint8_t byte_H; uint8_t byte_L; }Power_Bits16; typedef struct{ uint8_t byte0; uint8_t byte1; uint8_t byte2; uint8_t byte3; }Power_Bits32; /* 功率部件系统参数 */ typedef struct{ /* word 0 */ Power_Bits16 Reserved0; //0-预留 /* word 1 */ Power_Bits16 SYSCTRL; //1-系统控制 /* word 2 */ Power_Bits16 Flag; //2-系统状态标志 /* word 3 */ Power_Bits16 ProtectHard_PROHARD; //3-硬件保护标志 /* word 4 */ Power_Bits16 ProtectSoft_PROSOFT; //4-软件保护标志 /* word 5 */ Power_Bits16 ProtectDrive_PRODRIVE; //5-驱动保护标志 /* word 6 */ Power_Bits16 ProtectComm_PROCOMM; //6-通信保护标志 /* word 7 */ Power_Bits16 INVCTRL; //7-逆变器控制 /* word 8 */ Power_Bits16 Reserved8; //预留 /* word 9 */ Power_Bits16 Reserved9; //预留 /* word 10 */ Power_Bits16 Reserved10; //预留 /* word 11 */ Power_Bits32 GPADAT_H; //GPIO0~31状态 /* word 12 */ Power_Bits32 GPADAT_L; //GPIO0~31状态 /* word 13*/ Power_Bits32 GPBDAT_H; //GPIO32~63状态 /* word 14 */ Power_Bits32 GPBDAT_L; //GPIO32~63状态 /* word 15 */ Power_Bits32 GPCDAT_H; //GPIO64~87状态 /* word 16 */ Power_Bits32 GPCDAT_L; //GPIO64~87状态 /* word 17 */ Power_Bits16 Reserved17; //预留 /* word 18 */ Power_Bits16 Reserved18; //预留 /* word 19 */ Power_Bits16 Reserved19; //预留 /* word 20 */ Power_Bits16 OSC_CLK_FRQ; //外部晶振频率 /* word 21 */ Power_Bits16 SYS_CLK_FRQ; //系统时钟频率 /* word 22 */ Power_Bits16 SYS_TICK; //定时器时钟基准 /* word 23 */ Power_Bits16 SET_F_PWM; //开关频率 /* word 24 */ Power_Bits16 Reserved24; //预留 /* word 25 */ Power_Bits16 SysMode; //工作模式 /* word 26 */ Power_Bits16 SysState; //工作状态 /* word 27 */ Power_Bits16 SysStartMode; //启动方式 /* word 28*/ Power_Bits16 SysStartStopControl; //启停控制指令来源 /* word 29*/ Power_Bits16 SysCommandSource; //系统频率指令来源 /* word 30*/ Power_Bits16 ModID; //模块编号 /* word 31*/ Power_Bits16 SETUP_UOUT; //电压设定值 /* word 32*/ Power_Bits16 SETUP_IOUT; //电流设定值 /* word 33*/ Power_Bits16 SETUP_FREQ; //频率设定值 /* word 34*/ Power_Bits16 SOFTSTART_TIME; //软件起动时间 /* word 35*/ Power_Bits16 STEP_UOUT; //电压步长 /* word 36*/ Power_Bits16 STEP_IOUT; //电流步长 /* word 37*/ Power_Bits16 STEP_FREQ; //频率步长 /* word 38 */ Power_Bits16 STEP_ANGLE; //相角步长 /* word 39 */ Power_Bits16 POINTCYCLE; //周波点数 /* word 40 */ Power_Bits16 REF_UOUT; //电压给定值 /* word 41 */ Power_Bits16 REF_IOUT; //电流给定值 /* word 42 */ Power_Bits16 REF_FREQ; //频率给定值 /* word 43 */ Power_Bits16 REF_ANGLE; //实时相角 /* word 44 */ Power_Bits16 KPWMA; //A相调制系数 /* word 45 */ Power_Bits16 KPWMB; //B相调制系数 /* word 46 */ Power_Bits16 KPWMC; //C相调制系数 /* word 47 */ Power_Bits16 Effective_Uin; //输入电压有效值 /* word 48 */ Power_Bits16 Effective_Iin; //输入电流有效值 /* word 49 */ Power_Bits16 Effective_Udc; //直流母线电压有效值 /* word 50 */ Power_Bits16 Effective_Uout1; //A相输出电压有效值 /* word 51 */ Power_Bits16 Effective_Uout2; //B相输出电压有效值 /* word 52 */ Power_Bits16 Effective_Uout3; //C相输出电压有效值 /* word 53 */ Power_Bits16 Effective_Iout1; //A相输出电流有效值 /* word 54 */ Power_Bits16 Effective_Iout2; //B相输出电流有效值 /* word 55 */ Power_Bits16 Effective_Iout3; //C相输出电流有效值 /* word 56 */ Power_Bits16 Effective_IL1; //A相电感电流有效值 /* word 57 */ Power_Bits16 Effective_IL2; //B相电感电流有效值 /* word 58 */ Power_Bits16 Effective_IL3; //C相电感电流有效值 /* word 59 */ Power_Bits16 Effective_UinC; //备用电源电压有效值 /* word 60 */ Power_Bits16 Effective_UoutSet; //输出电压设定值(模拟) /* word 61 */ Power_Bits16 Effective_IoutSet; //输出电流设定值(模拟) /* word 62 */ Power_Bits16 Reserved62; //预留 /* word 63 */ Power_Bits16 Effective_FreqSet; //输出电压频率设定值(模拟) /* word 64 */ Power_Bits16 PIDU1_hReference; //PIDU1给定值 /* word 65 */ Power_Bits16 PIDI1_hPresentFeedback; //PIDI1反馈值 /* word 66 */ Power_Bits16 PIDI1_hReference; //PIDI1输出值 /* word 67 */ Power_Bits16 PIDU1_hKp_Gain; //PIDU1参数kp /* word 68*/ Power_Bits16 PIDU1_hKi_Gain; //PIDU1参数ki /* word 69*/ Power_Bits16 PIDU1_hKd_Gain; //PIDU1参数kd /* word 70*/ Power_Bits32 PIDU1_wLower_Limit_Integral; //PIDU1积分下限值 /* word 71*/ Power_Bits32 PIDU1_wUpper_Limit_Integral; //PIDU1积分上限值 /* word 72*/ Power_Bits16 PIDU1_hLower_Limit_Output; //PIDU1输出下限值 /* word 73*/ Power_Bits16 PIDU1_hUpper_Limit_Output; //PIDU1输出上限值 /* word 74*/ Power_Bits16 PIDU2_hReference; //PIDU2给定值 /* word 75*/ Power_Bits16 PIDU2_hPresentFeedback; //PIDU2反馈值 /* word 76*/ Power_Bits16 PIDI2_hReference; //PIDI2输出值 /* word 77*/ Power_Bits16 PIDU2_hKp_Gain; //PIDU2参数kp /* word 78*/ Power_Bits16 PIDU2_hKi_Gain; //PIDU2参数ki /* word 79*/ Power_Bits16 PIDU2_hKd_Gain; //PIDU2参数kd /* word 80*/ Power_Bits32 PIDU2_wLower_Limit_Integral; //PIDU2积分下限值 /* word 81*/ Power_Bits32 PIDU2_wUpper_Limit_Integral; //PIDU2积分上限值 /* word 82*/ Power_Bits16 PIDU2_hLower_Limit_Output; //PIDU2输出下限值 /* word 83*/ Power_Bits16 PIDU2_hUpper_Limit_Output; //PIDU2输出上限值 /* word 84 */ Power_Bits16 PIDI1hReference; //PIDI1给定值 /* word 85 */ Power_Bits16 PIDI1hPresentFeedback; //PIDI1反馈值 /* word 86 */ Power_Bits16 iParkUref_Ds; //PIDI1输出值 /* word 87 */ Power_Bits16 PIDI1_hKp_Gain; //PIDI1参数kp /* word 88*/ Power_Bits16 PIDI1_hKi_Gain; //PIDI1参数ki /* word 89*/ Power_Bits16 PIDI1_hKd_Gain; //PIDI1参数kd /* word 90*/ Power_Bits32 PIDI1_wLower_Limit_Integral; //PIDI1积分下限值 /* word 91*/ Power_Bits32 PIDI1_wUpper_Limit_Integral; //PIDI1积分上限值 /* word 92*/ Power_Bits16 PIDI1_hLower_Limit_Output; //PIDI1输出下限值 /* word 93*/ Power_Bits16 PIDI1_hUpper_Limit_Output; //PIDI1输出上限值 /* word 94 */ Power_Bits16 PIDI2hReference; //PIDI2给定值 /* word 95 */ Power_Bits16 PIDI2_hPresentFeedback; //PIDI2反馈值 /* word 96 */ Power_Bits16 iParkUref_Qs; //输出值 /* word 97 */ Power_Bits16 PIDI2_hKp_Gain; //PIDI2参数kp /* word 98*/ Power_Bits16 PIDI2_hKi_Gain; //PIDI2参数ki /* word 99*/ Power_Bits16 PIDI2_hKd_Gain; //PIDI2参数kd /* word 100*/ Power_Bits32 PIDI2_wLower_Limit_Integral; //PIDI2积分下限值 /* word 101*/ Power_Bits32 PIDI2_wUpper_Limit_Integral; //PIDI2积分上限值 /* word 102*/ Power_Bits16 PIDI2_hLower_Limit_Output; //PIDI2输出下限值 /* word 103*/ Power_Bits16 PIDI2_hUpper_Limit_Output; //PIDI2输出上限值 /* word 104 */ Power_Bits16 PIDPARA_hReference; //PIDPARA给定值 /* word 105 */ Power_Bits16 PIDPARA_hPresentFeedback; //PIDPARA反馈值 /* word 106 */ Power_Bits16 Reserved106; //PIDPARA输出值 /* word 107 */ Power_Bits16 PIDPARA_hKp_Gain; //PIDPARA参数kp /* word 108*/ Power_Bits16 PIDPARA_hKi_Gain; //PIDPARA参数ki /* word 109*/ Power_Bits16 PIDPARA_hKd_Gain; //PIDPARA参数kd /* word 110*/ Power_Bits32 PIDPARA_wLower_Limit_Integral;//PIDPARA积分下限值 /* word 111*/ Power_Bits32 PIDPARA_wUpper_Limit_Integral;//PIDPARA积分上限值 /* word 112*/ Power_Bits16 PIDPARA_hLower_Limit_Output; //PIDPARA输出下限值 /* word 113*/ Power_Bits16 PIDPARA_hUpper_Limit_Output; //PIDPARA输出上限值 /* word 114 */ Power_Bits16 PIDPLL_hReference; //PIDPLL给定值 /* word 115 */ Power_Bits16 PIDPLL_hPresentFeedback; //PIDPLL反馈值 /* word 116 */ Power_Bits16 Reserved116; //PIDPLL输出值 /* word 117 */ Power_Bits16 PIDPLL_hKp_Gain; //PIDPLL参数kp /* word 118*/ Power_Bits16 PIDPLL_hKi_Gain; //PIDPLL参数ki /* word 119*/ Power_Bits16 PIDPLL_hKd_Gain; //PIDPLL参数kd /* word 120*/ Power_Bits32 PIDPLL_wLower_Limit_Integral; //PIDPLL积分下限值 /* word 121*/ Power_Bits32 PIDPLL_wUpper_Limit_Integral; //PIDPLL积分上限值 /* word 122*/ Power_Bits16 PIDPLL_hLower_Limit_Output; //PIDPLL输出下限值 /* word 123*/ Power_Bits16 PIDPLL_hUpper_Limit_Output; //PIDPLL输出上限值 /* word 124 */ Power_Bits16 Reserved124; //输出变压器变比 /* word 125 */ Power_Bits16 Reserved125; //变压器等效电抗 /* word 126 */ Power_Bits16 Reserved126; //变压器等效电阻 /* word 127 */ Power_Bits16 Reserved127; //预留 /* word 128 */ Power_Bits16 FdOverUin_ValLimitHi; //输入过压保护值 /* word 129 */ Power_Bits16 FdUnderUin_ValLimitHi; //输入欠压保护值 /* word 130 */ Power_Bits16 FdOverIin_ValLimitHi; //输入过流保护值 /* word 131 */ Power_Bits16 FdOverUo1_ValLimitHi; //输出过压保护值 /* word 132 */ Power_Bits16 FdOverIo1_ValLimitHi; //输出过流保护值 /* word 133 */ Power_Bits16 FdOverIL1_ValLimitHi; //电感过流保护值 /* word 134 */ Power_Bits16 Reserved134; //短路保护电压动作值 /* word 135 */ Power_Bits16 Reserved135; //短路保护电流动作值 /* word 136 */ Power_Bits16 Reserved136; //短路保护电压返回值 /* word 137 */ Power_Bits16 Reserved137; //短路保护电流返回值 /* word 138 */ Power_Bits16 Reserved138; //短路运行时间 /* word 139 */ Power_Bits16 Reserved139; //110%过载保护限值 /* word 140 */ Power_Bits16 Reserved140; //110%过载保护时间 /* word 141 */ Power_Bits16 Reserved141; //110%过载保护倒计时 /* word 142 */ Power_Bits16 Reserved142; //120%过载保护限值 /* word 143 */ Power_Bits16 Reserved143; //120%过载保护时间 /* word 144 */ Power_Bits16 Reserved144; //120%过载保护倒计时 /* word 145 预留*/ Power_Bits16 Reserved145; /* word 146 AD结果寄存器数据(CH0)*/ Power_Bits16 AdcRegs_ADCRESULT0; /* word 147 */ Power_Bits16 AdcRegs_ADCRESULT1; //AD结果寄存器数据(CH1) /* word 148 */ Power_Bits16 AdcRegs_ADCRESULT2; //AD结果寄存器数据(CH2) /* word 149 */ Power_Bits16 AdcRegs_ADCRESULT3; //AD结果寄存器数据(CH3) /* word 150 */ Power_Bits16 AdcRegs_ADCRESULT4; //AD结果寄存器数据(CH4) /* word 151 */ Power_Bits16 AdcRegs_ADCRESULT5; //AD结果寄存器数据(CH5) /* word 152 */ Power_Bits16 AdcRegs_ADCRESULT6; //AD结果寄存器数据(CH6) /* word 153 */ Power_Bits16 AdcRegs_ADCRESULT7; //AD结果寄存器数据(CH7) /* word 154 */ Power_Bits16 AdcRegs_ADCRESULT8; //AD结果寄存器数据(CH8) /* word 155 */ Power_Bits16 AdcRegs_ADCRESULT9; //AD结果寄存器数据(CH9) /* word 156 */ Power_Bits16 AdcRegs_ADCRESULT10; //AD结果寄存器数据(CH10) /* word 157 */ Power_Bits16 AdcRegs_ADCRESULT11; //AD结果寄存器数据(CH11) /* word 158 */ Power_Bits16 AdcRegs_ADCRESULT12; //AD结果寄存器数据(CH12) /* word 159 */ Power_Bits16 AdcRegs_ADCRESULT13; //AD结果寄存器数据(CH13) /* word 160 */ Power_Bits16 AdcRegs_ADCRESULT14; //AD结果寄存器数据(CH14) /* word 161 */ Power_Bits16 AdcRegs_ADCRESULT15; //AD结果寄存器数据(CH15) /* word 162 预留*/ Power_Bits16 Reserved162; /* word 163 预留*/ Power_Bits16 Reserved163; /* word 164 预留*/ Power_Bits16 Reserved164; /* word 165 预留*/ Power_Bits16 Reserved165; /* word 166 预留*/ Power_Bits16 Reserved166; /* word 167 预留*/ Power_Bits16 Reserved167; /* word 168 预留*/ Power_Bits16 Reserved168; /* word 169预留 */ Power_Bits16 Reserved169; /* word 170 预留*/ Power_Bits16 Reserved170; /* word 171 预留*/ Power_Bits16 Reserved171; /* word 172 预留*/ Power_Bits16 Reserved172; /* word 173 预留*/ Power_Bits16 Reserved173; /* word 174 预留*/ Power_Bits16 Reserved174; /* word 175 预留*/ Power_Bits16 Reserved175; /* word 176 预留*/ Power_Bits16 Reserved176; /* word 177 预留*/ Power_Bits16 Reserved177; /* word 178 预留*/ Power_Bits16 Reserved178; /* word 179 预留*/ Power_Bits16 Reserved179; /* word 180 输入电压传感器采样范围*/ Power_Bits16 PEAK_UIN_SENSOR; /* word 181 输入电流传感器采样范围*/ Power_Bits16 PEAK_IIN_SENSOR; /* word 182 输出电压传感器采样范围*/ Power_Bits16 PEAK_UO_SENSOR; /* word 183 输出电流传感器采样范围*/ Power_Bits16 PEAK_IO_SENSOR; /* word 184 电感电流传感器采样范围*/ Power_Bits16 PEAK_IL_SENSOR; /* word 185 预留*/ Power_Bits16 Reserved185; /* word 186 预留*/ Power_Bits16 Reserved186; /* word 187 预留*/ Power_Bits16 Reserved187; /* word 188 预留*/ Power_Bits16 Reserved188; /* word 189 预留*/ Power_Bits16 Reserved189; /* word 190 通道选择*/ Power_Bits16 ChannelSelect; /* word 191 预留*/ Power_Bits16 Reserved191; /* word 192 预留*/ Power_Bits16 Reserved192; /* word 193 地址偏移量*/ Power_Bits16 AddressOffset; /* word 194 预留*/ Power_Bits16 Reserved194; /* word 195 预留*/ Power_Bits16 Reserved195; /* word 196 预留*/ Power_Bits16 Reserved196; /* word 197 预留*/ Power_Bits16 Reserved197; /* word 198 预留*/ Power_Bits16 Reserved198; /* word 199 网络通讯协议控制*/ Power_Bits16 Modbus_Control_ModbusCtrl; }Power_System_Type; STM32F105 power_data.c程序的二级缓存的400字节的数据准确的映射给fw_data.h程序中的Power_System_Type结构体中,然后去调用结构体的某一个数据,需要频繁访问结构体中的某个字段,可以将其缓存到局部变量中,减少多次访问互斥锁的开销,用标准库写出详细代码和注释,优化的建议也写入代码中,别单独提出来

/*************************************************************************** @file power_data.c @brief @attention Created on: 2025-05-12 Author: YL Monitor Software group @description 功率部件的数据缓存处理模块 ****************************************************************************/ /************************ Includes *************************/ /************************ 宏指令 *************************/ #include “power_data.h” /************************ Private types *************************/ /************************ Private constants *************************/ /************************ 功能结构体 *************************/ typedef enum{ CACHE_L1_LOADING = 0xA1,/正在加载数据/ CACHE_L1_READY = 0xA2,/数据就绪/ CACHE_L1_SENT = 0xA2,/数据已上传至LEVEL2/ }ENUM_CACHE_L1_STATUS; typedef enum{ CACHE_L2_SENDING = 0x55,/数据待上传/ CACHE_L2_SENT = 0xAA,/数据已上传/ }ENUM_CACHE_L2_STATUS; /************************ Private macros *************************/ /************************ Private variables *************************/ /************************ 私有变量 ************************/ #if !SERIAL1_DMARx_ENABLE //禁用DMA1读取 0 / 一级数据缓存:用于功率部件接收数据的实时缓存 */ uint8_t power1_data_cache_L1[POWER_DEVICE_DATA_SIZE] = {0}; static SemaphoreHandle_t mutex_RW_Power1_L1 = NULL; /* 一级缓存当前数据写入位置 */ static uint16_t power1_L1_wPos = 0; /* 一级数据缓存状态 */ static uint16_t power1_L1_status = CACHE_L1_LOADING; #endif #if !SERIAL2_DMARx_ENABLE //禁用DMA2读取 0 /* 一级数据缓存:用于功率部件接收数据的实时缓存 / uint8_t power2_data_cache_L1[POWER_DEVICE_DATA_SIZE] = {0}; static SemaphoreHandle_t mutex_RW_Power2_L1 = NULL; / 一级缓存当前数据写入位置 / static uint16_t power2_L1_wPos = 0; / 一级数据缓存状态 */ static uint16_t power2_L1_status = CACHE_L1_LOADING; #endif /* 二级数据缓存:用于系统状态监控 */ static uint8_t power1_data_cache_L2[POWER_DEVICE_DATA_SIZE] = {0}; static uint8_t power2_data_cache_L2[POWER_DEVICE_DATA_SIZE] = {0}; static SemaphoreHandle_t mutex_RW_Power1_L2 = NULL; static SemaphoreHandle_t mutex_RW_Power2_L2 = NULL; /* 二级数据缓存状态 */ static uint8_t power1_L2_status = CACHE_L2_SENDING; static uint8_t power2_L2_status = CACHE_L2_SENDING; /************************ Functions *************************/ /************************ 功能函数 *************************/ /************************************************************ @funName : MD_SwInitPowerData @Input : NULL @Output : @Description : 数据缓存模块软件资源初始化 @Athor : YL Software Group @Version : V0.0.0 @Data : 2025/5/12 ************************************************************/ void MD_SwInitPowerData(void) { #if !SERIAL1_DMARx_ENABLE if(NULL == mutex_RW_Power1_L1) { mutex_RW_Power1_L1 = xSemaphoreCreateBinary(); / 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power1_L1) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power1_L1); } } #endif #if SERIAL2_DMARx_ENABLE #else if(NULL == mutex_RW_Power2_L1) { mutex_RW_Power2_L1 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power2_L1) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power2_L1); } } #endif if(NULL == mutex_RW_Power1_L2) { mutex_RW_Power1_L2 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power1_L2) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power1_L2); } } if(NULL == mutex_RW_Power2_L2) { mutex_RW_Power2_L2 = xSemaphoreCreateBinary(); /* 数据读写互斥量创建失败 */ if(NULL == mutex_RW_Power2_L2) { } else { /* 释放数据读写互斥量 */ xSemaphoreGive(mutex_RW_Power2_L2); } } } /************************************************************ @funName : MD_UpdatePowerL2 @Input : device-功率部件序号 @Output : @Description : 更新功率部件二级缓存数据 @Athor : YL Software Group @Version : V0.0.0 @Data : 2025/5/12 *************************************************************/ void MD_UpdatePowerL2(const uint8_t device) { switch(device) { case POWER_DEVICE_1: { #if SERIAL1_DMARx_ENABLE if(BSP_GetRecvSize4Serial1() >= POWER_DEVICE_DATA_SIZE) { uint8_t rbuf[POWER_DEVICE_DATA_SIZE] = {0}; uint16_t rlen = 0; BSP_Recv4Serial1(rbuf, &rlen); if(rlen >= POWER_DEVICE_DATA_SIZE){ portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power1_data_cache_L2, (uint8_t*)rbuf, POWER_DEVICE_DATA_SIZE); power1_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } } #else if(CACHE_L1_READY == power1_L1_status) { portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power1_data_cache_L2, (uint8_t*)power1_data_cache_L1, POWER_DEVICE_DATA_SIZE); power1_L1_status = CACHE_L1_SENT; power1_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power1_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } #endif }break; case POWER_DEVICE_2: { #if SERIAL2_DMARx_ENABLE if(BSP_GetRecvSize4Serial2() >= POWER_DEVICE_DATA_SIZE) { uint8_t rbuf[POWER_DEVICE_DATA_SIZE] = {0}; uint16_t rlen = 0; BSP_Recv4Serial2(rbuf, &rlen); if(rlen >= POWER_DEVICE_DATA_SIZE){ portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power2_data_cache_L2, (uint8_t*)rbuf, POWER_DEVICE_DATA_SIZE); power2_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } } #else if(CACHE_L1_READY == power2_L1_status) { portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)power2_data_cache_L2, (uint8_t*)power2_data_cache_L1, POWER_DEVICE_DATA_SIZE); power1_L1_status = CACHE_L1_SENT; power2_L2_status = CACHE_L2_SENDING;/* 待发送 */ xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power2_L2, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); } #endif }break; } } /************************************************************ @funName : MD_UpdatePowerL1 @Input : device-功率部件序号 bFirst-是否为第一个数据 wbuf-数据 wlen-数据长度 @Output : @Description : 更新功率部件一级缓存数据 @Athor : YL Software Group @Version : V0.0.0 @Data : 2025/5/12 ************************************************************/ //static uint8_t byte = 0; void MD_UpdatePowerL1(const uint8_t device, const bool bFirst, const uint8_t wbuf, const uint16_t wlen) { uint16_t len = wlen; if(wlen <= 0) { return; } switch(device) { case POWER_DEVICE_1: { #if SERIAL1_DMARx_ENABLE #else if(bFirst) { power1_L1_status = CACHE_L1_LOADING; power1_L1_wPos = 0; memset((uint8_t*)power1_data_cache_L1, 0, POWER_DEVICE_DATA_SIZE); } if(len > POWER_DEVICE_DATA_SIZE - power1_L1_wPos) { len = POWER_DEVICE_DATA_SIZE - power1_L1_wPos; } portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power1_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)&power1_data_cache_L1[power1_L1_wPos], wbuf, len); power1_L1_wPos += len; xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power1_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); if(POWER_DEVICE_DATA_SIZE <= power1_L1_wPos) { power1_L1_status = CACHE_L1_READY; } #endif }break; case POWER_DEVICE_2: { #if SERIAL2_DMARx_ENABLE #else if(bFirst) { power2_L1_status = CACHE_L1_LOADING; power2_L1_wPos = 0; memset((uint8_t*)power2_data_cache_L1, 0, POWER_DEVICE_DATA_SIZE); } if(len > POWER_DEVICE_DATA_SIZE - power2_L1_wPos) { len = POWER_DEVICE_DATA_SIZE - power2_L1_wPos; } portBASE_TYPE xRecvWoken = pdFALSE; xSemaphoreTakeFromISR(mutex_RW_Power2_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); memcpy((uint8_t*)&power2_data_cache_L1[power2_L1_wPos], wbuf, len); power2_L1_wPos += len; xRecvWoken = pdFALSE; xSemaphoreGiveFromISR(mutex_RW_Power2_L1, &xRecvWoken); portYIELD_FROM_ISR(xRecvWoken); if(POWER_DEVICE_DATA_SIZE <= power2_L1_wPos) { power2_L1_status = CACHE_L1_READY; } #endif }break; } } /功率部件一级缓存数据/ /************************************************************ @funName : MD_ReadPowerL2 @Input : device-功率部件序号 rbuf-数据输出缓存 pos-数据读取位置 rlen-数据读取长度 @Output : @Description : 获取功率部件二级缓存数据 @Athor : YL Software Group @Version : V0.0.0 @Data : 2025/5/13 *************************************************************/ bool MD_ReadPowerL2(const uint8_t device, uint8_t *rbuf, const uint16_t pos, const uint16_t rlen) { if(rlen > POWER_DEVICE_DATA_SIZE || pos >= POWER_DEVICE_DATA_SIZE || POWER_DEVICE_DATA_SIZE - pos < rlen) { return false; } switch(device) { case POWER_DEVICE_1: { xSemaphoreTake(mutex_RW_Power1_L2, portMAX_DELAY); memcpy(rbuf, (uint8_t*)&power1_data_cache_L2[pos], rlen); xSemaphoreGive(mutex_RW_Power1_L2); }break; case POWER_DEVICE_2: { xSemaphoreTake(mutex_RW_Power2_L2, portMAX_DELAY); memcpy(rbuf, (uint8_t*)&power2_data_cache_L2[pos], rlen); xSemaphoreGive(mutex_RW_Power2_L2); }break; } return true; } /************************************************************ @funName : MD_GetPowerL2 @Input : device-功率部件序号 rbuf-数据缓存地址 @Output : @Description : 获取功率部件二级缓存地址 @Athor : YL Software Group @Version : V0.0.0 @Data : 2025/5/13 ***********************************************************/ uint8_t MD_GetPowerL2(const uint8_t device) { uint8_t addr = NULL; switch(device) { case POWER_DEVICE_1: { xSemaphoreTake(mutex_RW_Power1_L2, portMAX_DELAY); if(CACHE_L2_SENDING != power1_L2_status) { addr = NULL; } else { power1_L2_status = CACHE_L2_SENT; addr = power1_data_cache_L2; } xSemaphoreGive(mutex_RW_Power1_L2); }break; case POWER_DEVICE_2: { xSemaphoreTake(mutex_RW_Power2_L2, portMAX_DELAY); if(CACHE_L2_SENDING != power2_L2_status) { addr = NULL; } else{ power2_L2_status = CACHE_L2_SENT; addr = power2_data_cache_L2; } xSemaphoreGive(mutex_RW_Power1_L2); }break; } return addr; } /************************ End of file / /************************************************** @file fw_data.h @brief This file contains the macros & function about real data for framework & App. @attention Created on: 2025-05-30 Author: YL Monitor Software group @description ****************************************************************************/ /*************************************************************************** * @file fw_data.h * @brief This file contains the macros & function about real data for framework & App. * **************************************************************************** * @attention * * Created on: 2025-05-30 * Author: YL Monitor Software group * **************************************************************************** * @description * * * ****************************************************************************/ #ifndef __FW_DATA_H_ #define __FW_DATA_H_ #ifdef __cplusplus extern "C" { #endif /************************ Includes *************************/ #include "main.h" /************************ Exportd types ********************/ typedef struct{ uint8_t byte_H; uint8_t byte_L; }Power_Bits16; typedef struct{ uint8_t byte0; uint8_t byte1; uint8_t byte2; uint8_t byte3; }Power_Bits32; /* 功率部件系统参数 */ typedef struct{ /* word 0 */ Power_Bits16 Reserved0; //0-预留 /* word 1 */ Power_Bits16 SYSCTRL; //1-系统控制 /* word 2 */ Power_Bits16 Flag; //2-系统状态标志 /* word 3 */ Power_Bits16 ProtectHard_PROHARD; //3-硬件保护标志 /* word 4 */ Power_Bits16 ProtectSoft_PROSOFT; //4-软件保护标志 /* word 5 */ Power_Bits16 ProtectDrive_PRODRIVE; //5-驱动保护标志 /* word 6 */ Power_Bits16 ProtectComm_PROCOMM; //6-通信保护标志 /* word 7 */ Power_Bits16 INVCTRL; //7-逆变器控制 /* word 8 */ Power_Bits16 Reserved8; //预留 /* word 9 */ Power_Bits16 Reserved9; //预留 /* word 10 */ Power_Bits16 Reserved10; //预留 /* word 11-12 */ Power_Bits32 GPADAT; //GPIO0~31状态 /* word 13-14*/ Power_Bits32 GPBDAT; //GPIO32~63状态 /* word 15-16 */ Power_Bits32 GPCDAT; //GPIO64~87状态 /* word 17 */ Power_Bits16 Reserved17; //预留 /* word 18 */ Power_Bits16 Reserved18; //预留 /* word 19 */ Power_Bits16 Reserved19; //预留 /* word 20 */ Power_Bits16 OSC_CLK_FRQ; //外部晶振频率 /* word 21 */ Power_Bits16 SYS_CLK_FRQ; //系统时钟频率 /* word 22 */ Power_Bits16 SYS_TICK; //定时器时钟基准 /* word 23 */ Power_Bits16 SET_F_PWM; //开关频率 /* word 24 */ Power_Bits16 Reserved24; //预留 /* word 25 */ Power_Bits16 SysMode; //工作模式 /* word 26 */ Power_Bits16 SysState; //工作状态 /* word 27 */ Power_Bits16 SysStartMode; //启动方式 /* word 28*/ Power_Bits16 SysStartStopControl; //启停控制指令来源 /* word 29*/ Power_Bits16 SysCommandSource; //系统频率指令来源 /* word 30*/ Power_Bits16 ModID; //模块编号 /* word 31*/ Power_Bits16 SETUP_UOUT; //电压设定值 /* word 32*/ Power_Bits16 SETUP_IOUT; //电流设定值 /* word 33*/ Power_Bits16 SETUP_FREQ; //频率设定值 /* word 34*/ Power_Bits16 SOFTSTART_TIME; //软件起动时间 /* word 35*/ Power_Bits16 STEP_UOUT; //电压步长 /* word 36*/ Power_Bits16 STEP_IOUT; //电流步长 /* word 37*/ Power_Bits16 STEP_FREQ; //频率步长 /* word 38 */ Power_Bits16 STEP_ANGLE; //相角步长 /* word 39 */ Power_Bits16 POINTCYCLE; //周波点数 /* word 40 */ Power_Bits16 REF_UOUT; //电压给定值 /* word 41 */ Power_Bits16 REF_IOUT; //电流给定值 /* word 42 */ Power_Bits16 REF_FREQ; //频率给定值 /* word 43 */ Power_Bits16 REF_ANGLE; //实时相角 /* word 44 */ Power_Bits16 KPWMA; //A相调制系数 /* word 45 */ Power_Bits16 KPWMB; //B相调制系数 /* word 46 */ Power_Bits16 KPWMC; //C相调制系数 /* word 47 */ Power_Bits16 Effective_Uin; //输入电压有效值 /* word 48 */ Power_Bits16 Effective_Iin; //输入电流有效值 /* word 49 */ Power_Bits16 Effective_Udc; //直流母线电压有效值 /* word 50 */ Power_Bits16 Effective_Uout1; //A相输出电压有效值 /* word 51 */ Power_Bits16 Effective_Uout2; //B相输出电压有效值 /* word 52 */ Power_Bits16 Effective_Uout3; //C相输出电压有效值 /* word 53 */ Power_Bits16 Effective_Iout1; //A相输出电流有效值 /* word 54 */ Power_Bits16 Effective_Iout2; //B相输出电流有效值 /* word 55 */ Power_Bits16 Effective_Iout3; //C相输出电流有效值 /* word 56 */ Power_Bits16 Effective_IL1; //A相电感电流有效值 /* word 57 */ Power_Bits16 Effective_IL2; //B相电感电流有效值 /* word 58 */ Power_Bits16 Effective_IL3; //C相电感电流有效值 /* word 59 */ Power_Bits16 Effective_UinC; //备用电源电压有效值 /* word 60 */ Power_Bits16 Effective_UoutSet; //输出电压设定值(模拟) /* word 61 */ Power_Bits16 Effective_IoutSet; //输出电流设定值(模拟) /* word 62 */ Power_Bits16 Reserved62; //预留 /* word 63 */ Power_Bits16 Effective_FreqSet; //输出电压频率设定值(模拟) /* word 64 */ Power_Bits16 PIDU1_hReference; //PIDU1给定值 /* word 65 */ Power_Bits16 PIDI1_hPresentFeedback; //PIDI1反馈值 /* word 66 */ Power_Bits16 PIDI1_hReference; //PIDI1输出值 /* word 67 */ Power_Bits16 PIDU1_hKp_Gain; //PIDU1参数kp /* word 68*/ Power_Bits16 PIDU1_hKi_Gain; //PIDU1参数ki /* word 69*/ Power_Bits16 PIDU1_hKd_Gain; //PIDU1参数kd /* word 70*/ Power_Bits32 PIDU1_wLower_Limit_Integral; //PIDU1积分下限值 /* word 71*/ Power_Bits32 PIDU1_wUpper_Limit_Integral; //PIDU1积分上限值 /* word 72*/ Power_Bits16 PIDU1_hLower_Limit_Output; //PIDU1输出下限值 /* word 73*/ Power_Bits16 PIDU1_hUpper_Limit_Output; //PIDU1输出上限值 /* word 74*/ Power_Bits16 PIDU2_hReference; //PIDU2给定值 /* word 75*/ Power_Bits16 PIDU2_hPresentFeedback; //PIDU2反馈值 /* word 76*/ Power_Bits16 PIDI2_hReference; //PIDI2输出值 /* word 77*/ Power_Bits16 PIDU2_hKp_Gain; //PIDU2参数kp /* word 78*/ Power_Bits16 PIDU2_hKi_Gain; //PIDU2参数ki /* word 79*/ Power_Bits16 PIDU2_hKd_Gain; //PIDU2参数kd /* word 80*/ Power_Bits32 PIDU2_wLower_Limit_Integral; //PIDU2积分下限值 /* word 81*/ Power_Bits32 PIDU2_wUpper_Limit_Integral; //PIDU2积分上限值 /* word 82*/ Power_Bits16 PIDU2_hLower_Limit_Output; //PIDU2输出下限值 /* word 83*/ Power_Bits16 PIDU2_hUpper_Limit_Output; //PIDU2输出上限值 /* word 84 */ Power_Bits16 PIDI1hReference; //PIDI1给定值 /* word 85 */ Power_Bits16 PIDI1hPresentFeedback; //PIDI1反馈值 /* word 86 */ Power_Bits16 iParkUref_Ds; //PIDI1输出值 /* word 87 */ Power_Bits16 PIDI1_hKp_Gain; //PIDI1参数kp /* word 88*/ Power_Bits16 PIDI1_hKi_Gain; //PIDI1参数ki /* word 89*/ Power_Bits16 PIDI1_hKd_Gain; //PIDI1参数kd /* word 90*/ Power_Bits32 PIDI1_wLower_Limit_Integral; //PIDI1积分下限值 /* word 91*/ Power_Bits32 PIDI1_wUpper_Limit_Integral; //PIDI1积分上限值 /* word 92*/ Power_Bits16 PIDI1_hLower_Limit_Output; //PIDI1输出下限值 /* word 93*/ Power_Bits16 PIDI1_hUpper_Limit_Output; //PIDI1输出上限值 /* word 94 */ Power_Bits16 PIDI2hReference; //PIDI2给定值 /* word 95 */ Power_Bits16 PIDI2_hPresentFeedback; //PIDI2反馈值 /* word 96 */ Power_Bits16 iParkUref_Qs; //输出值 /* word 97 */ Power_Bits16 PIDI2_hKp_Gain; //PIDI2参数kp /* word 98*/ Power_Bits16 PIDI2_hKi_Gain; //PIDI2参数ki /* word 99*/ Power_Bits16 PIDI2_hKd_Gain; //PIDI2参数kd /* word 100*/ Power_Bits32 PIDI2_wLower_Limit_Integral; //PIDI2积分下限值 /* word 101*/ Power_Bits32 PIDI2_wUpper_Limit_Integral; //PIDI2积分上限值 /* word 102*/ Power_Bits16 PIDI2_hLower_Limit_Output; //PIDI2输出下限值 /* word 103*/ Power_Bits16 PIDI2_hUpper_Limit_Output; //PIDI2输出上限值 /* word 104 */ Power_Bits16 PIDPARA_hReference; //PIDPARA给定值 /* word 105 */ Power_Bits16 PIDPARA_hPresentFeedback; //PIDPARA反馈值 /* word 106 */ Power_Bits16 Reserved106; //PIDPARA输出值 /* word 107 */ Power_Bits16 PIDPARA_hKp_Gain; //PIDPARA参数kp /* word 108*/ Power_Bits16 PIDPARA_hKi_Gain; //PIDPARA参数ki /* word 109*/ Power_Bits16 PIDPARA_hKd_Gain; //PIDPARA参数kd /* word 110*/ Power_Bits32 PIDPARA_wLower_Limit_Integral;//PIDPARA积分下限值 /* word 111*/ Power_Bits32 PIDPARA_wUpper_Limit_Integral;//PIDPARA积分上限值 /* word 112*/ Power_Bits16 PIDPARA_hLower_Limit_Output; //PIDPARA输出下限值 /* word 113*/ Power_Bits16 PIDPARA_hUpper_Limit_Output; //PIDPARA输出上限值 /* word 114 */ Power_Bits16 PIDPLL_hReference; //PIDPLL给定值 /* word 115 */ Power_Bits16 PIDPLL_hPresentFeedback; //PIDPLL反馈值 /* word 116 */ Power_Bits16 Reserved116; //PIDPLL输出值 /* word 117 */ Power_Bits16 PIDPLL_hKp_Gain; //PIDPLL参数kp /* word 118*/ Power_Bits16 PIDPLL_hKi_Gain; //PIDPLL参数ki /* word 119*/ Power_Bits16 PIDPLL_hKd_Gain; //PIDPLL参数kd /* word 120*/ Power_Bits32 PIDPLL_wLower_Limit_Integral; //PIDPLL积分下限值 /* word 121*/ Power_Bits32 PIDPLL_wUpper_Limit_Integral; //PIDPLL积分上限值 /* word 122*/ Power_Bits16 PIDPLL_hLower_Limit_Output; //PIDPLL输出下限值 /* word 123*/ Power_Bits16 PIDPLL_hUpper_Limit_Output; //PIDPLL输出上限值 /* word 124 */ Power_Bits16 Reserved124; //输出变压器变比 /* word 125 */ Power_Bits16 Reserved125; //变压器等效电抗 /* word 126 */ Power_Bits16 Reserved126; //变压器等效电阻 /* word 127 */ Power_Bits16 Reserved127; //预留 /* word 128 */ Power_Bits16 FdOverUin_ValLimitHi; //输入过压保护值 /* word 129 */ Power_Bits16 FdUnderUin_ValLimitHi; //输入欠压保护值 /* word 130 */ Power_Bits16 FdOverIin_ValLimitHi; //输入过流保护值 /* word 131 */ Power_Bits16 FdOverUo1_ValLimitHi; //输出过压保护值 /* word 132 */ Power_Bits16 FdOverIo1_ValLimitHi; //输出过流保护值 /* word 133 */ Power_Bits16 FdOverIL1_ValLimitHi; //电感过流保护值 /* word 134 */ Power_Bits16 Reserved134; //短路保护电压动作值 /* word 135 */ Power_Bits16 Reserved135; //短路保护电流动作值 /* word 136 */ Power_Bits16 Reserved136; //短路保护电压返回值 /* word 137 */ Power_Bits16 Reserved137; //短路保护电流返回值 /* word 138 */ Power_Bits16 Reserved138; //短路运行时间 /* word 139 */ Power_Bits16 Reserved139; //110%过载保护限值 /* word 140 */ Power_Bits16 Reserved140; //110%过载保护时间 /* word 141 */ Power_Bits16 Reserved141; //110%过载保护倒计时 /* word 142 */ Power_Bits16 Reserved142; //120%过载保护限值 /* word 143 */ Power_Bits16 Reserved143; //120%过载保护时间 /* word 144 */ Power_Bits16 Reserved144; //120%过载保护倒计时 /* word 145 预留*/ Power_Bits16 Reserved145; /* word 146 AD结果寄存器数据(CH0)*/ Power_Bits16 AdcRegs_ADCRESULT0; /* word 147 */ Power_Bits16 AdcRegs_ADCRESULT1; //AD结果寄存器数据(CH1) /* word 148 */ Power_Bits16 AdcRegs_ADCRESULT2; //AD结果寄存器数据(CH2) /* word 149 */ Power_Bits16 AdcRegs_ADCRESULT3; //AD结果寄存器数据(CH3) /* word 150 */ Power_Bits16 AdcRegs_ADCRESULT4; //AD结果寄存器数据(CH4) /* word 151 */ Power_Bits16 AdcRegs_ADCRESULT5; //AD结果寄存器数据(CH5) /* word 152 */ Power_Bits16 AdcRegs_ADCRESULT6; //AD结果寄存器数据(CH6) /* word 153 */ Power_Bits16 AdcRegs_ADCRESULT7; //AD结果寄存器数据(CH7) /* word 154 */ Power_Bits16 AdcRegs_ADCRESULT8; //AD结果寄存器数据(CH8) /* word 155 */ Power_Bits16 AdcRegs_ADCRESULT9; //AD结果寄存器数据(CH9) /* word 156 */ Power_Bits16 AdcRegs_ADCRESULT10; //AD结果寄存器数据(CH10) /* word 157 */ Power_Bits16 AdcRegs_ADCRESULT11; //AD结果寄存器数据(CH11) /* word 158 */ Power_Bits16 AdcRegs_ADCRESULT12; //AD结果寄存器数据(CH12) /* word 159 */ Power_Bits16 AdcRegs_ADCRESULT13; //AD结果寄存器数据(CH13) /* word 160 */ Power_Bits16 AdcRegs_ADCRESULT14; //AD结果寄存器数据(CH14) /* word 161 */ Power_Bits16 AdcRegs_ADCRESULT15; //AD结果寄存器数据(CH15) /* word 162 预留*/ Power_Bits16 Reserved162; /* word 163 预留*/ Power_Bits16 Reserved163; /* word 164 预留*/ Power_Bits16 Reserved164; /* word 165 预留*/ Power_Bits16 Reserved165; /* word 166 预留*/ Power_Bits16 Reserved166; /* word 167 预留*/ Power_Bits16 Reserved167; /* word 168 预留*/ Power_Bits16 Reserved168; /* word 169预留 */ Power_Bits16 Reserved169; /* word 170 预留*/ Power_Bits16 Reserved170; /* word 171 预留*/ Power_Bits16 Reserved171; /* word 172 预留*/ Power_Bits16 Reserved172; /* word 173 预留*/ Power_Bits16 Reserved173; /* word 174 预留*/ Power_Bits16 Reserved174; /* word 175 预留*/ Power_Bits16 Reserved175; /* word 176 预留*/ Power_Bits16 Reserved176; /* word 177 预留*/ Power_Bits16 Reserved177; /* word 178 预留*/ Power_Bits16 Reserved178; /* word 179 预留*/ Power_Bits16 Reserved179; /* word 180 输入电压传感器采样范围*/ Power_Bits16 PEAK_UIN_SENSOR; /* word 181 输入电流传感器采样范围*/ Power_Bits16 PEAK_IIN_SENSOR; /* word 182 输出电压传感器采样范围*/ Power_Bits16 PEAK_UO_SENSOR; /* word 183 输出电流传感器采样范围*/ Power_Bits16 PEAK_IO_SENSOR; /* word 184 电感电流传感器采样范围*/ Power_Bits16 PEAK_IL_SENSOR; /* word 185 预留*/ Power_Bits16 Reserved185; /* word 186 预留*/ Power_Bits16 Reserved186; /* word 187 预留*/ Power_Bits16 Reserved187; /* word 188 预留*/ Power_Bits16 Reserved188; /* word 189 预留*/ Power_Bits16 Reserved189; /* word 190 通道选择*/ Power_Bits16 ChannelSelect; /* word 191 预留*/ Power_Bits16 Reserved191; /* word 192 预留*/ Power_Bits16 Reserved192; /* word 193 地址偏移量*/ Power_Bits16 AddressOffset; /* word 194 预留*/ Power_Bits16 Reserved194; /* word 195 预留*/ Power_Bits16 Reserved195; /* word 196 预留*/ Power_Bits16 Reserved196; /* word 197 预留*/ Power_Bits16 Reserved197; /* word 198 预留*/ Power_Bits16 Reserved198; /* word 199 网络通讯协议控制*/ Power_Bits16 Modbus_Control_ModbusCtrl; }Power_System_Type; STM32F105 power_data.c程序的二级缓存的400字节的数据准确的映射给fw_data.h程序中的Power_System_Type结构体中,然后去调用结构体的某一个数据,需要频繁访问结构体中的某个字段,可以将其缓存到局部变量中,减少多次访问互斥锁的开销,用标准库写出详细代码和注释,优化的建议也写入代码中,别单独提出来

大家在看

recommend-type

Android_Get_IMEI.rar

IMEI是一个缩写,移动设备识别码 (国际移动设备识别码)。这是每个设备的唯一数字序列和特殊字符。这个想法非常类似于网卡的MAC地址。这使得每月在市场上的数百个设备中定位特定设备变得容易。创建Mobile Delphi 10.3应用程序移动APP,确保只有授权的“人员”APP才能查看公司信息是至关重要的。
recommend-type

该压缩包里是详细介绍下载和安装tableau的步骤:包括一、下载和安装Tableau、二、Tableau页面介绍等等

该压缩包里是详细介绍下载和安装tableau的步骤:包括一、下载和安装Tableau、二、Tableau页面介绍、三、Tableau绘制条形图、四、Tableau绘制直方图、五、数据预处理、六、绘制折线图、七、饼图与环形图、八、基本表、九、树形图、十、气泡图与词云、十一、Tableau制作标靶图、十二、Tableau制作甘特图、十三、Tableau进阶、十四、填充地图、十五、多维地图、十六、数据分(层级)结构、十七、数据分组、十八、计算字段、十九、人口金字塔、二十、范围-线图
recommend-type

f1rs485 - host.zip

主要是读取modbus协议传感器的数据,主要是功能03,利用rs485接口,将读取的数据显示到串口助手上
recommend-type

SmartSVN license

和谐SmartSVN试用版的license,下载后覆盖即可。(注意:覆盖前最好备份原license)
recommend-type

《深度学习噪声标签学习》综述论文

在海量大数据的帮助下,深度学习在许多领域都取得了显著的成功。但是,数据标签的质量是一个问题,因为在许多现实场景中缺乏高质量的标签。

最新推荐

recommend-type

市政工程施工进度横道图(内含CAD网络图).doc

市政工程施工进度横道图(内含CAD网络图).doc
recommend-type

Delphi实现U盘自动运行防护源码解析

Delphi是一种高级的、结构化的编程语言,它非常适合快速开发各种类型的应用程序。它由一家名为Borland的公司最初开发,后来Embarcadero Technologies接管了它。Delphi的特点是其强大的可视化开发环境,尤其是对于数据库和Windows应用程序的开发。它使用的是Object Pascal语言,结合了面向对象和过程式编程的特性。 当涉及到防自动运行源码时,Delphi可以实现一些功能,用以阻止病毒利用Windows的自动运行机制来传播。自动运行(AutoRun)功能允许操作系统在插入特定类型的媒体(如U盘、移动硬盘)时自动执行程序。这对于病毒来说是一个潜在的攻击向量,因为病毒可能隐藏在这些媒体上,并利用AutoRun功能自动执行恶意代码。 在Delphi中实现防自动运行的功能,主要是通过编程监测和控制Windows注册表和系统策略来达到目的。自动运行功能通常与Windows的注册表项“HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer”以及“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer”相关联。通过修改或锁定这些注册表项,可以禁用自动运行功能。 一种常见的方法是设置“NoDriveTypeAutoRun”注册表值。这个值可以被设置为一个特定的数字,这个数字代表了哪些类型的驱动器不会自动运行。例如,如果设置了“1”(二进制的00000001),则系统会阻止所有非CD-ROM驱动器的自动运行。 除了直接修改注册表,还可以通过编程方式使用Windows API函数来操作这些设置。Delphi提供了直接调用Windows API的机制,它允许开发者调用系统底层的功能,包括那些与注册表交互的功能。 同时,Delphi中的TRegistry类可以简化注册表操作的复杂性。TRegistry类提供了简单的接口来读取、写入和修改Windows注册表。通过这个类,开发者可以更加便捷地实现禁用自动运行的功能。 然而,需要注意的是,单纯依赖注册表级别的禁用自动运行并不能提供完全的安全保障。病毒和恶意软件作者可能会发现绕过这些限制的新方法。因此,实现多重防护措施是很重要的,比如使用防病毒软件,定期更新系统和安全补丁,以及进行安全意识教育。 此外,为了确保源码的安全性和有效性,在使用Delphi编程实现防自动运行功能时,应遵循最佳编程实践,例如对代码进行模块化设计,编写清晰的文档,以及进行彻底的测试,确保在不同的系统配置和条件下都能稳定运行。 总结来说,使用Delphi编写防自动运行源码涉及对Windows注册表和系统策略的控制,需要良好的编程习惯和安全意识,以构建既安全又可靠的解决方案。在文件名称列表中提到的“Delphi防自动运行源码”,可能就是一个实现了上述功能的Delphi项目文件。
recommend-type

【性能测试基准】:为RK3588选择合适的NVMe性能测试工具指南

# 1. NVMe性能测试基础 ## 1.1 NVMe协议简介 NVMe,全称为Non-Volatile Memory Express,是专为固态驱动器设计的逻辑设备接口规范。与传统的SATA接口相比,NVMe通过使用PCI Express(PCIe)总线,大大提高了存储设备的数据吞吐量和IOPS(每秒输入输出操作次数),特别适合于高速的固态存储设备。
recommend-type

如果有外码,定义各基本表外码。

### 如何在数据库中定义包含外码的基本表 在外键存在的场景下,定义基本表的外键关系是为了确保两个表之间的数据一致性和参照完整性。以下是关于如何定义外键关系的具体说明: #### 定义外键的基本语法 外键可以通过 `ALTER TABLE` 或者创建表时直接指定的方式进行定义。以下是一般情况下定义外键的 SQL 语法[^5]: ```sql CREATE TABLE 子表 ( 列名1 数据类型, 列名2 数据类型, ... CONSTRAINT 外键名称 FOREIGN KEY (子表列名) REFERENCES 主表(主表列名) ); ``` 如果是在已
recommend-type

F-FTP开源资源下载器:自动下载、续传与暂停功能

标题中提到的“F-FTP资源下载工具(开源)”指向了一款针对文件传输协议(FTP)的资源下载工具。FTP是一种用于在网络上进行文件传输的标准协议,它允许用户将文件从一台计算机传输到另一台计算机上。开源意味着该工具的源代码是公开的,意味着用户和开发者都可以自由地查看、修改和分发该软件。 根据描述,“自动下载FTP资源工具,支持续传,支持暂停,个人作品,没事写来玩玩。”我们可以提取以下知识点: 1. 自动下载功能:这款工具具备自动化下载的能力,用户无需手动选择和下载文件。它可能具备自动搜索FTP服务器上的资源、自动排队下载和自动处理错误等功能。 2. 续传功能:FTP下载过程中可能会因为网络问题、服务器问题或是用户自身原因而中断。该工具支持断点续传功能,即在下载中断后能够从上次中断的位置继续下载,而不是重新开始,这对于大规模文件的下载尤其重要。 3. 暂停功能:用户在下载过程中可能因为某些原因需要暂时停止下载,该工具支持暂停功能,用户可以在任何时候暂停下载,并在适当的时候恢复下载。 4. 个人作品:这意味着该软件是由一个或少数开发者作为业余项目开发的。它可能表明该软件的成熟度和稳定性可能低于商业软件,但也不排除其具备某些独到的功能或特性。 5. 开源:工具的源代码是可以公开获取的。这为技术社区的成员提供了研究和改进软件的机会。开源软件通常由社区维护和更新,可以充分利用集体智慧来解决问题和增加新功能。 标签“FTP”已经解释了该工具的主要用途,即处理FTP协议相关的文件下载任务。 压缩包子文件的文件名称列表中的“F-ftp2”可能指的是这款开源FTP资源下载工具的文件名。由于描述中只提到“F-ftp”,所以“F-ftp2”可能是该工具的更新或升级版本,或者仅仅是文件压缩包的命名。 从这些信息来看,如果你是一名网络管理员、开发者或对FTP下载工具有需求的用户,这个工具可能对你非常有用,特别是如果你希望自动下载资源、需要支持续传和暂停功能以处理可能的中断,以及对开源项目有兴趣并愿意参与到项目贡献中。在使用此类开源工具时,建议对源代码进行审查,以确保其安全性和是否符合你的需求,并考虑是否参与改进工具。同时,由于是个人作品,应当准备好可能存在的文档不全、缺乏技术支持等问题,或在使用过程中遇到的任何潜在问题。
recommend-type

【固态硬盘寿命延长】:RK3588平台NVMe维护技巧大公开

# 1. 固态硬盘寿命延长的基础知识 ## 1.1 固态硬盘的基本概念 固态硬盘(SSD)是现代计算设备中不可或缺的存储设备之一。与传统的机械硬盘(HDD)相比,SSD拥有更快的读写速度、更小的体积和更低的功耗。但是,SSD也有其生命周期限制,主要受限于NAND闪存的写入次数。 ## 1.2 SSD的写入次数和寿命 每块SSD中的NAND闪存单元都有有限的写入次数。这意味着,随着时间的推移,SSD的
recommend-type

reduce怎么写多维转一维

### 使用 `reduce` 方法实现多维数组转一维数组 在 JavaScript 中,可以利用 `reduce()` 和 `concat()` 方法将多维数组展平为一维数组。以下是详细的解释以及代码示例。 #### 原理说明 `reduce()` 是一种高阶函数,用于遍历数组并对累积器执行回调操作。通过将其与 `concat()` 配合使用,可以逐步将嵌套的子数组拼接到最终的一维数组中[^1]。 #### 示例代码 以下是一个完整的代码示例: ```javascript // 定义一个多维数组 const multiDimensionalArray = [1, [2, [3, 4]
recommend-type

视频会议电子白板功能实现与设备需求

视频会议系统是一种远程通信技术,允许位于不同地理位置的人们通过互联网进行音频、视频及数据的实时传输和交流,是一种高效的沟通和协作工具。其中,电子白板功能是视频会议中的一项重要功能,它模拟了传统会议中使用白板的场景,使得参会者能够通过电子的方式共同协作,绘制图形、书写文字、分享文件以及标注信息等。在技术实现层面,电子白板功能通常需要依赖特定的软件和硬件设备。 首先,电子白板功能的核心在于能够实时捕捉和共享会议参与者的书写内容。在本例中,电子白板功能在 Windows XP 系统上使用 Visual C++ 6.0 环境编译通过,这意味着软件是用C++语言编写,并且特别针对Windows XP系统进行了优化。Visual C++ 6.0 是微软公司早期的一款开发工具,主要用于创建Windows桌面应用程序。虽然它已经较为老旧,但不少企业仍然在使用旧的系统和软件,因为它们已经稳定且经过了长时间的验证。 电子白板功能的实现还依赖于rtcdll.dll文件。这个文件很可能是程序运行时需要用到的一个动态链接库(DLL)文件。动态链接库是Windows操作系统中一种实现共享函数库的方式,允许程序共享执行代码和数据。DLL文件通常包含可由多个程序同时使用的代码和数据,使得应用程序体积更小,效率更高。在Windows系统中,许多标准功能和服务都是通过DLL文件实现的。通常,rtcdll.dll文件可能与音视频编解码、网络通信等实时传输功能相关,这在电子白板功能中尤其重要,因为它需要实时同步所有参会者的操作。 此外,电子白板功能的实现也离不开摄像头和麦克风等输入设备。摄像头负责捕获视频图像,让参与视频会议的各方能够看到彼此的面貌和表情,进而增加交流的真实感。麦克风则负责捕捉声音,使得参与者可以进行语音交流。这两个硬件设备对于任何基于视频的远程会议来说都是必不可少的。 在使用电子白板时,用户可以通过触摸屏或者专用的电子笔在电子白板上进行操作,其他参会者则可以实时看到这些操作。这种共享式的交互方式极大地提高了远程协作的效率。在远程教学、远程演示、远程培训、远程会议等场景中,电子白板功能都能够提供强大的视觉支持和互动体验。 考虑到视频会议系统的安全性,还需要注意电子白板在共享内容时的权限控制。在商业和教育环境中,可能需要限制某些敏感信息的共享,或者确保内容在传输和存储过程中的加密,防止信息泄露。 最后,需要注意的是,随着云计算和移动互联网技术的发展,基于云服务的视频会议平台逐渐成为主流。这类平台通常支持跨平台使用,用户可以随时随地通过多种设备加入视频会议,分享电子白板,并且无需关心系统兼容性或本地安装的详细配置问题。这进一步降低了视频会议技术的门槛,也使得电子白板功能更加普及和便捷。
recommend-type

【故障恢复策略】:RK3588与NVMe固态硬盘的容灾方案指南

# 1. RK3588处理器与NVMe固态硬盘的概述 ## 1.1 RK3588处理器简介 RK3588是Rockchip推出的一款高端处理器,具备强大的性能和多样的功能,集成了八核CPU和六核GPU,以及专用的AI处理单元,主要用于高端移动设备、边缘计算和
recommend-type

python智能搜索excel中的数据

<think>好的,我需要处理用户的问题:如何用Python实现对Excel文件中数据的智能搜索,使用pandas和openpyxl进行数据处理。首先,用户提到的工具是pandas和openpyxl,这两个库都是处理Excel的常用工具。pandas主要用于数据分析和处理,而openpyxl则用于读写Excel文件,特别是.xlsx格式。 接下来,我需要确定什么是“智能搜索”。用户可能指的是模糊匹配、关键词搜索、多条件筛选,或者更高级的自然语言处理。但考虑到用户提到的库是pandas和openpyxl,可能更倾向于基础的数据处理功能。因此,我应该先覆盖基本的搜索方法,再扩展到更智能的方面,比