我正在做一个从电子计数器读取串行数据的库。根据您的合同,计数器可以传输多达105个不同的标签。因为这个库可以在轻量级和不强大的嵌入式系统(通常是arduino或esp8266)上,我试图将内存使用减少到最低限度。
为了读取每个标记,我的库有一个长度等于最大标记值长度的缓冲区(范围从2字节到94字节)。我希望我的库能够自动将缓冲区大小设置为正确的值,知道用户能够在其主文件中使用#define指令指示他想要的标记。
main.cpp
#define BASE
#define HCHP
#define OPTARIF
#include "LinkyTIC.h"
#include <SoftwareSerial.h>
SoftwareSerial LinkySerial(13, 15);
LinkyTIC linky(LinkySerial);
void setup() {
}
void loop() {
if(linky.read()){
int base = linky.GetBASE();
int hchp = linky.GetHCHP();
Serial.println(base);
Serial.println(hchp);
}
}
What I tried:
在我的头文件中,我使用了一个#ifdef链来保持最大长度,但是我得到了错误的变量"max_length"不能用作常量。我试图将值转换为常量,但它也不起作用。
header.h
uint8_t max_length = 8;
#ifdef ADCO
uint8_t max_length = max_length > 12 ? max_length : 12;
#endif
#ifdef OPTARIF
uint8_t max_length = max_length > 4 ? max_length : 4;
#endif
#ifdef ISOUSC
uint8_t max_length = max_length > 2 ? max_length : 2;
#endif
#ifdef BASE
uint8_t max_length = max_length > 9 ? max_length : 9;
#endif
...
class LinkyTIC {
public:
// unrelated stuff
private:
// unrelated stuff
char _buffer_tag[8]; // buffer for the tag name
>>>> char _buffer_date[max_length]; // buffer for the (optional) tag date. Must be the same length as value because we can't know in advance if it s going to be a date or a value
^^^^^^^^^^ the value of variable "max_length" cannot be used as a constant
>>>> char _buffer_value[max_length]; // buffer for the tag value
^^^^^^^^^^ the value of variable "max_length" cannot be used as a constant
char _buffer_checksum[1]; // buffer for the tag checksum
char _checksum;
char* _buffers[4] = {_buffer_tag, _buffer_date, _buffer_value, _buffer_checksum};
uint8_t _buffer_reference_index;
uint8_t _buffer_index;
...
}
max_length的值因此可以在编译时知道,但是我无法找到一种方法来使用它的值来创建我的数组。
实现我想做的事情的最好方法是什么?因为flash也是一个问题,所以我宁愿避免使用std::vector.
有许多使用预处理器宏和#if
语句的选项,这取决于您的需求是什么,您没有明确说明。一个例子是:
#define MaximumLength 8
#if defined ADCO
#if MaximumLength > 12
#undef MaximumLength
#define MaximumLength 12
#endif
#endif
#if defined OPTARIF
#if MaximumLength > 4
#undef MaximumLength
#define MaximumLength 4
#endif
#endif
#if defined ISOUSC
#if MaximumLength > 2
#undef MaximumLength
#define MaximumLength 2
#endif
#endif
#if defined BASE
#if MaximumLength > 9
#undef MaximumLength
#define MaximumLength 9
#endif
#endif
uint8_t max_length = MaximumLength; // If this variable is still desired.
…
char _buffer_date[MaximumLength];
首先,您需要定义变量const
或consexpr
。因为你的代码已经有错误,你不能用相同的名字重新定义变量,我不确定你打算做什么,但像这样的事情应该工作:
#include <cstdint>
#include <iostream>
#include <algorithm>
// Uncomment line(s) below to check behavior
//#define ADCO
//#define OPTARIF
//#define ISOUSC
//#define BASE
const uint8_t def_max_length = 8;
#ifdef ADCO
const uint8_t max_length = std::max<uint8_t>(def_max_length, 12);
#elif defined(OPTARIF)
const uint8_t max_length = std::max<uint8_t>(def_max_length, 4);
#elif defined(ISOUSC)
const uint8_t max_length = std::max<uint8_t>(def_max_length, 2);
#elif defined(BASE)
const uint8_t max_length = std::max<uint8_t>(def_max_length, 9);
#else
const uint8_t max_length = def_max_length;
#endif
char buffer[max_length];
int main()
{
std::cout << std::size(buffer) << std::endl;
}
如果您需要独立检查所有定义,那么您可以为每个定义定义一个变量,例如:
#ifdef ADCO
const uint8_t max_length_adco = 12;
#else
const uint8_t max_length_adco = 0;
#ednif
然后得到所有变量的最大值:
const uint8_t max_length = std::max({def_max_length, max_length_adco, max_length_optarif, max_length_isousc, max_length_base});