การเริ่มต้นการสื่อสารพอร์ตอนุกรม

ในขณะนี้เรากำลังพยายามสร้างอินเทอร์เฟซสำหรับการสื่อสารแบบอนุกรมเพื่อให้สามารถสื่อสารกับไมโครโปรเซสเซอร์ได้

จริงๆแล้ว - ทุกอย่างทำงานได้ดี เกือบ! เพื่อให้สามารถสื่อสารกับคอนโทรลเลอร์ของเราได้ เราจำเป็นต้องซิงค์กับคอนโทรลเลอร์นั้น ในการดำเนินการนี้ เราเขียนสตริง: "?0{SY}13!" และตัวควบคุมควรตอบกลับด้วย "!0{SY}F5?" เพื่อยอมรับคำขอซิงค์ ในการทำเช่นนี้ เราใช้ฟังก์ชัน writeData (ซึ่งได้ผล - เรารู้ว่าใช้ echo) และหลังจากนั้นเราใช้ readData เพื่ออ่านคำตอบ ปัญหาคือมันจะไม่อ่านอะไรเลยด้วยเหตุผลบางประการ แม้ว่าจะส่งกลับ 1 เพื่อความสำเร็จ แต่ตัวอักษรที่อ่านก็ยังเป็น " " อย่างต่อเนื่อง (ไม่มีเลย)

ตอนนี้ส่วนที่แปลกมาถึงแล้ว - ถ้าเราใช้โปรแกรมเทอร์มินัลภายนอกเพื่อเริ่มต้นพอร์ต (เช่น สีโป๊ว) แล้วปิดโปรแกรม ทุกอย่างก็ทำงานได้ดี ยอมรับคำขอซิงค์ คำตอบ (และเราสามารถอ่านได้) จากนั้นเราก็สามารถทำทุกอย่างที่เราต้องการได้ แต่ถ้าเราใช้โปรแกรมภายนอกเพื่อเริ่มต้นพอร์ต มันก็จะไม่ทำงาน

ตัวสร้างสำหรับการเริ่มต้นอินเทอร์เฟซมีลักษณะดังนี้:

SerialIF::SerialIF(int baud, int byteSize, int stopBits, char* parity, int debug)
{
    string coutport = getPort();    
    wstring wideport;               
    debug_ = debug;                 //Debuglevel

    sync = false;                   //sync starts with false

    error = false;                  //Error false as beginnging

    //this is just for converting to the right type
    for (int i = 0; i < coutport.length(); i++)
    {
        wideport += wchar_t(coutport[i]);  
    }
    const wchar_t* port = wideport.c_str();

    SerialIF::hserial = CreateFile(port,
        GENERIC_READ | GENERIC_WRITE,       
        0,
        0,
        OPEN_EXISTING,                      
        FILE_ATTRIBUTE_NORMAL,              
        0);
    if (hserial == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == ERROR_FILE_NOT_FOUND)
        {
            if (debug_ != LOW)
            {
                cout << "[-] Port " << coutport << "doesn't exist." << endl;  
            }
        }

        if (debug_ != LOW)
        {
            cout << "[-] Handle error - is there another terminal active?" << endl;
        }
        error = true;
    }

    DCB dcbParms = { 0 };
    dcbParms.DCBlength = sizeof(dcbParms);

    if (!GetCommState(hserial, &dcbParms))
    {
        if (debug_ != LOW)
        {
            cout << "[-] Couldn't get status from port " << coutport << endl;
        }
        error = true;  
    }

    if (!error)
    {
        setBaud(dcbParms, baud);
        setParity(dcbParms, parity);
        setByteSize(dcbParms, byteSize);
        setStopbits(dcbParms, stopBits);

        if (debug_ == HIGH)
        {
            cout << "[+] Serial port " << coutport << " has been activated. \nBaud-rate: " << baud << "\nParity: "
                << parity << "\nStop bits: " << stopBits << endl;
        }
    }
    else if (debug_ != LOW)
    {
        cout << "[-] Port not initialized" << endl;
    }
}

สิ่งนี้ควรจะได้ผล - ฉันไม่รู้จริงๆ ว่าทำไมถึงไม่ควร มันไม่ส่งคืนข้อผิดพลาด ฉันได้ลองค้นหาข้อผิดพลาดมากมายในช่วงสองสามวันที่ผ่านมา ฉันลองหมดเวลา ฉันลองวิธีอื่นในการสร้างมัน แต่ทุกอย่างก็กลายเป็นปัญหาเดียวกัน

เหตุใดจึงไม่เริ่มต้นพอร์ต

แก้ไข:

ผลลัพธ์เมื่อพยายามซิงค์: ไม่สามารถโพสต์รูปภาพได้เนื่องจากไม่มีชื่อเสียง แม้ว่าจะมีผลลัพธ์ดังนี้:

[+] เปิดใช้งานพอร์ตอนุกรม COM1 แล้ว อัตรารับส่งข้อมูล: 9600 ความเท่าเทียมกัน: NONE บิตหยุด: 1

[+] -> ?0{SY}13! ถูกเขียนไปที่พอร์ต ((และนี่คือจุดที่มันเข้าสู่วงวนอนันต์ที่อ่าน " "))

แก้ไข: รหัสสำหรับอ่าน:

const int bytesToRead = 1;              //I byte pr læsning
char buffer[bytesToRead + 1] = { 0 };   //Bufferen til data
DWORD dwBytesRead = 0;                  //Antal bytes læst
string store;                           //Store - den vi gemmer den samlede streng i
bool end = false;                       //Kontrolvariabel til whileloop.

while (end == false)                    
{
    if (ReadFile(hserial, buffer, bytesToRead, &dwBytesRead, NULL)) 
    /*Readfile læser fra interfacet vha. hserial som vi oprettede i constructoren*/
    {
        if (buffer[0] == '?')           //Da protokollen slutter en modtaget streng med "?", sætter vi end til true 
        {                               //Hvis denne læses.     
            end = true;     
        }
        store += buffer[0];
    }
    else
    {
        if (debug_ != LOW)
        {
            cout << "[-] Read fail" << endl;    //Hvis readfile returnerer false, så er der sket en fejl. 
        }
        end = true;
    }
}

if (debug_ == HIGH)
{
    cout << "[+] Recieved: " << store << endl;  //I forbindelse med debug, er det muligt at få udsrkevet det man fik ind.
}

recentIn = store;                               //RecentIN brugES i andre funktioner                
if (verify())                                   //Som f.eks. her, hvor vi verificerer dataen
{
    if (debug_ == HIGH)
    {
        cout << "[+] Verification success!" << endl;
    }
    return convertRecData(store);
}
else
{
    if (debug_ != LOW)
    {
        cout << "[-] Verification failed." << endl;
    }

    vector <string> null;   //Returnerer en string uden data i, hvis der er sket en fejl.
    return null;
}

person Benjamin Larsen    schedule 11.12.2014    source แหล่งที่มา
comment
อะไรจะออกมาเมื่อพอร์ตถูกเตรียมใช้งาน? เช่นเดียวกับในบรรทัด [+] Serial Port ....   -  person Greycon    schedule 11.12.2014
comment
คุณสามารถให้รหัส readData() ได้หรือไม่?   -  person alexm    schedule 11.12.2014
comment
@Greycon - ฉันได้แก้ไขโพสต์ต้นฉบับเพื่อรวมผลลัพธ์แล้ว   -  person Benjamin Larsen    schedule 11.12.2014
comment
@alexm ฉันได้แก้ไขโพสต์แล้ว   -  person Benjamin Larsen    schedule 11.12.2014
comment
คุณกำลังพึ่งพาความมีน้ำใจของคนแปลกหน้าในการเริ่มต้น DCB ให้กับคุณ การตั้งค่าการจับมือไม่เคยมีรายละเอียดเล็กๆ น้อยๆ ง่ายต่อการแก้ไขโดยดูที่ DCB ที่ส่งคืนโดย GetCommState() btw   -  person Hans Passant    schedule 11.12.2014
comment
@HansPassant ฉันเห็นสิ่งที่คุณหมายถึง ขอบคุณที่สังเกตเห็น   -  person Benjamin Larsen    schedule 11.12.2014
comment
เมธอด setHandshake() หายไปอย่างสิ้นเชิง มันเข้าข่ายการร้องเรียน   -  person Hans Passant    schedule 11.12.2014
comment
@HansPassant ฉันพยายามแก้ไขโค้ด ` dcbParms.BaudRate = 9600; dcbParms.Parity = NOPARITY; dcbParms.StopBits = 1; SetCommState(hserial, &dcbParms);` แม้ว่าจะไม่มีผลกระทบต่อโปรแกรมก็ตาม ค่ามาตรฐานสำหรับส่วนที่เหลือควรจะใช้ได้ '   -  person Benjamin Larsen    schedule 11.12.2014
comment
อ่านโพสต์นี้เพื่อดูข้อมูลเบื้องต้นเกี่ยวกับความหมายของการจับมือกัน   -  person Hans Passant    schedule 11.12.2014
comment
ฉันมีปัญหาเดียวกัน แม้ว่าฉันจะโทรหา SetCommState ก็ตาม ลิงก์ที่โพสต์โดย Hans Passant ช่วยให้ฉันเห็นปัญหา ในกรณีของฉันมันคือ DtrControl ขอบคุณมาก !!!   -  person BaldDude    schedule 14.11.2018


คำตอบ (3)


คุณไม่เคยโทร SetCommState

ฉันไม่แน่ใจว่าฟังก์ชัน setBaud,setParity ฯลฯ ของคุณมาจากไหน แต่ฉันไม่เห็นว่าฟังก์ชันเหล่านี้สามารถปรับเปลี่ยนพอร์ตอนุกรมได้อย่างไร เนื่องจากไม่สามารถเข้าถึงที่จับของอุปกรณ์สื่อสารได้

person Roddy    schedule 11.12.2014
comment
ฉันเห็นสิ่งที่คุณหมายถึง ฟังก์ชัน GetCommState เป็นเพียงฟังก์ชันเดียวที่ได้รับสิ่งเหล่านี้ การใช้ SetBaud และอื่นๆ: dcbParms.BaudRate = CBR_110 ฉันจะลองใช้ SetCommState - person Benjamin Larsen; 11.12.2014
comment
..แม้ว่าจะให้ผลเช่นเดียวกันเมื่อใช้ SetCommState หลังจากส่งข้อมูลไปยังโครงสร้าง dcb :-( - person Benjamin Larsen; 11.12.2014
comment
@BenjaminLarsen คุณควรจะตรวจสอบว่าพอร์ตได้รับการกำหนดค่าอย่างถูกต้องโดยพิมพ์ MODE COMn: ลงในพร้อมท์คำสั่ง หรือเพียงโทรหา GetCommState ครั้งที่สอง (ใน DCB อื่น) แล้วเปรียบเทียบทั้งสอง นอกจากนี้ หากโค้ดของคุณใช้งานได้หลังจาก PUTTY ทำงาน ให้เปรียบเทียบ DCB ที่คุณได้รับหลังจากนั้นกับ DCB หลังจากรันการตั้งค่าแล้ว - person Roddy; 12.12.2014
comment
โอ้ และอีกอย่างหนึ่ง: ฟิลด์ StopBits ใน DCB นั้นใช้งานไม่ได้ง่ายมาก (0= 1 บิตหยุด, 1=1.5 บิตหยุด, 2=2) คุณควรใช้ dcbParms.StopBits = ONESTOPBIT; - person Roddy; 12.12.2014

ReadFile() สามารถคืนความสำเร็จได้แม้ว่าจะอ่านเป็นศูนย์ไบต์ก็ตาม ใช้ dwBytesRead เพื่อค้นหาจำนวนอักขระที่ได้รับจริง

while (ReadFile(hserial, buffer, 1, &dwBytesRead, NULL)) 
{
    if (dwBytesRead != 0)
    {
       store += buffer[0];

       if (buffer[0] == '?')  
       {                               
           end = true;     
           break;
       }
    }
}
person alexm    schedule 11.12.2014
comment
ใช่ ฉันตระหนักดีถึงเรื่องนั้น ฉันพยายามดึงทุกอย่างออกจากบัฟเฟอร์ ว่างเปล่าทั้งหมด ปัญหาอาจอยู่ในตัวสร้าง - ดูเหมือนจะไม่สามารถทำงานได้ - person Benjamin Larsen; 11.12.2014
comment
@BenjaminLarsen ดังนั้น dwBytesRead ไม่ใช่ศูนย์ใช่ไหม - person alexm; 11.12.2014

มีปัญหาคล้ายกันระหว่างพีซีกับ Arduino nano clone รวมถึง CH340 โพสต์นี้เป็นโพสต์เดียวที่อธิบายปัญหาของฉันได้ดีมาก ฉันแก้ไขมันได้โดยปิดการควบคุมโฟลว์ DTR (พร้อมเทอร์มินัลข้อมูล) และ RTS (คำขอเพื่อส่ง) ซึ่งจะเปิดใช้งานตามปกติหลังจาก (รีสตาร์ท) พีซีหรือเสียบปลั๊ก Arduino ฉันพบคำอธิบายของพารามิเตอร์นี้ในเอกสารประกอบของ ดีซีบี

ฉันรู้ว่าโพสต์ของ Shis นั้นเก่ามาก แต่บางทีฉันอาจช่วยคนอื่นด้วยแนวคิด/วิธีแก้ปัญหานี้ได้

person DGO    schedule 07.06.2020
comment
อา!! นี่อาจเป็นปัญหาของฉันเช่นกัน! ขอบคุณ! stackoverflow.com/questions/64929987/ - person Jimmy Westberg; 27.11.2020