123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- #ifndef _UART_H_
- #define _UART_H_
- #include <stdio.h>
- #include <fcntl.h>
- #include <termios.h>
- #include <string.h>
- #include <unistd.h>
- #include <signal.h>
- #include <stdlib.h>
- int serial_init(char *device, int speed, int databits, int parity, int stopbits, int RTSCTS, int newline);
- int serial_write(int fd, void *src, int len);
- int serial_read(int fd, char *buf, int len);
- //串口默认初始化接口
- #define serial_default(device) serial_init(device, 1500000, 8, 'n', 1, 0, 1)
- #endif
- /**
- *@brief 设置串口数据位,停止位和效验位
- *@param fd 类型 int 打开的串口文件句柄
- *@param speed 类型 int 波特率
- *@param databits 类型 int 数据位 取值为 7 或者8
- *@param stopbits 类型 int 停止位 取值为 1 或者2
- *@param parity 类型 char 效验类型 取值为N,E,O,S
- *@param newline 类型 int 新的一行输出
- */
- int set_parity(int fd, int speed, int databits, int parity, int stopbits, int RTSCTS, int newline)
- {
- struct termios options;
- if ( tcgetattr(fd, &options) != 0) {
- return -1;
- }
-
- cfsetispeed(&options, speed);
- cfsetospeed(&options, speed);
-
- options.c_cflag &= ~CSIZE;
-
- switch (databits) /*设置数据位数*/
- {
- case 7:
- options.c_cflag |= CS7;
- break;
- case 8:
- options.c_cflag |= CS8;
- break;
- default:
- return -1;
- }
- options.c_iflag |= INPCK;
- cfmakeraw(&options);
- //options.c_lflag |= (ICANON | ECHO | ECHOE);
- //options.c_lflag &= ~(ICANON | ECHO | ECHOE);
- //options.c_iflag &= ~(IXON | IXOFF);
- switch (parity)
- {
- case 'n':
- case 'N':
- options.c_cflag &= ~PARENB; /* Clear parity enable */
- options.c_iflag &= ~INPCK; /* Enable parity checking */
- break;
- case 'o':
- case 'O':
- options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
- break;
- case 'e':
- case 'E':
- options.c_cflag |= PARENB; /* Enable parity */
- options.c_cflag &= ~PARODD; /* 转换为偶效验*/
- break;
- case 'S':
- case 's': /*as no parity*/
- options.c_cflag &= ~PARENB;
- options.c_cflag &= ~CSTOPB;
- break;
- default:
- return -1;
- }
- /* 设置停止位*/
- switch (stopbits)
- {
- case 1:
- options.c_cflag &= ~CSTOPB;
- break;
- case 2:
- options.c_cflag |= CSTOPB;
- break;
- default:
- return -1;
- }
- /* Set rts/cts */
- if (RTSCTS)
- {
- options.c_cflag |= CRTSCTS;
- }
-
- if (newline)
- {
- options.c_lflag |= ICANON;
- }
- tcflush(fd,TCIFLUSH);
- options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/
- options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
- if (tcsetattr(fd, TCSANOW, &options) != 0)
- {
- return -1;
- }
- // printf("set_Parity\n");
- return 0;
- }
- /**
- *@brief
- *@param device 串口设备
- *@param speed 串口速度
- *@param databits,parity,stopbits,RTSCTS,分别为数据位,校验位,停止位,rtscts位
- *@param newline 接收数据结尾是否加换行符?
- */
- int serial_init(char *device, int speed, int databits, int parity, int stopbits, int RTSCTS, int newline)
- {
- int fd, ret;
- fd = open(device, O_RDWR|O_NOCTTY);//O_NONBLOCK 非阻塞, O_WRONLY 只读写, O_RDONLY 只读, O_RDWR 读写,O_NOCTTY 阻塞
- if (-1 == fd) {
- fprintf(stderr, "ERROR: init %s failed\n", device);
- return -1;
- }
- ret = set_parity(fd, speed, databits, parity, stopbits, RTSCTS, newline);
- if (ret < 0) {
- fprintf(stderr, "ERROR: set parity failed\n");
- return -1;
- }
-
- return fd;
- }
- /**
- *@brief
- *@param fd 串口端口号文件描述符
- *@param src 需要通过串口发送的数据
- *@param len 需要发送的数据长度
- *@param 成功返回0, 否则返回-1
- */
- int serial_write(int fd, void *src, int len)
- {
- int ret = write(fd, src, len);
- if (len != ret) {
- fprintf(stderr, "ERROR: write serial failed!\n");
- return -1;
- }
- return 0;
- }
- /**
- *@brief
- *@param fd 串口端口号文件描述符
- *@param src 串口接收数据的指针
- *@param len 需要接收的数据长度
- *@param 成功返回0, 否则返回-1
- */
- int serial_read(int fd, char *buf, int len)
- {
- int ret = read(fd, buf, len-1);
- if (-1 == ret) {
- fprintf(stderr, "ERROR: read serial failed!\n");
- return -1;
- }
- buf[ret] = '\0';
- return ret;
- }
- static void timeout()
- {
- fprintf(stderr, "No response from modem.\n");
- exit(1);
- }
- /*字符包含判断*/
- static int starts_with(const char* prefix, const char* str)
- {
- while(*prefix)
- {
- if (*prefix++ != *str++)
- {
- return 0;
- }
- }
- return 1;
- }
- /*判断是否存在*/
- int file_exist(const char* filename)
- {
- if (filename && access(filename, F_OK) == 0) {
- return 1;
- }
- return 0;
- }
- int main(int argc, char **argv)
- {
- if(argc != 3)
- {
- fprintf(stderr, "Usage: sendat 2 'ATI'\n");
- return 1;
- }
- char device[16];
- sprintf(device, "/dev/ttyUSB%s", argv[1]);
- char *message= argv[2];
- if (*message=='\0')
- {
- fprintf(stderr, "ERROR: AT Command Absent.\n");
- return 1;
- }
-
- if(file_exist(device)==0)
- {
- fprintf(stderr, "ERROR: AT Device Absent.\n");
- return 1;
- }
- signal(SIGALRM, timeout);
- alarm(5);
-
- char *rn= "\r\n";
- char buff[1024];
- int fd = serial_default(device);
- if(fd < 0) return 1;
- char *msg= strcat(message, rn);
- serial_write(fd, msg, strlen(msg));
- int ret=0;
- while(1) {
- int read = serial_read(fd, buff, sizeof(buff));
- printf("%s", buff);
-
- if(starts_with("OK", buff)) {
- break;
- }
- if(starts_with("ERROR", buff)) {
- ret=1;
- break;
- }
- if(starts_with("COMMAND NOT SUPPORT", buff)) {
- ret=1;
- break;
- }
- if(starts_with("+CME ERROR", buff)) {
- ret=1;
- break;
- }
- if(starts_with("+CMS ERROR", buff)) {
- ret=1;
- break;
- }
- }
- close(fd);
- return ret;
- }
|