问题描述
我想将RFID阅读器附加到我的android应用程序上,但是我陷入了termios错误的初始化代码!读取器在Windows上的工作速度为19200 br / 8个数据位/ N(o奇偶校验)/ 1个停止位。 当将我的测试控制台应用程序运行到带有ubuntu 20.04的WSL环境中时,它始终运行良好!但是,当我在真实PC(或android)上的Ubuntu 20.04上运行它时,它在read()上返回损坏的数据,但似乎读取器始终接受未损坏的命令,但我不确定。我想知道我做错了什么吗?在同一台PC上,在netcore 3.1上重写为system.io.serialports的示例效果很好!因此,似乎只有我的代码问题! (我只了解带有一些默认值的Windows初始化序列,而且似乎没有将所有系统调用代理到winapi)
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <errno.h>
#define SOH 0x01
#define STX 0x02
#define ETX 0x03
#define EOT 0x04
#define ENQ 0x05
#define ACK 0x06
#define NAK 0x15
#define CAN 0x18
static speed_t getBaudrate(int baudrate)
{
switch (baudrate) {
case 0: return B0;
case 50: return B50;
case 75: return B75;
case 110: return B110;
case 134: return B134;
case 150: return B150;
case 200: return B200;
case 300: return B300;
case 600: return B600;
case 1200: return B1200;
case 1800: return B1800;
case 2400: return B2400;
case 4800: return B4800;
case 9600: return B9600;
case 19200: return B19200;
case 38400: return B38400;
case 57600: return B57600;
case 115200: return B115200;
case 230400: return B230400;
case 460800: return B460800;
case 500000: return B500000;
case 576000: return B576000;
case 921600: return B921600;
case 1000000: return B1000000;
case 1152000: return B1152000;
case 1500000: return B1500000;
case 2000000: return B2000000;
case 2500000: return B2500000;
case 3000000: return B3000000;
case 3500000: return B3500000;
case 4000000: return B4000000;
default: return -1;
}
}
char bcc(char* buffer,int size)
{
char result = SOH;
while (size-->0)result ^= *buffer++;
return result;
}
void test(int fd)
{
char cmd_buffer[] = { 0x01,0x43,0x31,0x02,0x03,0x42 };
char response_buffer[256];
char dump_buffer[1025];
int bytes_available;
char response;
char enq = ENQ;
ioctl(fd,FIONREAD,&bytes_available);
read(fd,response_buffer,bytes_available);
memset(response_buffer,sizeof(response_buffer));
memset(dump_buffer,sizeof(dump_buffer));
if (fd < 0)
printf("Bad file descriptor!\n");
write(fd,cmd_buffer,sizeof(cmd_buffer));
bytes_available = 0;
while (!bytes_available)
{
ioctl(fd,&bytes_available);
usleep(100000);
}
read(fd,&response,1);
if (response == ACK)
{
//printf("OK! ACK was recieved!\n");
write(fd,&enq,1);
bytes_available = 0;
while (bytes_available<14)
{
ioctl(fd,&bytes_available);
usleep(100000);
}
ioctl(fd,&bytes_available);
int read_count = read(fd,bytes_available);
for (int i = 0; i < read_count; i++)
{
sprintf(dump_buffer + strlen(dump_buffer),"%02X ",(0xff & response_buffer[i]));
}
printf("%s - BCC: %02X,BCC[-1]: %02X\n",dump_buffer,0xff&bcc(response_buffer,read_count),0xff & bcc(response_buffer,read_count-1));
}
else
printf("ACK was not recieved!\n");
}
int configTTY2(int fd,int baudrate)
{
if (ioctl(fd,TIOCEXCL)) {
printf("configTTY2 open: error setting TIOCEXCL: errno=%d\n",errno);
return -1;
}
speed_t speed = getBaudrate(baudrate);
struct termios newtio;
memset(&newtio,sizeof(newtio));
printf("configTTY2: getting attributes\n");
if (tcgetattr(fd,&newtio) == -1) {
printf("configTTY2: tcgetattr Failed: errno=%d\n",errno);
return -2;
}
newtio.c_cflag |= (CLOCAL | CREAD);
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN);
newtio.c_oflag &= ~OPOST;
newtio.c_iflag = IGNBRK;
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |= CS8;
newtio.c_cflag &= ~CSTOPB;
newtio.c_iflag &= ~(INPCK | ISTRIP | IGNPAR | PARMRK);
newtio.c_cflag &= ~(PARENB | PARODD);
#ifdef HAVE_TERMIOS_CMSPAR
newtio.c_cflag &= ~CMSPAR;
#endif
//newtio.c_iflag |= INPCK;
newtio.c_cflag &= ~CRTSCTS;
newtio.c_iflag &= ~(IXON | IXOFF | IXANY);
newtio.c_cc[VMIN] = 0;
newtio.c_cc[VTIME] = 0;
//cfmakeraw(&newtio);
if (cfsetospeed(&newtio,speed) < 0 || cfsetispeed(&newtio,speed) < 0)
{
printf("error to set speed!\n");
return -4;
}
if (tcsetattr(fd,TCSADRAIN,&newtio) < 0) {
printf("setproperties: setting attributes Failed: errno=%d\n",errno);
return -5;
}
//printf("setting attributes done\n");
fsync(fd);
// Get the baudrate and compare with what we set
tcgetattr(fd,&newtio);
if (cfgetispeed(&newtio) != speed ||
cfgetospeed(&newtio) != speed) {
printf("baudrate mismatch. ispeed ret=%d set=%d; ospeed ret=%d set=%d",cfgetispeed(&newtio),speed,cfgetospeed(&newtio),speed);
// For some reason the baudrate was not set to what we had asked.
return -6;
}
return 0;
}
int main( int argc,char** argv)
{
if (argc < 2)
{
printf("\n%s /dev/ttyS0 for select com1\n",argv[0]);
return 0;
}
int fd = open(argv[1],O_RDWR | O_NOCTTY | O_SYNC );
if (fd < 0 )
{
printf("Cannot open port!\n");
return -1;
}
if (configTTY2(fd,19200) < 0)
return -1;
for (int i = 0; i < 30; i++)
{
printf("%d: ",i);
test(fd);
}
close(fd);
return 0;
}
与ubuntu的WSL通信转储: 循环发送获取版本命令给阅读器,它总是返回正确的响应 [SOH]'c''1''1'[STX] [P] [STATUS] V 2。 0 2 [ETX] [BCC]
./wsl_serial_test /dev/ttyS4
configTTY2: getting attributes
0: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
1: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
2: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
3: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
4: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
5: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
6: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
7: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
8: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
9: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
10: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
11: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
12: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
13: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
14: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
15: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
16: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
17: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
18: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
19: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
20: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
21: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
22: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
23: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
24: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
25: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
26: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
27: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
28: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
29: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
使用ubuntu在PC上进行通讯转储:
./wsl_serial_test /dev/ttyS0
configTTY2: getting attributes
0: 01 43 31 39 02 D0 00 56 32 2E 30 32 03 5A - BCC: 88,BCC[-1]: D2
1: 01 43 31 31 02 50 00 56 32 2E 30 32 83 5A - BCC: 80,BCC[-1]: DA
2: 01 43 31 31 02 58 00 56 32 2E 30 32 03 5A - BCC: 08,BCC[-1]: 52
3: 01 43 31 71 02 50 00 56 32 2E 30 32 03 5A - BCC: 40,BCC[-1]: 1A
4: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
5: 01 43 B1 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 80,BCC[-1]: DA
6: 01 53 31 31 82 50 00 56 32 2E 60 32 03 5B - BCC: C1,BCC[-1]: 9A
7: 01 43 31 99 02 50 00 5E 32 2E 30 32 03 AE - BCC: 54,BCC[-1]: FA
8: 01 43 31 31 02 A0 00 56 32 2E 30 9A 03 5A - BCC: 58,BCC[-1]: 02
9: ACK was not recieved!
10: 01 43 31 31 02 B0 00 F6 32 2E 30 32 83 5A - BCC: C0,BCC[-1]: 9A
11: ACK was not recieved!
12: 01 43 31 31 02 50 02 56 32 2E 30 32 03 5A - BCC: 02,BCC[-1]: 58
13: ACK was not recieved!
14: 01 43 31 31 02 B0 00 56 32 2E 30 32 03 BA - BCC: 00,BCC[-1]: BA
15: 01 43 31 31 02 50 00 56 32 2E 30 32 43 5A - BCC: 40,BCC[-1]: 1A
16: 81 43 31 71 02 50 00 56 32 2E 30 32 03 5A - BCC: C0,BCC[-1]: 9A
17: ACK was not recieved!
18: 81 43 31 31 82 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
19: ACK was not recieved!
20: 01 43 31 31 82 50 00 56 32 2E 30 32 03 5A - BCC: 80,BCC[-1]: DA
21: 01 43 31 31 02 50 00 56 32 2E 30 32 03 5A - BCC: 00,BCC[-1]: 5A
22: 01 43 D9 CC 81 D0 00 56 B2 2E 30 36 03 5A - BCC: 92,BCC[-1]: C8
23: ACK was not recieved!
24: 81 A3 31 31 02 50 00 56 32 2E 31 9A 03 5A - BCC: C9,BCC[-1]: 93
25: 01 63 31 35 02 A8 80 AE 32 2E 38 32 03 5A - BCC: AC,BCC[-1]: F6
26: 01 C3 31 31 02 50 00 56 9A 2E 30 32 03 5A - BCC: 28,BCC[-1]: 72
27: 01 43 31 63 02 50 01 56 32 2E 30 32 03 5A - BCC: 53,BCC[-1]: 09
28: ACK was not recieved!
29: 81 43 31 33 02 50 00 56 32 AE 30 32 03 5A - BCC: 02,BCC[-1]: 58
在同一台ubuntu PC上进行dotnet测试:
~/test_net$ dotnet run --port:/dev/ttyS0
Ack was received,send ENQ
Respose:
01-43-31-31-02-50-00-56-32-2E-30-32-03-5A
~/test_net$ dotnet run --port:/dev/ttyS0
Ack was received,send ENQ
Respose:
01-43-31-31-02-50-00-56-32-2E-30-32-03-5A
/test_net$ cat Program.cs
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace core_serial_test
{
class Program
{
static byte ACK = 0x06;
static byte ENQ = 0x05;
class Anchor { };
static void Main(string[] args)
{
string portName=null;
foreach(var arg in args)
{
var kv = arg.Split(new char[] { ':' });
if(kv.Length==2)
{
switch(kv[0])
{
case "--port":
portName = kv[1];
break;
}
}
}
if(portName==null)
{
Console.WriteLine("{0} --port:[comport name]",System.IO.Path.GetFileName(new Anchor().GetType().Assembly.Location));
string[] ports = SerialPort.GetPortNames();
foreach(var port in ports) Console.WriteLine(port);
return;
}
SerialPort serialPort = new SerialPort(portName,19200,Parity.None,8,StopBits.One);
serialPort.open();
byte[] cmd = new byte[] { 0x01,0x42 };
byte[] response = new byte[200];
serialPort.Write(cmd,cmd.Length);
Thread.Sleep(200);
serialPort.Read(response,1);
if (response[0] == ACK)
serialPort.Write(new byte[] { ENQ },1);
else
return;
Console.WriteLine("Ack was received,send ENQ");
Thread.Sleep(200);
int size = 0;
if (serialPort.BytesToRead > 0)
{
size = serialPort.Read(response,serialPort.BytesToRead);
}
serialPort.Close();
Array.Resize<byte>(ref response,size);
Console.WriteLine("Respose: ");
Console.WriteLine(BitConverter.ToString(response,response.Length));
Console.ReadLine();
}
}
}
今天更新,我正在尝试以下代码示例:
int open_tty(char* ttyname,int baudrate)
{
int USB = open(ttyname,O_RDWR | O_NOCTTY);
struct termios tty;
struct termios tty_old;
memset(&tty,sizeof(tty));
if (tcgetattr(USB,&tty) != 0) {
std::cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << std::endl;
return -1;
}
tty_old = tty;
cfsetospeed(&tty,(speed_t)baudrate);
cfsetispeed(&tty,(speed_t)baudrate);
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 1; // read doesn't block
tty.c_cc[VTIME] = 0;
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
cfmakeraw(&tty);
tcflush(USB,TCIFLUSH);
tcflush(USB,TCOFLUSH);
if (tcsetattr(USB,TCSANow,&tty) != 0) {
std::cout << "Error " << errno << " from tcsetattr" << std::endl;
return -1;
}
return USB;
}
char bcc(char* buffer,int size)
{
char result = SOH;
while (size-- > 0)result ^= *buffer++;
return result;
}
void test(int fd)
{
char cmd_buffer[] = { 0x01,0x42 };
char response_buffer[256];
char dump_buffer[1025];
char response;
char enq = ENQ;
memset(response_buffer,sizeof(cmd_buffer));
usleep(50000);
while(1!=read(fd,1))
usleep(10000);
if (response == ACK)
{
write(fd,1);
usleep(2000);
int read_count = 0;
while (read_count < 14)
{
read_count+=read(fd,response_buffer + read_count,1);
usleep(1000);
}
if (read_count > 7)
{
for (int i = 0; i < read_count; i++)
{
sprintf(dump_buffer + strlen(dump_buffer),(0xff & response_buffer[i]));
}
printf("%s - BCC: %02X,read_count - 1));
}
else
{
tcflush(fd,TCIFLUSH);
tcflush(fd,TCOFLUSH);
printf("read result is %d\n",read_count);
}
}
else
{
printf("ACK was not recieved [%02X] !\n",0xff & response);
tcflush(fd,TCOFLUSH);
}
}
在main()内部进行更改
int main(int argc,char** argv)
{
if (argc == 2 && argv[1][0] == '4')
{
int fd = open_tty("/dev/ttyUSB0",B1200);
int n = 0,spot = 0;
char buf = '\0';
/* Whole response*/
char response[1024];
memset(response,sizeof response);
usleep(10000);
do {
n = read(fd,&buf,1);
if (n)
{
sprintf(&response[spot],"%c",buf);
printf("%c - %02X\n",buf,buf & 0xff);
spot += n;
}
} while (buf != '\r' && n > 0);
if (n < 0) {
std::cout << "Error reading: " << strerror(errno) << std::endl;
}
else if (n == 0) {
std::cout << "Read nothing!" << std::endl;
}
else {
std::cout << "Response: " << response << std::endl;
}
close(fd);
}
else
if (argc == 2 && argv[1][0] == '5')
{
int fd = open_tty("/dev/ttyS0",B19200);
test(fd);
close(fd);
}
}
对于串行初始化,结果从另一台设备读取的文本可以正常工作,读取器的响应仍然看起来不正常!
从重量终端模拟器(位于/ dev / ttyUSB0上)读取文本
./wsl_serial_test 4
P - 50
+ - 2B
- 20
1 - 31
2 - 32
1 - 31
0 - 30
0 - 30
- 0D
Response: P+ 12100
./wsl_serial_test 4
P - 50
+ - 2B
- 20
1 - 31
2 - 32
1 - 31
0 - 30
0 - 30
- 0D
Response: P+ 12100
./wsl_serial_test 4
P - 50
+ - 2B
- 20
1 - 31
2 - 32
1 - 31
0 - 30
0 - 30
- 0D
Response: P+ 12100
./wsl_serial_test 5
01 43 D9 CC 81 50 00 56 32 2E B0 32 03 5A - BCC: 16,BCC[-1]: 4C
./wsl_serial_test 5
01 43 31 31 82 50 00 56 32 2E 30 32 23 5A - BCC: A0,BCC[-1]: FA
./wsl_serial_test 5
01 43 31 35 02 50 00 D6 32 AE 30 32 03 5A - BCC: 04,BCC[-1]: 5E
结论从相对较慢的设备(9600 bps)读取文本可以正常工作,但在阅读器问题上仍然存在。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)