Embedded 更改函数调用的位置会中断uart上的通信
今天我遇到了一个非常令人困惑的问题。我通过UART将数据从pc发送到MCU,反之亦然。 我在使用中断。 我有两种不同版本的代码。它们看起来几乎一样,但其中一个工作不正常-数据没有发送回pc(第一个版本工作正常)。我不知道为什么,但我想知道,为了在将来更快地发现此类问题 代码的完整版本-> 分支机构:Embedded 更改函数调用的位置会中断uart上的通信,embedded,stm32,microcontroller,Embedded,Stm32,Microcontroller,今天我遇到了一个非常令人困惑的问题。我通过UART将数据从pc发送到MCU,反之亦然。 我在使用中断。 我有两种不同版本的代码。它们看起来几乎一样,但其中一个工作不正常-数据没有发送回pc(第一个版本工作正常)。我不知道为什么,但我想知道,为了在将来更快地发现此类问题 代码的完整版本-> 分支机构: uart\u不工作\u版本 uart\u工作版本 重要文件位于:src/app/src 我可以让它保持工作版本的状态,但我想了解问题的本质,以避免将来出现此类问题 这两个版本之间的关键区别:
- uart\u不工作\u版本
- uart\u工作版本
- 版本1->我一直在调用(主循环中的)函数server_check(),它检查MCU是否已经接收到64kb,如果已经接收到,那么这些字节将被复制到write_buffer,然后发送回pc
- 版本2->我不使用function server_check,因为它的功能被移动到server_run,它从main调用一次,然后使用它自己的循环永不停止,在这个循环中几乎有与版本1中function server_check相同的代码
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();
}
}
extern“C”{
#包括
#包括
#包括
#包括
}
#包括
#包括
#包括
#包括
静态uint8_t w_缓冲区[1024];//写缓冲区
静态uint8_t r_缓冲区[1024];//读取缓冲区
utils::containers::RingBuffer write_rb{w_buffer,sizeof(w_buffer)};
utils::containers::RingBuffer read_rb{r_buffer,sizeof(r_buffer)};
静态void sendData()
{
如果(写入容量()!=0)
{
usart_send(usart 1,write_rb.read());
usart_启用_发送_中断(USART1);
}
其他的
{
usart_禁用_发送_中断(USART1);
}
}
静态void readData()
{
自动数据=usart\U recv(USART1);
读写(静态转换(数据));
//usart_启用_接收_中断(USART1);
}
void server_init()
{
//碾压混凝土
rcc外围时钟启用(rcc USART1);
//GPIO
gpio_设置_模式(gpio_银行_USART1_发送,gpio_模式_输出_50_MHZ,
GPIO_CNF_输出_ALTFN_推拉,GPIO_USART1_TX);
gpio_设置_模式(gpio_银行_用户1_接收,gpio_模式_输入,
GPIO_CNF_输出_ALTFN_OPENDRAIN,GPIO_USART1_RX);
//乌萨特
usart_设置_模式(USART1、usart_模式_发送_接收);
usart\U set\U波特率(USART19600);
usart\U集合\U奇偶校验(USART1,usart\U奇偶校验\U无);
usart_集合_数据位(USART1,8);
usart\U set\U停止位(USART1,1);
usart\U设置\U流量控制(USART1,usart\U流量控制\U无);
usart_启用_接收_中断(USART1);
//ISR
nvic_启用_irq(nvic_USART1_irq);
//使能
usart_启用(USART1);
}
void server_run()
{
}
无效服务器检查()
{
如果(读取容量()==64)
{
while(read_rb.capacity()!=0)
{
write_rb.write(read_rb.read());
}
sendData();
}
}
无效usart1_isr()
{
如果(usart\U get\U标志(USART1,usart\U标志)!=0)
{
sendData();
}
如果(usart\U get\U flag(USART1,usart\U flag\U RXNE)!=0)//当数据准备好读取时
{
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, 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()
{
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_TXE) != 0)
{
sendData();
}
if (usart_get_flag(USART1, USART_FLAG_RXNE) != 0) // when data is ready to read
{
readData();
}
}
main.cpp
int main()
{
//初始化时钟等
server_init();
服务器运行();
while(true)
{
}
}
server.cpp
外部“C”{
#包括
#包括
#包括
#包括
}
#包括
#包括
#包括
#包括
#包括
/**
*
*|味精|U型||
*
*/
静态uint8_t w_缓冲区[1024];//写缓冲区
静态uint8_t r_缓冲区[1024];//读取缓冲区
utils::containers::RingBuffer write_rb{w_buffer,sizeof(w_buffer)};
utils::containers::RingBuffer read_rb{r_buffer,sizeof(r_buffer)};
静态void sendData()
{
如果(写入容量()!=0)
{
usart_send(usart 1,write_rb.read());
usart_启用_发送_中断(USART1);
}
其他的
{
usart_禁用_发送_中断(USART1);
}
}
静态void readData()
{
自动数据=usart\U recv(USART1);
读写(静态转换(数据));
//usart_启用_接收_中断(USART1);
}
void server_init()
{
//碾压混凝土
rcc外围时钟启用(rcc USART1);
//GPIO
gpio_设置_模式(gpio_银行_USART1_发送,gpio_模式_输出_50_MHZ,
GPIO_CNF_输出_ALTFN_推拉,GPIO_USART1_TX);
gpio_设置_模式(gpio_银行_用户1_接收,gpio_模式_输入,
GPIO_CNF_输出_ALTFN_OPENDRAIN,GPIO_USART1_RX);
//乌萨特
usart_设置_模式(USART1、usart_模式_发送_接收);
usart\U set\U波特率(USART19600);
usart\U集合\U奇偶校验(USART1,usart\U奇偶校验\U无);
usart_集合_数据位(USART1,8);
usart\U set\U停止位(USART1,1);
usart\U设置\U流量控制(USART1,usart\U流量控制\U无);
usart_启用_接收_中断(USART1);
//ISR
nvic_启用_irq(nvic_USART1_irq);
//使能
usart_启用(USART1);
}
void server_run()
{
while(true)
{
如果(读取容量()==64)
{
while(read_rb.capacity()!=0)
{
write_rb.write(read_rb.read());
}
sendData();
}
}
}
无效服务器检查()
{
}
无效usart1_isr()
{
如果(usart\U get\U标志(USART1,usart\U标志)!=0)
{
sendData();
}
如果(usart\U get\U flag(USART1,usart\U flag\U RXNE)!=0)//当数据准备好读取时
{
readData();
}
}
您应该在版本2代码中尝试以下技巧:
- 从
函数中删除main()
while(true)
- 将
替换为==64
,以确保即使跳过一个值且容量变为65,也会处理缓冲区:=64
if(read_rb.capacity()>=64)
此外,应避免在除main之外的其他函数中放入无限循环。您应尝试以下技巧