~/share/bin/PC$ dmesg | grep tty
[ 0.083244] printk: console [tty0] enabled
[ 0.329145] 00:02: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A
[ 0.351177] 00:03: ttyS1 at I/O 0x2f8 (irq = 3, base_baud = 115200) is a 16550A
[ 0.420781] tty tty48: hash matches
从回复信息中可以看出电脑有两个串口,分别是ttyS0,ttyS1
USB口的话,信息显示是ttyUSB0
简单实现控制灯开的函数
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h> /*文件控制定义*/
#include <termios.h> /*PPSIX 终端控制定义*/
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/select.h>
#include <sstream>
#include <iomanip>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
using namespace std;
static int lightOn();
static int sendRecv(uint8_t *sBuf, uint16_t sSize, uint8_t *rBuf, uint16_t rSize);
static int Open(const char* device, int baudrate, char parity = 'N', int bytesize = 8, int stopbits = 1);
static int set_parity(int fd,int databits,int stopbits,int parity,int baudrate);
int Read(void* buf, size_t maxLen);
int Write(const void* buf, size_t len);
std::string toHex(uint8_t *buf, uint16_t size);
int m_fd;
int main()
{
Open("/dev/ttyS0", 9600);
lightOn();
return 0;
}
int Open(const char* device, int baudrate, char parity/* = 'N'*/, int bytesize/* = 8*/, int stopbits/* = 1*/)
{
printf("enter %s\n", __func__);
m_fd = ::open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (m_fd < 0){
perror("打开COM口时出错");
return -1;
}
//if( set_parity(m_fd,8,1,'N') < 0)
if( set_parity(m_fd, bytesize, stopbits, parity, baudrate) < 0){
perror("Set Parity Error\n");
return -1;
}
tcflush(m_fd, TCIOFLUSH);
printf("leave %s\n", __func__);
return 0;
}
int set_parity(int fd,int databits,int stopbits,int parity,int baudrate)
{
struct termios optnew;
speed_t speed = B19200;
if ( fd >0 ) {
/* Read with blocking behavior */
fcntl(fd, F_SETFL, 0);
/* Get current option */
tcgetattr(fd, &optnew);
/* initialize new option to raw input/output */
// memset(&optnew, 0, sizeof(optnew));
cfmakeraw(&optnew);
optnew.c_cc[VMIN ] = 0;
optnew.c_cc[VTIME] = 2*10;
/* set baudrate */
switch (baudrate) {
case 1200: speed = B1200; break;
case 1800: speed = B1800; break;
case 4800: speed = B4800; break;
case 9600: speed = B9600; break;
case 19200: speed = B19200; break;
case 38400: speed = B38400; break;
case 57600: speed = B57600; break;
case 115200: speed = B115200; break;
default: speed = B19200; break;
}
cfsetispeed(&optnew, speed);
cfsetospeed(&optnew, speed);
/* Set data bits */
optnew.c_cflag &= ~CSIZE;
optnew.c_cflag &= ~CRTSCTS;
optnew.c_iflag &= ~(ICRNL|IXON);
optnew.c_cflag |= CLOCAL | CREAD;
optnew.c_oflag &= ~OPOST;
switch (databits) {
case 5: optnew.c_cflag |= CS5; break;
case 6: optnew.c_cflag |= CS6; break;
case 7: optnew.c_cflag |= CS7; break;
default :
optnew.c_cflag |= CS8; break;
}
/* Set parity checking */
optnew.c_cflag |= PARENB;
switch (parity) {
case 'e':
case 'E': optnew.c_cflag &= ~PARODD; break;
case 'o':
case 'O': optnew.c_cflag &= PARODD; break;
default :
optnew.c_cflag &= ~PARENB; break;
}
/* Set stop bit(s) */
if (stopbits == 2)
optnew.c_cflag &= CSTOPB;
else
optnew.c_cflag &= ~CSTOPB;
optnew.c_lflag &= ~( ICANON | ECHO | ECHOE | ISIG );
/* Apply new option */
tcsetattr(fd, TCSANOW, &optnew);
}
return fd;
}
int lightOn()
{
uint8_t send[] = {0x2A, 0x4B, 0x0D};
uint8_t right[] = {0x2A, 0x4B, 0x00, 0x0D};
int retry = 2;
while(retry--){
uint8_t recv[sizeof(right)];
memset(recv, 0, sizeof(right));
printf("send %s\n", toHex((uint8_t *)send, sizeof(send)).c_str());
const int recvCount = sendRecv(send, sizeof(send), recv, sizeof(recv));
if(recvCount != sizeof(recv)){
if(recvCount){
printf("recv %s\n", toHex((uint8_t *)recv, sizeof(recv)).c_str());
}
continue;
}
if(0 != memcmp(right, recv, sizeof(right))){
printf("recv %s\n", toHex((uint8_t *)recv, sizeof(recv)).c_str());
continue;
}
//success
printf("recv %s\n", toHex((uint8_t *)recv, sizeof(recv)).c_str());
retry = 0;
break;
}
return retry;
}
int sendRecv(uint8_t *sBuf, uint16_t sSize, uint8_t *rBuf, uint16_t rSize)
{
printf("enter %s\n", __func__);
// m_mutex.lock();
int ret = Write(sBuf, sSize);
if (ret != 0){
printf("%s Write error, Buf:%s\n", __func__, sBuf);
goto _RET;
}
ret = Read(rBuf, rSize);
if (ret != rSize){
printf("%s read:%s ret:%d\n", __func__, rBuf, ret);
goto _RET;
}
_RET:
// m_mutex.unlock();
return ret;
}
int Write(const void* buf, size_t len)
{
printf("enter %s\n", __func__);
int ret = 0;
int n = ::write(m_fd, buf, len);
if(n != len){
ret = -2;
}
// printf("send to uart result:%i\n", ret);
return ret;
}
/*
* return 接受到的字节数
*/
int Read(void* buf, size_t maxLen)
{
printf("enter %s\n", __func__);
int offset = 0;
while(offset < maxLen){
fd_set rd;
FD_ZERO(&rd);
FD_SET(m_fd, &rd);
timeval timeout;
timeout.tv_sec = 1;
int ready = select(m_fd+1, &rd, NULL, NULL, &timeout);
if (ready == 0){ //timeout
// offset = SER_TO;
printf("timeout\n");
break;
}else if (ready == -1 && (errno != EINTR) ){ //error
offset = -2;
printf("error\n");
break;
}else if(ready == 1){
if (FD_ISSET(m_fd, &rd)){
int n = ::read(m_fd, buf + offset, maxLen - offset);
if(n > 0){
offset += n;
}
}
}
}
return offset;
}
std::string toHex(uint8_t *buf, uint16_t size)
{
std::stringstream hexSS;
for (int i = 0; i < size; i++){
hexSS << std::setw(2) << std::setfill('0') << std::hex << (int)buf[i] << " ";
}
std::string hexStr = hexSS.str();
return hexStr;
}
在::open() 出错时,已经通过perror函数打印出出错信息,可以根据信息修改
1)比如报错信息提示权限不对,修改权限
chmod 666 /dev/ttyS0
2)检查串口波特率
~/share/bin/PC$ stty -F /dev/ttyS0
speed 9600 baud; line = 0;
min = 0; time = 20;
-brkint -icrnl -imaxbel
-opost
-isig -icanon -iexten -echo -echoe
?