Linux串口编程(向空调发送十六进制指令)

一 首先需要提示:ubuntu下面打开串口需要超级权限,可以用下面两种方法来获得打开串口的权限。
方法一:
由于tty属于“dialout”组别,将用户加入到dialout用户组即可。例如我用户名是thinker,操作如下。
sudo usermod -aG dialout thinker
方法二:
在 /etc/udev/rules.d 目录下面添加一个 :
20-usb-serial.rules的文件, 内容如下:

    KERNEL=="ttyUSB*"  MODE="0666"  

注销或者重启电脑即可。

二 该程序发送的命令是格力立式空调的关闭命令,其他空调或者其他命令需要修改下面comm变量的值。
main.cpp

#include "nfraredSerial.h"
#include 
#include 
#include 
#include 
#include 
#include 
int main(int argc, char **argv)
{
    char comm[10] = {0};
    comm[0] = 0x04;
    comm[1] = 0x00;
    comm[2] = 0x08;
    comm[3] = 0x08;
    comm[4] = 0x04;

    InfraredSerial infrared_serial;
    infrared_serial.uart_send(comm, 5);
    char recv[5];
    infrared_serial.uart_recv(recv, 10);
    return 0;
}

InfraredSerial.h ,和main.cpp放到同一个目录下

//
// Created by thinker on 16-7-7.
//

#ifndef FIRST_INFRAREDSERIAL_H
#define FIRST_INFRAREDSERIAL_H

#endif //FIRST_INFRAREDSERIAL_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define DEV "/dev/ttyUSB0"

class InfraredSerial {
    int serial_fd;
public:

    InfraredSerial():serial_fd(0){

        serial_fd = open(DEV, O_RDWR | O_NOCTTY | O_NDELAY);
        if (serial_fd < 0) {
            perror("open");
        }
        struct termios options;
        tcgetattr(serial_fd, &options);
        /**2. 修改所获得的参数*/
        options.c_cflag |= (CLOCAL | CREAD);//设置控制模式状态,本地连接,接收使能
        options.c_cflag &= ~CSIZE;//字符长度,设置数据位之前一定要屏掉这个位
        options.c_cflag &= ~CRTSCTS;//无硬件流控
        options.c_cflag |= CS8;//8位数据长度
        options.c_cflag &= ~CSTOPB;//1位停止位
        options.c_iflag |= IGNPAR;//无奇偶检验位
        options.c_oflag = 0; //输出模式
        options.c_lflag = 0; //不激活终端模式
        cfsetospeed(&options, B9600);//设置波特率
        cfsetispeed(&options, B9600);
        /**3. 设置新属性,TCSANOW:所有改变立即生效*/
        tcflush(serial_fd, TCIFLUSH);//溢出数据可以接收,但不读
        tcsetattr(serial_fd, TCSANOW, &options);
    };

//    ~InfraredSerial();

    int uart_send(char *data, ssize_t datalen);

    int uart_recv(char *data, int datalen);

protected:

};
int InfraredSerial::uart_recv(char *data, int datalen)
{
    int len=0, ret = 0;
    fd_set fs_read;
    struct timeval tv_timeout;

    FD_ZERO(&fs_read);
    FD_SET(serial_fd, &fs_read);
    tv_timeout.tv_sec  = (10*20/115200+2);
    tv_timeout.tv_usec = 0;

    ret = select(serial_fd+1, &fs_read, NULL, NULL, &tv_timeout);
    printf("ret = %d\n", ret);
    //如果返回0,代表在描述符状态改变前已超过timeout时间,错误返回-1

    if (FD_ISSET(serial_fd, &fs_read)) {
        len = read(serial_fd, data, datalen);
        printf("len = %d\n", len);
        return len;
    } else {
        perror("select");
        return -1;
    }
}

int InfraredSerial::uart_send(char *data, ssize_t datalen)
{
    ssize_t len = 0;
    len = write(serial_fd, data, datalen);//实际写入的长度
    if(len == datalen) {
        return len;
    } else {
        tcflush(serial_fd, TCOFLUSH);//TCOFLUSH刷新写入的数据但不传送
        return -1;
    }
}

附:把十进制整型转为十六进制

char comm[10] = {0};
int int_tem = 4;
char *tem;
tem = (char *)&int_tem;
comm[0] = tem[0]&0xff;  //根据大端序和小端序,可能是tem[3];
printf("%x", comm[0]);  //是十六进制的数,如果其他格式输出可能会乱码

你可能感兴趣的:(c++知识点)