问题描述
今天,我陷入了一个非常令人困惑的问题。我通过UART将数据从PC发送到MCU,反之亦然。 我正在使用中断。 我有两个不同版本的代码。它们看起来几乎相同,但是其中一个不能正常工作-数据未发送回PC(第一个版本正常)。我不知道为什么,但是我想知道,以便将来更快地发现这种问题。
完整版代码-> https://gitlab.com/bielu000/stm32-libopencm3 分支机构:
- uart_not_working_version
- uart_working_version
重要文件位于:src / app / src。
我可以将其保留为工作版本,但我想了解该问题的性质,以便将来避免此类问题。
这两个版本之间的主要区别:
- 版本1->我经常调用(从主循环中的)函数server_check(),该函数检查MCU是否已接收到64kb,如果是,则将这些字节复制到write_buffer,然后发送回pc
- 版本2->我不使用功能server_check,因为它的功能已移至server_run(从main调用一次),然后使用其自己的循环永不停止,并且在该循环中几乎完全相同类似于版本1中的server_check函数中的代码。
MCU:STM32F103 我正在使用g ++ 8.2
Compliation标志:
set(COMPILER_CXX_FLAGS“ -fno-use-cxa-atexit -O1 -fno-exceptions -g”)
set(COMPILER_FLAGS“ -fdata-sections -ffunction-sections -DNDEBUG -Wall -Werror -g“)
版本1。 //main.cpp
int main()
{
//init clock etc
server_init();
server_run();
while(true)
{
server_check();
}
}
// server.cpp
extern "C" {
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/cm3/nvic.h>
}
#include <server.hpp>
#include <stdint.h>
#include <ring_buffer.hpp>
#include <target.h>
static uint8_t w_buffer[1024]; // write buffer
static uint8_t r_buffer[1024]; // read buffer
utils::containers::RingBuffer write_rb{w_buffer,sizeof(w_buffer)};
utils::containers::RingBuffer read_rb{r_buffer,sizeof(r_buffer)};
static void sendData()
{
if (write_rb.capacity() != 0)
{
usart_send(USART1,write_rb.read());
usart_enable_tx_interrupt(USART1);
}
else
{
usart_disable_tx_interrupt(USART1);
}
}
static void readData()
{
auto data = usart_recv(USART1);
read_rb.write(static_cast<uint8_t>(data));
// usart_enable_rx_interrupt(USART1);
}
void server_init()
{
//RCC
rcc_periph_clock_enable(RCC_USART1);
//GPIO
gpio_set_mode(GPIO_BANK_USART1_TX,GPIO_MODE_OUTPUT_50_MHZ,GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,GPIO_USART1_TX);
gpio_set_mode(GPIO_BANK_USART1_RX,GPIO_MODE_INPUT,GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN,GPIO_USART1_RX);
//USART
usart_set_mode(USART1,USART_MODE_TX_RX);
usart_set_baudrate(USART1,9600);
usart_set_parity(USART1,USART_PARITY_NONE);
usart_set_databits(USART1,8);
usart_set_stopbits(USART1,1);
usart_set_flow_control(USART1,USART_FLOWCONTROL_NONE);
usart_enable_rx_interrupt(USART1);
//ISR
nvic_enable_irq(NVIC_USART1_IRQ);
//Enable
usart_enable(USART1);
}
void server_run()
{
}
void server_check()
{
if (read_rb.capacity() == 64)
{
while (read_rb.capacity() != 0)
{
write_rb.write(read_rb.read());
}
sendData();
}
}
void usart1_isr()
{
if (usart_get_flag(USART1,USART_FLAG_TXE) != 0)
{
sendData();
}
if (usart_get_flag(USART1,USART_FLAG_RXNE) != 0) // when data is ready to read
{
readData();
}
}
版本2
main.cpp
int main()
{
//init clock etc
server_init();
server_run();
while(true)
{
}
}
server.cpp
extern "C" {
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/cm3/nvic.h>
}
#include <server.hpp>
#include <stdint.h>
#include <ring_buffer.hpp>
#include <Os.hpp>
#include <target.h>
/**
*
* | MSG_TYPE | |
*
*/
static uint8_t w_buffer[1024]; // write buffer
static uint8_t r_buffer[1024]; // read buffer
utils::containers::RingBuffer write_rb{w_buffer,USART_FLOWCONTROL_NONE);
usart_enable_rx_interrupt(USART1);
//ISR
nvic_enable_irq(NVIC_USART1_IRQ);
//Enable
usart_enable(USART1);
}
void server_run()
{
while(true)
{
if (read_rb.capacity() == 64)
{
while (read_rb.capacity() != 0)
{
write_rb.write(read_rb.read());
}
sendData();
}
}
}
void server_check()
{
}
void usart1_isr()
{
if (usart_get_flag(USART1,USART_FLAG_RXNE) != 0) // when data is ready to read
{
readData();
}
}
解决方法
您应该使用第2版代码尝试以下提示:
- 从
while(true)
函数中删除main()
- 将
==64
替换为>=64
以确保即使跳过一个值且容量变为65,缓冲区也已处理:if (read_rb.capacity() >= 64)
此外,应避免在main函数之外的其他函数中放入无限循环。