当前位置: 首页 > news >正文

CSerialPort教程4.3.x (2) - CSerialPort源码简介

CSerialPort教程4.3.x (2) - CSerialPort源码简介

前言

CSerialPort项目是一个基于C/C++的轻量级开源跨平台串口类库,可以轻松实现跨平台多操作系统的串口读写,同时还支持C#, Java, Python, Node.js等。

CSerialPort项目的开源协议自 V3.0.0.171216 版本后采用GNU Lesser General Public License v3.0

为了让开发者更好的使用CSerialPort进行开发,特编写基于4.3.x版本的CSerialPort教程系列。

CSerialPort项目地址:

  • https://github.com/itas109/CSerialPort
  • https://gitee.com/itas109/CSerialPort

本文对CSerialPort 4.3.0版本源码进行简介。

1. CSerialPort源码目录结构

CSerialPort # root
+--- .clang-format # code format 代码规范
├── bindings # 第三方语言接口
│   ├── c # c interface c接口
│   ├── csharp # csharp interface c#接口
│   ├── java # java interface java接口
│   ├── javascript # javascript interface javascript接口
│   └── python # python interface python接口
├── CHANGELOG.md # change log 修改日志
├── cmake # cross compile 交叉编译
├── CMakeLists.txt
├── doc # document 文档
├── examples # example 示例程序
│   ├── CommMFC # CSerialPort MFC Demo MFC程序示例
│   ├── CommNoGui # CSerialPort No Gui Demo 无界面程序示例
│   ├── CommQT # CSerialPort QT Demo QT程序示例
│   ├── CommTui # CSerialPort tui Demo 文本界面程序示例
│   ├── CommWXWidgets # CSerialPort wxwidgets Demo wxwidgets界面程序示例
├── include # headers 头文件
│   └── CSerialPort
│       ├── ibuffer.hpp # lightweight cross-platform buffer library 轻量级跨平台缓冲区类
│       ├── ithread.hpp # lightweight cross-platform thread library 轻量级跨平台线程类
│       ├── itimer.hpp # lightweight cross-platform timer library 轻量级跨平台定时器类
│       ├── iutils.hpp # lightweight cross-platform utils library 轻量级跨平台工具类
│       ├── SerialPortBase.h # CSerialPort Base class 串口基类
│       ├── SerialPort_global.h # Global difine of CSerialPort 串口全局定义 
│       ├── SerialPort.h # lightweight cross-platform serial port library 轻量级跨平台串口类库
│       ├── SerialPortInfoBase.h # CSerialPortInfo Base class 串口信息辅助类基类
│       ├── SerialPortInfo.h # CSerialPortInfo class 串口信息辅助类
│       ├── SerialPortInfoUnixBase.h # CSerialPortInfo unix class unix串口信息辅助类基类
│       ├── SerialPortInfoWinBase.h # CSerialPortInfo windows class windows串口信息辅助类基类
│       ├── SerialPortListener.h # CSerialPortListener interface class 串口事件监听接口类
│       ├── SerialPortUnixBase.h # CSerialPort unix Base class unix串口基类
│       ├── SerialPort_version.h # CSerialPort version 版本定义
│       └── SerialPortWinBase.h # CSerialPort Windows Base class windows串口基类
├── lib # lib 库目录
├── LICENSE # LGPL3.0 license
├── pic # picture 图片
├── README.md
├── README_zh_CN.md
├── src # source 源代码
├── test # unit test 单元测试
└── VERSION # version 版本号

2. CSerialPort常用函数

2.1 串口信息相关函数

2.1.1 获取串口信息列表函数 availablePortInfos

该函数获取串口信息列表,主要包括:

  • 串口名称 (如COM2)
  • 描述信息 (如USB-SERIAL CH340)
  • 硬件id (如USB\VID_1A86&PID_7523&REV_0264)
static vector<SerialPortInfo> itas109::CSerialPortInfo::availablePortInfos()

2.2 串口操作相关函数

2.2.1 串口初始化函数 init

该函数用于串口初始化。

void itas109::CSerialPort::init(const char *portName,                                 // 串口名称 Windows:COM1 Linux:/dev/ttyS0int baudRate = itas109::BaudRate9600,                 // 波特率itas109::Parity parity = itas109::ParityNone,         // 校验位itas109::DataBits dataBits = itas109::DataBits8,      // 数据位itas109::StopBits stopbits = itas109::StopOne,        // 停止位itas109::FlowControl flowControl = itas109::FlowNone, // 流控制unsigned int readBufferSize = 4096                    // 读取缓冲区大小
)

注意:

  • 5位数据位不能使用2位停止位
  • 1.5位停止位不能使用5位数据位
  • POSIX系统8位数据位不能使用0校验
  • windows数据位范围为4 - 8
  • 1.5位停止位仅对windows有效
  • 停止位数字1表示StopOneAndHalf,即1.5位停止位,并非1位停止位

2.2.2 打开串口函数 open

该函数用于打开串口。

bool itas109::CSerialPort::open()

true表示打开成功,false表示打开失败。

打开失败可用itas109::CSerialPort::getLastError()获取错误码

2.2.3 关闭串口函数 close

该函数用于关闭串口。

void itas109::CSerialPort::close()

2.2.4 是否打开串口成功函数 isOpen

该函数用于获取是否打开串口成功。

bool itas109::CSerialPort::isOpen()

true表示串口打开成功,false表示串口打开失败。

2.2.5 向串口写入数据函数 writeData

该函数用于向串口写入数据。

int itas109::CSerialPort::writeData(const void *data, // 待写入数据int maxSize       // 写入长度
)

成功则返回写入字节数,失败则返回-1。

写入失败可用itas109::CSerialPort::getLastError()获取错误码。

2.2.6 从串口读取指定长度数据函数 readData

该函数用于从串口读取指定长度数据。

int readData(void *data,  // 读取结果int size     // 读取长度
)

正常则返回读取字节数,失败则返回-1。

读取失败可用itas109::CSerialPort::getLastError()获取错误码。

注意:
CSerialPort异步操作模式下,需要配合connectReadEvent函数使用。详见第三节的代码示例。

2.2.7 从串口读取所有数据函数 readAllData

该函数用于从串口读取所有数据。

int itas109::CSerialPort::readAllData(void *data // 读取结果
)

正常则返回读取字节数,失败则返回-1。

读取失败可用itas109::CSerialPort::getLastError()获取错误码。

注意:
CSerialPort异步操作模式下,需要配合connectReadEvent函数使用。详见第三节的代码示例。

2.2.8 绑定读取事件函数 connectReadEvent

该函数用于异步模式(默认)下,绑定读取响应的结果。

需要继承CSerialPortListener,并实现onReadEvent虚函数。详见第三节的代码示例。

class MyListener : public CSerialPortListener
{
public:void onReadEvent(const char *portName, unsigned int readBufferLen){}
}

2.2.9 获取CSerialPort版本信息函数 getVersion

该函数用于获取CSerialPort版本信息。

std::string itas109::CSerialPort::getVersion()

返回CSerialPort版本信息,如https://github.com/itas109/CSerialPort - V4.3.0.230215

2.2.10 错误码 SerialPortError

错误码数值错误码宏定义错误码说明
-1ErrorUnknownunknown error 未知错误
0ErrorOKok 成功
1ErrorFailgeneral error一般性错误
2ErrorNotImplementednot implemented 未实现
3ErrorInnerinner error 内部错误(如内存访问异常等)
4ErrorNullPointernull pointer error 空指针错误
5ErrorInvalidParaminvalid parameter error 无效的参数
6ErrorAccessDeniedaccess denied error 权限错误
7ErrorOutOfMemoryout of memory 内存不足
8ErrorTimeouttime out error 超时
9ErrorNotInitnot init 未初始化
10ErrorInitFailedinit failed 初始化失败
11ErrorAlreadyExistalready exist 已经存在
12ErrorNotExistnot exist 不存在
13ErrorAlreadyOpenalready open 已经打开
14ErrorNotOpennot open 未打开
15ErrorOpenFailedopen failed 打开失败
16ErrorCloseFailedclose failed 关闭失败
17ErrorWriteFailedwrite failed 写入失败
18ErrorReadFailedread failed 读取失败

3. CSerialPort简单代码示例

  • 操作步骤
$ mkdir CSerialPortDemo
$ cd CSerialPortDemo
$ git clone https://github.com/itas109/CSerialPort
$ touch CSerialPortDemo.cpp
$ touch CMakeLists.txt
$ mkdir bin 
$ cd bin
$ cmake ..
$ cmake --build .
  • 目录结构
$ tree
.
+--- CMakeLists.txt
+--- CSerialPort
|   +--- include
|   +--- src
|   +--- ...
+--- CSerialPortDemo.cpp
  • CSerialPortDemo.cpp

注意:接收函数需要继承CSerialPortListener

#include <iostream>#include "CSerialPort/SerialPort.h"
#include "CSerialPort/SerialPortInfo.h"#include <vector>
using namespace itas109;
using namespace std;class MyListener : public CSerialPortListener
{
public:MyListener(CSerialPort *sp): p_sp(sp){};void onReadEvent(const char *portName, unsigned int readBufferLen){if (readBufferLen > 0){char *data = new char[readBufferLen + 1]; // '\0'if (data){// readint recLen = p_sp->readData(data, readBufferLen);if (recLen > 0){data[recLen] = '\0';std::cout << portName << ", Length: " << recLen << ", Str: " << data << std::endl;}delete[] data;data = NULL;}}};private:CSerialPort *p_sp;
};int main()
{CSerialPort sp;MyListener listener(&sp);std::cout << "Version : " << sp.getVersion() << std::endl << std::endl;vector<SerialPortInfo> m_availablePortsList = CSerialPortInfo::availablePortInfos();std::cout << "availableFriendlyPorts: " << std::endl;for (size_t i = 1; i <= m_availablePortsList.size(); ++i){SerialPortInfo serialPortInfo = m_availablePortsList[i - 1];std::cout << i << " - " << serialPortInfo.portName << " " << serialPortInfo.description << " " << serialPortInfo.hardwareId << std::endl;}if (m_availablePortsList.size() == 0){std::cout << "No valid port" << std::endl;}else{std::cout << std::endl;int input = -1;do{std::cout << "Please Input The Index Of Port(1 - " << m_availablePortsList.size() << ")" << std::endl;std::cin >> input;if (input >= 1 && input <= m_availablePortsList.size()){break;}} while (true);const char *portName = m_availablePortsList[input - 1].portName;std::cout << "Port Name: " << portName << std::endl;sp.init(portName,              // windows:COM1 Linux:/dev/ttyS0itas109::BaudRate9600, // baudrateitas109::ParityNone,   // parityitas109::DataBits8,    // data bititas109::StopOne,      // stop bititas109::FlowNone,     // flow4096                   // read buffer size);sp.setReadIntervalTimeout(0); // read interval timeout 0ms// sp.setOperateMode(itas109::SynchronousOperate);sp.open();std::cout << "Open " << portName << (sp.isOpen() ? " Success. " : " Failed. ");std::cout << "Code: " << sp.getLastError() << ", Message: " << sp.getLastErrorMsg() << std::endl;// 绑定读取函数sp.connectReadEvent(&listener);// 写入数据sp.writeData("itas109", 7);for (;;){}}return 0;
}
  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)project(CSerialPortDemo)if(APPLE)find_library(IOKIT_LIBRARY IOKit)find_library(FOUNDATION_LIBRARY Foundation)
endif()include_directories(CSerialPort/include)
file(GLOB_RECURSE COMMON_SOURCES CSerialPort/src/SerialPort.cpp CSerialPort/src/SerialPortBase.cpp CSerialPort/src/SerialPortInfo.cpp CSerialPort/src/SerialPortInfoBase.cpp)
if (CMAKE_HOST_WIN32)file(GLOB_RECURSE OS_ABOUT_SOURCES CSerialPort/src/SerialPortInfoWinBase.cpp CSerialPort/src/SerialPortWinBase.cpp)
elseif (CMAKE_HOST_UNIX)file(GLOB_RECURSE OS_ABOUT_SOURCES CSerialPort/src/SerialPortInfoUnixBase.cpp CSerialPort/src/SerialPortUnixBase.cpp)
endif ()	add_executable( ${PROJECT_NAME} CSerialPortDemo.cpp ${COMMON_SOURCES} ${OS_ABOUT_SOURCES})if (WIN32)target_link_libraries( ${PROJECT_NAME} setupapi )
elseif (APPLE)target_link_libraries( ${PROJECT_NAME} ${FOUNDATION_LIBRARY} ${IOKIT_LIBRARY})
elseif (UNIX)target_link_libraries( ${PROJECT_NAME} pthread )
endif ()
  • 运行结果(windows下环回测试)
Version : https://github.com/itas109/CSerialPort - V4.3.0.230215availableFriendlyPorts:
1 - COM1 USB-SERIAL CH340  USB\VID_1A86&PID_7523&REV_0264Please Input The Index Of Port(1 - 1)
1
Port Name: COM1
Open COM1 Success. Code: 0, Message: success
COM1, Length: 7, Str: itas109

License

License under CC BY-NC-ND 4.0: 署名-非商业使用-禁止演绎


Reference:

  1. https://github.com/itas109/CSerialPort
  2. https://gitee.com/itas109/CSerialPort
  3. https://blog.csdn.net/itas109

相关文章:

CSerialPort教程4.3.x (2) - CSerialPort源码简介

CSerialPort教程4.3.x (2) - CSerialPort源码简介 前言 CSerialPort项目是一个基于C/C的轻量级开源跨平台串口类库&#xff0c;可以轻松实现跨平台多操作系统的串口读写&#xff0c;同时还支持C#, Java, Python, Node.js等。 CSerialPort项目的开源协议自 V3.0.0.171216 版本…...

【数据结构OJ题】有效的括号

原题链接&#xff1a;https://leetcode.cn/problems/valid-parentheses/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 这道题目主要考查了栈的特性&#xff1a; 题目的意思主要是要做到3点匹配&#xff1a;类型、顺序、数量。 题目给的例子是比较…...

Java性能分析中常用命令和工具

当涉及到 Java 性能分析时&#xff0c;有一系列强大的命令和工具可以帮助开发人员分析应用程序的性能瓶颈、内存使用情况和线程问题。以下是一些常用的 Java 性能分析命令和工具&#xff0c;以及它们的详细说明和示例。 以下是一些常用的性能分析命令和工具汇总&#xff1a; …...

JVM性能分析-jstat工具观察gc频率

jstat jstat是java自带的工具&#xff0c;在bin目录下 用法 语法&#xff1a;jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]] [kqkyyj-2 bin]$ jstat -help Usage: jstat -help|-optionsjstat -<option> [-t] [-h&l…...

mysql 查询报错 1267 - Illegal mix of collations

mysql 查询报错 1267 - Illegal mix of collations 详细报错: 1267 - Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT) and (utf8mb4_unicode_ci,IMPLICIT) for 主要的原因其实就是两张表的字符集不一样改一下就行了。 注: 改了表还是报错的话,那就是表内的字段没有…...

【ARM】Day6

cotex-A7核UART总线实验 1. 键盘输入一个字符‘a’&#xff0c;串口工具显示‘b’ 2. 键盘输入一个字符串"nihao"&#xff0c;串口工具显示“nihao” uart.h #ifndef __UART4_H__ #define __UART4_H__#include "stm32mp1xx_rcc.h" #include "stm3…...

深入理解Flink Mailbox线程模型

文章目录 整体设计processMail1.Checkpoint Tigger2.ProcessingTime Timer Trigger processInput兼容SourceStreamTask 整体设计 Mailbox线程模型通过引入阻塞队列配合一个Mailbox线程的方式&#xff0c;可以轻松修改StreamTask内部状态的修改。Checkpoint、ProcessingTime Ti…...

Docker搭建LNMP运行Wordpress平台

一、项目1.1 项目环境1.2 服务器环境1.3 任务需求 二、Linux 系统基础镜像三、Nginx1、建立工作目录2、编写 Dockerfile 脚本3、准备 nginx.conf 配置文件4、生成镜像5、创建自定义网络6、启动镜像容器7、验证 nginx 四、Mysql1、建立工作目录2、编写 Dockerfile3、准备 my.cnf…...

10个常见渐变交互效果

1、透明度渐变背景交互 <div class"fade-background"></div> Copy .fade-background {width: 200px;height: 200px;background: linear-gradient(to bottom, rgba(255, 0, 0, 0), rgba(255, 0, 0, 1));transition: background 0.5s ease; }.fade-backgro…...

[线程/C]基础

文章目录 1. 线程介绍2. 创建线程2.1 线程函数2.2 创建线程 3. 线程退出4. 线程回收4.1 线程函数4.2 回收子线程数据4.2.1 使用子线程栈4.2.2 使用全局变量4.2.3 使用主线程栈 5. 线程分离6. 其他线程函数6.1 线程取消6.2 线程ID的比较 1. 线程介绍 线程是轻量级的进程&#x…...

Spring Clould 负载均衡 - Ribbon

视频地址&#xff1a;微服务&#xff08;SpringCloudRabbitMQDockerRedis搜索分布式&#xff09; Ribbon-负载均衡原理&#xff08;P14&#xff09; 具体实现时通过LoaBalanced注解实现&#xff0c;表示RestTemplate要被Ribbon拦截处理 orderservice调用user时候&#xff0c…...

活用DNS技术实现相同IP的不同端口映射不同域名

WindowsDNS基本配置 在内网的 Windows 服务器环境中&#xff0c;你可以通过配置 DNS 服务和 Web 服务器来实现所需的域名解析和端口转发。如下是一些基本的步骤来实现配置&#xff1a; 1&#xff0c;配置 Windows DNS 服务 在你的 Windows 服务器上配置 DNS 服务&#xff0c…...

AutoHotkey:定时删除目录下指定分钟以前的文件,带UI界面

删除指定目录下&#xff0c;所有在某个指定分钟以前的文件&#xff0c;可以用来清理经常生成很多文件的目录&#xff0c;但又需要保留最新的一部分文件 支持拖放目录到界面 能够记忆设置&#xff0c;下次启动后不用重新设置&#xff0c;可以直接开始 应用场景比如&#xff1a…...

一文学会sklearn中的交叉验证的方法

前言 在机器学习中&#xff0c;我们经常需要评估模型的性能。而为了准确评估模型的性能&#xff0c;我们需要使用一种有效的评估方法。五折交叉验证&#xff08;5-fold cross-validation&#xff09;就是其中一种常用的模型评估方法&#xff0c;用于评估机器学习模型的性能和泛…...

【MySQL面试题(66道)】

文章目录 MySQL面试题(66道)基础1.什么是内连接、外连接、交叉连接、笛卡尔积呢&#xff1f;2.那 MySQL 的内连接、左连接、右连接有有什么区别&#xff1f;3.说一下数据库的三大范式&#xff1f;4.varchar 与 char 的区别&#xff1f;5.blob 和 text 有什么区别&#xff1f;6.…...

CSSCI、北核期刊投稿指南(2023年更新)

该数据为经管类的期刊投稿指南&#xff0c;包含发表难度&#xff0c;文章数量&#xff0c;影响因子&#xff0c;用户评价等指标。共5份文件&#xff0c;分别为国内所有期刊信息库、投稿指南&#xff08;CSSCI版本、CSSCI扩展版本、北大核刊版本、建议期刊版本&#xff09; 一、…...

构建 NodeJS 影院微服务并使用 docker 部署它(02/4)

一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 图片取自网络 — 封面由我制作 这是✌️“构建 NodeJS 影院微服务”系列的第二篇文章。 二、对第一部分的…...

HTML <style> 标签

实例 <html> <head> <style type="text/css"> h1 {color:red} p {color:blue} </style> </head><body> <h1>Header 1</h1> <p>A paragraph.</p> </body> </html>定义和用法 <style>…...

设计模式——迪米特法则

文章目录 基本介绍应用实例应用实例改进迪米特法则注意事项和细节 基本介绍 一个对象应该对其他对象保持最少的了解类与类关系越密切&#xff0c;耦合度越大迪米特法则(Demeter Principle)又叫最少知道原则&#xff0c;即一个类对自己依赖的类知道的越少越好。也就是说&#x…...

区块链基本概念与当前生态简介

区块链是一种去中心化的分布式账本技术&#xff0c;它通过将数据按照时间顺序链接成区块&#xff0c;并使用密码学算法确保数据的安全性和完整性。每个区块包含一定数量的交易记录&#xff0c;而且每个区块都包含了前一个区块的哈希值&#xff0c;这样形成了一个不可篡改的链式…...

【PostgreSQL】生态工具箱:从核心插件到企业级扩展的实战指南

1. PostgreSQL生态工具箱全景图 第一次接触PostgreSQL时&#xff0c;很多人会惊讶于它丰富的扩展生态。就像一位老木匠的工具箱&#xff0c;PostgreSQL提供了从螺丝刀到电锯的全套工具。我在实际项目中最深刻的体会是&#xff1a;选对工具比盲目编码更重要。比如曾经有个项目需…...

IT6500电源蜂鸣器太吵?教你用Python远程静音并实现电压步进扫描

IT6500电源蜂鸣器静音与电压步进扫描的Python实战指南 深夜的实验室里&#xff0c;IT6500电源的蜂鸣器突然响起&#xff0c;刺耳的"哔哔"声打破了宁静&#xff0c;这种场景对于电子工程师来说再熟悉不过。本文将带你用Python彻底解决这个恼人的问题&#xff0c;同时实…...

Cogito-v1-preview-llama-3B效果展示:STEM题目分步推导+代码生成真实截图

Cogito-v1-preview-llama-3B效果展示&#xff1a;STEM题目分步推导代码生成真实截图 1. 模型能力概览 Cogito v1 预览版是Deep Cogito推出的混合推理模型系列&#xff0c;在大多数标准基准测试中均超越了同等规模下最优的开源模型。这个3B参数的模型在编码、STEM题目解答、指…...

leOS2:基于看门狗定时器的轻量级嵌入式调度器

1. leOS2&#xff1a;基于看门狗定时器的轻量级嵌入式调度器 leOS2&#xff08;little embedded Operating System 2&#xff09;是一个专为资源受限的8位AVR微控制器设计的极简实时调度器。它不依赖于通用定时器&#xff08;如Timer0/Timer1&#xff09;&#xff0c;而是创造…...

易语言实现阶乘与组合数计算

是的&#xff0c;我听说过易语言&#xff0c;它是一款面向中文使用者的编程语言&#xff0c;以其直观的中文语法和图形化界面开发能力而著称。 一、 数学概念解析 在深入编程实现前&#xff0c;我们先明确两个基础的数学概念。 1. 阶乘 阶乘 是所有小于及等于该数的正整数的…...

ApiPost实战指南:从接口创建到自动化测试的全流程解析

1. 从零开始创建你的第一个API接口 作为一个常年和API打交道的开发者&#xff0c;我深知新手第一次接触接口工具时的迷茫。ApiPost作为一款国产的API开发工具&#xff0c;用起来确实比Postman更顺手&#xff0c;特别是对中文用户特别友好。下面我就带你一步步创建第一个接口&am…...

COMSOL中固态锂离子电池的电-热-力耦合仿真:考虑扩散诱导应力、热应力及外部挤压应力的影响

COMSOL 固态锂离子电池仿真 固态锂离子电池电-热-力耦合仿真&#xff0c;考虑了扩散诱导应力&#xff0c;热应力以及外部挤压应力。固态电池鼓包变形的时候&#xff0c;工程师老张盯着屏幕上的应力云图直挠头。这玩意儿明明充满电就膨胀&#xff0c;放完电又缩回去&#xff0c;…...

XML Notepad:免费高效的XML编辑器终极指南

XML Notepad&#xff1a;免费高效的XML编辑器终极指南 【免费下载链接】XmlNotepad XML Notepad provides a simple intuitive User Interface for browsing and editing XML documents. 项目地址: https://gitcode.com/gh_mirrors/xm/XmlNotepad XML Notepad是一款由微…...

小型电动助力播种机【设计说明书+CAD图纸+solidworks三维+STEP+IGS】

小型电动助力播种机是针对传统播种作业效率低、劳动强度大的问题设计的农业机械装置&#xff0c;其核心作用在于通过电动助力系统优化播种流程&#xff0c;实现均匀播种与精准控制。该装置采用模块化设计理念&#xff0c;将动力传输、播种控制与行走机构集成于一体&#xff0c;…...

罚到肉疼!2026“两个细则”大考:你的风电场还在用“注定不准”的方法做预测吗?

当95%置信概率成为国家标准&#xff0c;单点预测的时代彻底终结2026年的春天&#xff0c;对于新能源发电企业而言&#xff0c;比以往任何时候都要“寒冷”。山东、四川等地新版“两个细则”正式施行&#xff0c;国家发改委“136号文”深入落地&#xff0c;新能源全面进入电力市…...