簡體   English   中英

C程序不斷在串行端口上發送相同的數據

[英]C program keeps sending same data on serial port

我正在運行一個運行Linux嵌入式ARM的SOM板,並且正在開發一個C程序以通過串行(RS232)端口與外部設備進行通信。 我遇到一種奇怪的行為。 我還使用板上的另一個串行端口與板上運行的linux通信。

該軟件具有簡單的結構:是一個純文本的類似控制台的程序,其作為主菜單:

Possible commands:
1 - 4: Select serial device (pump should be on 1)
m - pump op. mode configuration
r -  reads from the serial device
w -  writes to the serial device
>>>>>>>>>>>>>>Current device is /dev/ttymxc1
>>>>>>>>>>>>>>Enter input (q quits):

和輔助菜單(通過上面的“ m”選項打開)

SPEED:
r - rpm (sends 1M<CR>) //<CR> stands for carriage return
f - flow rate (sends 1N<CR>)
QUANTITY:
v - volume (sends 1H<CR>)
t - time (sends 1O<CR>)
DIRECTION:
c - clockwise (sends 1T<CR>)
a - c-clockwise (sends 1K<CR>)
>>>>>>>>>>>>>>Enter input (q quits):

使用主菜單選項“ r”和“ w”進行通訊可以很好地工作(從而消除了我對諸如波特率之類的串行設置的疑問):“ w”調用了一個例程(以下稱為“ serial_write”),該例程發送一個單字符輸入用戶,而“ r”則返回讀取后的數據(使用下面的“ serial_read”)。 無論我重復“ w”和“ r”循環的時間如何,我發送的字符都能正確到達,並且在控制台上可以正確顯示答案。

二級菜單中的選項應以相同的方式運行:它們僅調用例程(以下稱為“ sendSimpleCmd”),該例程將以“ charant”字符作為參數調用“ serial_write”(每個選項均不同),然后調用“ serial_read”。

問題在於,這僅適用於所選的第一個選項:此后,無論我選擇哪個選項,程序都會繼續發送鏈接到所選第一個選項的數據。 它一直這樣做,直到我回到主菜單,然后再次選擇“ m”:這時發送的數據是我期望的數據,但是后續的選擇將被忽略,直到我返回主菜單(或關閉)軟件,如果那很重要)。

最奇怪的是,我在與主板進行通信的同一串行上收到了預期的數據,而在“正確的”串行端口上,我不斷收到第一條消息。 這是在選擇“ f”作為第一選項后,當我選擇“ a”作為第二選項時從控制台粘貼的文本(由我添加的注釋):

SPEED:
r - rpm (sends 1M<CR>)   
f - flow rate (sends 1N<CR>)
QUANTITY:
v - volume (sends 1H<CR>)
t - time (sends 1O<CR>)
DIRECTION:
c - clockwise (sends 1T<CR>)
a - c-clockwise (sends 1K<CR>)
>>>>>>>>>>>>>>Enter input (q quits):
a                   //second option
1Knding 1M          //mixup of data 
wrote 4 characters on fs 4
serial_read: *

混合由軟件輸出(“發送數據1M”)和選擇選項“ a”(1K)后應發送的數據組成。 由於在“正確”端口上一遍又一遍地得到相同的消息,而在“錯誤”端口上我得到正確的消息,似乎軟件以某種方式自主地更改了端口。

問題是:此行為可能是由我的編碼引起的,還是與其他某些內核配置(例如某些內核配置)綁定? 如果需要更多信息,請詢問。

先感謝您


Serial_write

void serial_write(char text[], int length){

    if (selectedDevice == 0){
        printf("Select device first!\r\n");
        return;
    }

    int n;
    length = length +1 + 2; 
    char toBeSent[length];
    strcat(toBeSent, PUMP_CMD_MSG_START); //header, "1"
    strcat(toBeSent, text);
    strcat(toBeSent, PUMP_CMD_MSG_END); //footer, "<CR>"
    printf("Sending %s\r\n", toBeSent);
    n = write (fd, toBeSent, length);
    if (n<0){
        printf("writing failed on /dev/ttymxc%i\r\n", selectedDevice);
    } else {
        printf("wrote %i characters on fs %i\r\n", n, fd);

    }
}

Serial_read

int serial_read(char *buffer, int size){
    int bytes = 0;
    int n;
    int i = 0;
    char tmp_buffer[size];

    while(1){
        ioctl(fd, FIONREAD, &bytes); 
        if (bytes > 0){
            break;
        }
        i++;
        if(i> 1000){
            printf("FIONREAD tries exceeded 1000, aborting read\r\n");
            return;
        }
        usleep(1000);
    }

    n=read(fd, tmp_buffer, sizeof(tmp_buffer));
    for(i=0;i<n;i++) {
        buffer[i]=tmp_buffer[i];
    }
    printf("serial_read: %s\r\n", buffer);
    return 0;
}

sendSimpleCmd

void sendSimpleCmd(char text[]){
    int bufSize= 20;
    char answer[bufSize];
    serial_write(text,1);

    if (serial_read(answer, bufSize) == 0) {
        printf("Ricevuto da pompa \"%s\":", answer);

        //handling of possible answers, doesn't do anything relevant since it always receives "*" as answer
        if (strcmp(answer, PUMP_ANS_OK) == 0){ //PUMP_ANS_OK is "*"
                printf("ok!\r\n");
            } else if (strcmp(answer, PUMP_ANS_NOK) == 0){
                printf("errore!\r\n");
            } else {
                printf("sconosciuto!\r\n");
            }
    } else {
//        printf("read failed\r\n");
    }
}

在使用strcat之前,您應該初始化toBeSent的內容。

您的編譯器可能通過用0而不是垃圾初始化數組來節省您的時間,但是如果不這樣做,則可能導致緩沖區溢出。 沒有代碼可以防止這種情況發生,因此這可能是程序意外行為的原因。 如果不查看代碼的其余部分並了解其他一些細節,將很難知道問題出在哪里。 如果這作為其余代碼的示例,則該解決方案很可能會修改代碼以解決這些問題。

考慮使用安全的字符串函數來幫助防止緩沖區溢出。

暫無
暫無

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

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