簡體   English   中英

如何使用GPIO引腳通過Qt進行串行流控制?

[英]How to use a GPIO pin, for serial flow control with Qt?

目標

在我的Qt應用程序中,我需要控制GPIO引腳,具體取決於通過串行總線發送的數據。 因此,只要傳輸數據,就需要將其設置為HIGH,傳輸結束后立即將其設置為LOW。 將其視為串行通信流控制引腳,當設置為1時,它將啟用發送,而設置為0時,則將允許接收數據。 整個系統是半雙工的,並且以主從方式通信。

問題

我設法接近解決方案,即將任何傳輸之前將其設置為HIGH,根據波特率引入了一些恆定的延遲(我使用了QThread:usleep() ),然后再次將其設置為低,但是我變得隨機了。當我用示波器觀察脈沖時,脈沖“伸展”(保持高電平的時間長於應有的時間)。

嘗試的解決方案

好吧,似乎有些“魔術”正在發生,這在我手動定義的延遲的基礎上增加了一些額外的延遲。 為了消除這種可能性,我使用了bytesWritten()信號,因此在將實際數據寫入端口后,可以觸發setPinLow()插槽。 所以我的代碼現在看起來像這樣:

classTTY::classTTY(/*someStuff*/) : port(/*some other stuff*/)
{
    s_port = new QSerialPort();
    connect(s_port, SIGNAL(bytesWritten(qint64)), this, SLOT(setPinLow()));

    if(GPIOPin->open(QFile::ReadWrite | QFile::Truncate | QFile::Text | QFile::Unbuffered)) {
        qDebug() << "GPIO pin ready to switch.";
    } else {
        qDebug() << "Failed to access GPIO pin";
    }

bool classTTY::sendData(data, replyLength)
{
    directionPinEnable(true);

    if(m_port->isOpen()) {
        s_expectedReplyLength = replyLength;
        s_receivedData.clear();

        s_port->flush();
        s_port->write(data);

        return true;
    }

return false;
}

void classTTY::setPinLow()
{
    gpioPinEnable(false);
}

void classTTY::gpioPinEnable(bool enable){

    if(enable == true){
        GPIOPin->write("1");
    } else if (enable == false) {
        GPIOPin->write("0");
    }
}

實施該引腳后,該引腳開始發出非常短的脈沖,更像是“尖峰脈沖”,這意味着(我認為)現在只要Qt write()過程持續,它就會一直保持高電平,而不是在實際傳播時。數據持續。

問題

  1. 當我使用幼稚的QThread::usleep方法時,會導致脈寬延長的額外延遲是什么?
  2. 為什么信號插槽方法是事件驅動的,所以為什么不起作用?
  3. 通常,如何指示引腳在數據傳輸過程中僅變為活動狀態,然后再次下降為零,以便接收從設備的答復?
  1. 當我使用幼稚的QThread :: usleep方法時,會導致脈寬延長的額外延遲是什么?

Linux不是實時操作系統,線程睡眠會以至少指定的時間暫停進程。 在休眠期間,其他線程和進程可能會運行,並且可能不會在比您的休眠周期更長的時間內產生處理器,或者可能根本不產生並消耗它們分配給操作系統的整個時間片。 除此之外,內核驅動程序中斷處理程序將始終搶占用戶級進程。 Linus有一個用於實時調度的構建選項,但是保證仍然不夠可靠,以至於真正的實時操作系統和延遲通常會更糟。

還要注意,不僅線程的掛起時間比睡眠時間長,而且傳輸的擴展量可能超過波特率上的位數-內核驅動程序可能會被其他驅動程序搶占並引入字符間的間隙您無法控制。

  1. 為什么信號插槽方法是事件驅動的,所以為什么不起作用?

QSerialPort::waitForBytesWritten()的文檔指出:

該函數將阻塞,直到至少一個字節已寫入串行端口並且已發出bytesWritten()信號為止。

因此很明顯,其語義是“ 已寫入一些數據 ”而不是“ 已寫入所有數據 ”。 每當寫入一個字節時,它都會返回,然后再次調用,如果繼續寫入字節,它可能會立即返回(因為QSerialPort已緩沖並且將獨立於應用程序寫入數據)。

  1. 通常,如何指示引腳在數據傳輸過程中僅變為活動狀態,然后再次下降為零,以便接收從設備的答復?

不幸的是,Qt並不是答案。 此行為需要在串行端口內核驅動程序中實現,或者至少在Qt的較低級別實現。 Qt QSerialPort抽象不能為您提供控制或深入了解所需的“在線”實際發生情況的級別。 從硬件上來說,它有些距離了-這是有充分理由的。

但是,有一個簡單的解決方案-不用擔心! 似乎完全沒有必要。 它是主從通信,因此數據本身流控制。 從屬設備直到講話后才開始說話,而主控器必須等待並等待答復。 為什么奴隸除了說話所暗示的以外還需要其他任何說話的權限?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM