在 for 循环中初始化的变量包含一个值,不会递增
Posted
技术标签:
【中文标题】在 for 循环中初始化的变量包含一个值,不会递增【英文标题】:Variable initialized in a for-loop contains a value, won't increment 【发布时间】:2021-05-05 20:04:13 【问题描述】:我正在为 STM32 微控制器开发一个功能,该功能通过 uart 端口发送给定长度的字符串。为了处理 uart 通信,我创建了一个 Serial 类,它有一个在中断处理程序中弹出和传输的传输和接收缓冲区。我目前正在处理的函数实际上是我之前编写的有效函数的重载。下面是工作函数:
void Serial::sendString(char* str)
// Writes a string to txBuffer. If Transmit interrupts are enabled, and
// the Data register is empty, the txBuffer will be popped into the DR to
// prime the interrupts.
__HAL_UART_DISABLE_IT(uart, UART_IT_TXE); // Keeps our spaghetti straightened out...
while (*str != '\0') // While char is not a null terminator...
txBuffer->push(*str); // Push first char into queue as we know it is valid
str++; // Pointer goes to next char in string
uint32_t isrflags = READ_REG(uart->Instance->SR); // Reads the flags and control register
//uint32_t cr1its = READ_REG(uart->Instance->CR1); // Into variables
// If the DR is empty and Transmission interrupts are disabled...
if ((isrflags & USART_SR_TXE) != RESET)
uart->Instance->DR = txBuffer->pop(); // Reenable interrupts and prime the DR
__HAL_UART_ENABLE_IT(uart, UART_IT_TXE); // Alright, time to cook the pasta
重载是我遇到问题的功能。出于某种原因,调试器显示变量“i”以值“14”初始化,并且在使用调试器单步执行时不会递增。事实上,调试器根本不允许我进入 for 循环。这是重载:
void Serial::sendString(char* str, unsigned int len)
// Writes a string to txBuffer. If Transmit interrupts are enabled, and
// the Data register is empty, the txBuffer will be popped into the DR to
// prime the interrupts.
// Rather than being terminated by a null character, this method instead
// sends each char in an array of a specified length. Note that this overload
// MUST be used in any situation that a null terminator might appear in a char
// array!
__HAL_UART_DISABLE_IT(uart, UART_IT_TXE); // Keeps our spaghetti straightened out...
for (unsigned int i = 0; i < len; i++) // While char is not a null terminator...
txBuffer->push(str[i]); // Push first char into queue as we know it is valid
//str++; // Pointer goes to next char in string
uint32_t isrflags = READ_REG(uart->Instance->SR); // Reads the flags and control register
// uint32_t cr1its = READ_REG(uart->Instance->CR1); // Into variables
// If the DR is empty...
if ((isrflags & USART_SR_TXE) != RESET)
uart->Instance->DR = txBuffer->pop();
__HAL_UART_ENABLE_IT(uart, UART_IT_TXE); // Alright, time to cook the pasta
这些函数在 main 的终端 while 循环中调用。调试时,问题立即发生;我根本无法承受超载。我的代码似乎只是在这个位置遇到了死机。
我之前已经能够成功运行过载。仅当我试图解决函数中的另一个错误时,该错误才出现,即字符串中的第一个字符仅在一半时间内被传输。我设置了一个断点并开始调试,现在它根本不起作用....
【问题讨论】:
更新:我重新启动了我的 IDE,将我的板换成了另一个,刷新了代码,它神奇地开始工作。我对固件工程比较陌生,有人能解释一下导致这些奇怪错误的原因吗?它们似乎很小,而且具体是硬件问题..... 顺便说一句,您的代码意义不大。中断处理必须看起来完全不同。它是偶然“工作”的,当你编写更多代码时它会停止工作。 您能详细说明一下吗?我正在使用的电路板有一个中断,当数据寄存器在传输后被清空时触发。在我的 ISR 中,我将 txBuffer 中的内容弹出到 DR 中,以便传输字节。 您只是以错误的方式进行操作。查看任何 STM32 体面的 IT UART 代码并找出差异。评论解释太多了。 你好,我研究了一些STM32中断传输代码。在 send 方法中将数据放入 DR 是否不当?感谢您的反馈 【参考方案1】:听起来编译器已经优化掉了你的循环控制变量。
如果您启用了高级别的优化,则可以展开循环,或者如果您从定义它的同一文件中调用该函数,则可以内联它以消除循环控制变量。
您实际上并没有描述您要调试的问题是什么。与其期望调试体验完美,不如尝试解决您遇到的问题,尽管我一直是 14 岁!
仅查看您发布的代码,我看不出有什么大问题。当然,您未显示的代码中可能存在错误。
我非常不同意这段代码根本上是垃圾的无益评论。打开和关闭中断以访问共享数据是老式且低效的,但操作起来也很简单,可能足以满足您的目的。
在此函数中将第一个字节写入 UART 确实节省了一次中断的成本,但如果您正在写入一个 20 字节的字符串,您真的关心需要 20 次还是 19 次中断吗?一个好的设计原则是,只有当代码为您带来一些您不想没有的东西时,您才应该使代码变得更复杂。
【讨论】:
调试器不优化代码。至于编译器,它不会优化掉包含对硬件外围寄存器的读/写的代码。如果发生这种情况,那只能是因为整个寄存器定义代码乱七八糟,听起来有些牵强。 感谢您的反馈!问题是我试图解决变量卡住的问题,当我的代码神奇地停止工作时,我正在努力将 Dynamixel 的协议 2.0 实施到一个更大的项目中。我不确定优化是否有问题,因为我在调试和发布版本中遇到问题...当我换掉另一块板并重新连接我的 ST-Link 时问题消失了...到目前为止我实际上还没有能够重现该错误,但如果我再次遇到该问题,我将更新此线程...以上是关于在 for 循环中初始化的变量包含一个值,不会递增的主要内容,如果未能解决你的问题,请参考以下文章