将volatile变量作为函数中的常量参数传递

Aru*_*yan 5 c embedded arm

我正在为Cortex-M0 MC开发和嵌入代码,其中我声明了一个变量,volatile char TOS_Mins_Char[3]; 以便在ISR期间存储一些值,这些值会定期更改.我想使用atoi()函数将这些字符转换为整数,但atoi()将其参数类型作为指向常量字符串的指针:int atoi(const char *);除非我volatile在变量声明中避免使用关键字,否则这会给出错误.(在其他std函数中也面临类似的情况)

  1. 除了编写用户定义的函数之外,还有其他解决方案吗?
  2. 如果我使用const char TOS_Mins_Char[3];,它会有问题吗?
  3. 是否必须使用volatile关键字,与ARM MC相比,它的用途是什么?

chq*_*lie 5

volatile必须使用关键字来告诉编译器为每次访问从内存中重新加载字符。

如果您知道在转换过程中不会修改数组,则可以使用强制转换来消除警告:

int value = atoi((const char*)TOS_Mins_Char);
Run Code Online (Sandbox Code Playgroud)

请注意,atoi()如果中断例程在转换过程中修改了数组,则返回的值可能完全是假的。您可以通过禁用访问数组的中断来防止这种情况。为了在禁用中断的情况下最小化处理持续时间,您可能希望以这种方式将数组复制到本地数组:

char buf[sizeof TOS_Mins_Char];
CLI;   // whatever macro use to disable interrupts
memcpy(buf, TOS_Mins_Char, sizeof TOS_Mins_Char);
STI;   // enable interrupts
int value = atoi(buf);
Run Code Online (Sandbox Code Playgroud)

这种方法的问题是中断禁用/启用机制的不可重入性:如果在输入代码时中断已经被禁用,它们将在离开时启用,这可能不是故意的,并且可能是调用代码中错误的原因。

另一个快速而肮脏的技巧可用于降低中断冲突的可能性:

int value, last = atoi((const char*)TOS_Mins_Char);
while ((value = atoi((const char*)TOS_Mins_Char)) != last) {
    last = value;
}
Run Code Online (Sandbox Code Playgroud)

如果在转换期间 ISR 修改了缓冲区,则下一次转换将产生不同的结果。下一次转换也有可能被 ISR 中断,但在非生命攸关的系统中,您可能希望忽略这种可能性。

  • 最后一个想法是有问题的,因为空字符可能会消失(字符串在 `atoi()` 中间变短)。`memcpy()` 的想法很好,但建议改进 `SAVE_ENABLE(); CLI(); memcpy(); RESTORE_ENABLE();` 来处理重入。 (3认同)