[英]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.