UART qt到微控制器,无法正确发送数据

UART qt to microcontroller, cannot send data properly

本文关键字:数据 qt 控制器 UART      更新时间:2023-10-16

我在许多不同的微控制器上多次遇到同样的问题。今天我想最终解决这个问题。

问题:

我正在尝试将数据从我的Qt UI发送到我的mycrocontroller。现在我可以发送它了,我的mc收到了我的数据(100%肯定)。每次我向mc发送数据时,led都会闪烁。但是有时我的led会闪烁,有时却不会。当我只发送"D"时,我可以看到我的led闪烁,这是没有问题的。但当我发送"Hello world D\n"时,led不会闪烁。

为什么?请

我的Qt代码:

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{  
   //SETS up my serial port
            serialPort = new QSerialPort(this);
            serialPort->setPortName("COM13");
            serialPort->setBaudRate(QSerialPort::Baud115200);
            if (!serialPort->open(QIODevice::ReadWrite))
            {
             qDebug("some error when openingn");
            }
}
void Widget::on_pushButton_clicked()
{
    if(ui->radioButton->isChecked()==true)
    {
       serialPort->write("Hello world Dn"); //doesn't work fine
    }
    else if(ui->radioButton_3->isChecked()==true)
    {
        serialPort->write(" Dn"); //works fine
    }
}

我的微控制器代码:

void blinkLed()
{
    volatile uint32_t ui32Loop;
    SYSCTL_RCGCGPIO_R = SYSCTL_RCGCGPIO_R12;
    ui32Loop = SYSCTL_RCGCGPIO_R;
    GPIO_PORTN_DIR_R = 0x01;
    GPIO_PORTN_DEN_R = 0x01;
    while(1)
    {
        GPIO_PORTN_DATA_R |= 0x01;
        for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++)
        {
        }
        GPIO_PORTN_DATA_R &= ~(0x01);
        for(ui32Loop = 0; ui32Loop < 200000; ui32Loop++)
        {
        }
    }
}

void
UARTIntHandler(void)
{

    int j=0;
    int ulStatus=0;

    for(j=0;j<20;j++)
    {
        receivedDataQt[j] = UARTCharGet(UART0_BASE);
        if(receivedDataQt[j]=='D')
        {
            gotDataQt=1; //this is a global variable
            break;
        }
    }
    ulStatus = UARTIntStatus(UART0_BASE, true);
    UARTIntClear(UART0_BASE, ulStatus);
    initUART(); //re setup UART after interrupt
}
int main(void)
{
    while(1)
    {
        initUART();
        setUARTinterrupt();
        setupI2c(); 
        setupSensor();
        while(1)
        {
                // communicate with sensor
            if(gotDataQt==1) //when it returns from the interrupt this (global) bit  is set
            {
                blinkLed(); //makes my led 
                gotDataQt=0;
            }

        }
    }
}

问题似乎是您试图读取中断处理程序中的多个字符,而没有检查是否有更多字符可用。一般的方法是更像下面这样的代码,每次中断读取一个字符:

#define BUF_SIZE 20
volatile int j;
void UARTIntHandler(void)
{
    int ulStatus=0;
    ulStatus = UARTIntStatus(UART0_BASE, true);
    while(UARTCharsAvail(UART0_BASE))
    {
        char c = UARTCharGet(UART0_BASE);
        if (j < BUF_SIZE)
            receivedDataQt[j++] = c;
        if (c == 'D')
            gotDataQt=1; //this is a global variable
    }
    UARTIntClear(UART0_BASE, ulStatus);
}
int main(void)
{
    while(1)
    {
        initUART();
        setUARTinterrupt();
        setupI2c(); 
        setupSensor();
        j = 0;
        while(1)
        {
            if(gotDataQt==1) //when it returns from the interrupt this (global) bit  is set
            {
                blinkLed(); //makes my led 
                j = 0;
                gotDataQt=0;
            }
        }
    }
}

以上内容未经测试,我不熟悉您使用的微控制器,因此它可能需要一些工作来适应您的应用程序,但需要注意的几点是:

  • 检查是否有更多的字符可用,不要试图在每次中断时重新初始化UART,这应该不是必要的
  • 您可能不想以这种方式中断,因为它会跳过为下次设置中断的代码
  • 在中断中可以更改jgotDataQt时,将它们声明为易失性
  • 看看volatile关键字和原子操作。如果您使用的是8位微控制器和8位数据类型,通常操作将是原子操作,但假设它们是8位微处理器上的16位,则您可能希望在读取/写入主代码时禁用中断,以防止读取和写入中断发生时仅写入一部分数据的内容

一般来说,最好尽量减少中断例程的工作量,避免其中的任何延迟和循环,因此在主代码中使用标志和执行LED闪烁等的通用方法是很好的。