⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 port.c

📁 嵌入式的小程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>              // printf
#include <fcntl.h>              // open
#include <string.h>             // bzero
#include <stdlib.h>             // exit
#include <sys/times.h>          // times
#include <sys/stat.h>           // lstat
#include <pthread.h>
#include <signal.h>

#include <sys/types.h>          // pid_t
#include <limits.h>             // CHAR_MAX

#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>          // ioctl
#include "../include/types.h"   // INT32, INT16, INT8, UINT32, UINT16, UINT8
#include "../include/arithmetic.h"

#define TTY_DEV "/dev/ttyS"
#define BUFFER_LEN      1024    // sendfile()
#define E_CANNOT_OPEN   -0x10   // 串口不能打开
#define E_CANNOT_CLOSE  -0x11   // 串口不能关闭
#define E_SET_ATTR      -0x12   // 设置串口属性错误
#define E_CLOSED        -0x13
#define E_OPENED	-0x14
#define E_NODATA        -0x15
#define E_INVALID_BAUDRATE -0x01
#define E_GET_ERROR	-0x16   //取串口信号错误
#define E_SET_ERROR	-0x17
#define S_PROCESS	0x00    // 函数返回成功


static portinfo_t portinfo = 
{
    0,                          // print prompt after receiving
    2400,                       // baudrate: 115200
    8,                          // databit: 8
    0,                          // debug: off
    0,                          // echo: off
    1,                          // flow control: hardware
    2,                          // tty: COM1
    0,                          // parity: none
    1,                          // stopbit: 1
    0                           // reserved
};

/* tty.c */
INT8 tty_is_open();
int tty_open(const portinfo_t * p_portinfo,const char *);
void tty_close();
//读写控制
int tty_read(void *data, int datalength);       //读指定长度的数据
int tty_write(BYTE * data, int datalength);     //写指定长度的数据
int tty_set_read_sigon(void);   //信号读设置
int tty_signal_resume(void);    //控制线恢复
int tty_rts_request(void);      //信道请求
int tty_rts_cancel(void);       //信道释放
int tty_tcflush(int queue);
int tty_send_checking(void);    //串口有没有数据发送检测
int tty_get_signal(int *status);        //串口信号线控制
int tty_set_signal(int *status);

//串口指令操作
void tty_input(void);           //串口指令接收
int tty_output(BYTE * send_data, UINT32 len);   //串口指令发送




#define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2)
#define TIMEOUT_USEC 0

static int fd = -1;             // ttyS端口文件描述符
static struct termios termios_old, termios_new; //定义termios
static struct timeval tv_timeout;


static int tty_get_baudrate();
static char *tty_get_ptty(INT8 tty);
static int tty_set_attr(const portinfo_t * pportinfo);
static void tty_set_baudrate(int);
static void tty_set_databit(INT8 databit);
static void tty_set_flow_control(INT8 fctrl);
static void tty_set_parity_check(INT8 parity);
static void tty_set_stopbit(INT8 stopbit);
static void tty_sig_handler();

INT8 tty_is_open()
{
    return -1 == fd ? 0 : 1;    // fd == -1, return 0
}

/*
 * 参数   : portinfo_t* pportinfo;
 * 返回值 : fd 端口描述符、
 * 描述   : 打开特定波特率的端口
 */
int tty_open(const portinfo_t * pportinfo,const char *tty)
{
    char *ptty;
    int retval;


    pportinfo->tty = atoi(tty);

    ptty = tty_get_ptty(pportinfo->tty);

    if (tty_is_open()) {
        return (E_OPENED);
    }

    fd = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (-1 == fd) {
        fprintf(stderr, "cannot open port %s\n", ptty);
        return (E_CANNOT_OPEN);
    }
    	
    tcgetattr(fd, &termios_old);        // 存储旧的termios值

    // 0 on success, -1 on failure 
    retval = tty_set_attr(pportinfo);
    if (-1 == retval) {
        fprintf(stderr, "\nport %s cannot set baudrate at %d\n", ptty,
                pportinfo->baudrate);
        return (E_SET_ATTR);
    }
    
    return (0);
}

/*
 * 参数   : none 
 * 返回值 : none
 * 描述   : 关闭串口
 */
void tty_close()
{
    if (!tty_is_open()) {
        return;
    }
    tcsetattr(fd, TCSADRAIN, &termios_old);
    close(fd);
    fd = -1;
}

/*
 * 参数   : void *data, int datalength;
 * 返回值 : E_CLOSE   : 端口没有打开
 *	    E_NODATA  : 在指定时间内没有数据
 * 描述   : 从端口读数据
 */
int tty_read(void *data, int datalength)
{
    int retval = 0;
    fd_set fs_read;

    if (!tty_is_open()) {
        return (E_CLOSED);
    }

    FD_ZERO(&fs_read);
    FD_SET(fd, &fs_read);
    tv_timeout.tv_sec = TIMEOUT_SEC(datalength, tty_get_baudrate());
    tv_timeout.tv_usec = TIMEOUT_USEC;
    retval = select(fd + 1, &fs_read, NULL, NULL, &tv_timeout);
    if (retval) {

        return (read(fd, data, datalength));
    } else {
        return (E_NODATA);
    }
}

/*
 * 参数   : UINT8 *data, int datalength;
 * 返回值 : 所写的字节数
 * 描述   : 写数据到缓冲区
 */
int tty_write(BYTE * data, int datalength)
{
    int retval, len = 0, total_len = 0;
    fd_set fs_write;
    char tmp[50];
    int i=0;
    if (!tty_is_open()) {
            printf("-!tty_is_open\n");
        return (E_CLOSED);
    }

    FD_ZERO(&fs_write);
    FD_SET(fd, &fs_write);
    tv_timeout.tv_sec = TIMEOUT_SEC(datalength, tty_get_baudrate());
    tv_timeout.tv_usec = TIMEOUT_USEC;
    strncpy(tmp,"0123456789",10);            

    for (total_len = 0, len = 0; total_len < datalength;) {
        retval = select(fd + 1, NULL, &fs_write, NULL, &tv_timeout);
        if (retval) {
            
            len = write(fd, tmp,10);//&data[total_len],10);// datalength - total_len);
	  

            for(i=0;i<10;i++)
            {
                printf("write data :%c\n",tmp[i]);

            }
            if (len > 0) {
                total_len += len;
            }
        } else {
            tcflush(fd, TCOFLUSH);      // 刷新所有的输出数据 
            break;
        }
    }
    return (total_len);
}

/*
 * 参数   : void;
 * 返回值 : 
 * 描述   : 取串口波特率
 */
static int tty_get_baudrate()
{
    switch (cfgetospeed(&termios_new)) {
    case B0:
        return (0);
    case B50:
        return (50);
    case B75:
        return (75);
    case B110:
        return (110);
    case B134:
        return (134);
    case B150:
        return (150);
    case B200:
        return (200);
    case B300:
        return (300);
    case B600:
        return (600);
    case B1200:
        return (1200);
    case B2400:
        return (9600);
    case B9600:
        return (9600);
    case B19200:
        return (19200);
    case B38400:
        return (38400);
    case B57600:
        return (57600);
    case B115200:
        return (115200);
    default:
        return (E_INVALID_BAUDRATE);
    }
}

/*
 * 参数   : INT8 tty
 * 返回值 : 串口描述(ttyS0...);
 * 描述   : 取得串口的描述
 */
static char *tty_get_ptty(INT8 tty)
{
    char *ptty;
    if (0 == tty) {
        ptty = TTY_DEV "0";
    } else if (1 == tty) {
        ptty = TTY_DEV "1";
    } else if (2 == tty) {
        ptty = TTY_DEV "2";
    } else if (3 == tty) {
        ptty = TTY_DEV "3";
    } else if (4 == tty) {
        ptty = TTY_DEV "4";
    } else if (5 == tty) {
        ptty = TTY_DEV "5";
    } else if (6 == tty) {
        ptty = TTY_DEV "6";
    } else if (7 == tty) {
        ptty = TTY_DEV "7";
    } else {
        ptty = TTY_DEV "0";
    }
    return (ptty);
}

/*
 * 参数   : const portinfo_t* pportinfo;
 * 返回值 : 
 * 描述   : 设置端口的属性
 */
static int tty_set_attr(const portinfo_t * pportinfo)
{
    bzero(&termios_new, sizeof(termios_new));

    cfmakeraw(&termios_new);
   // tty_set_baudrate(pportinfo->baudrate);
    tty_set_baudrate(9600);
    termios_new.c_cflag |= CLOCAL | CREAD;
    tty_set_flow_control(pportinfo->fctrl);
    tty_set_databit(pportinfo->databit);
    tty_set_parity_check(pportinfo->parity);
    tty_set_stopbit(pportinfo->stopbit);
    termios_new.c_oflag &= ~OPOST;
    termios_new.c_cc[VTIME] = 1;        // unit: (1/10) second. 
    termios_new.c_cc[VMIN] = 1; // minimal characters for reading 
    tcflush(fd, TCIFLUSH);

    return (tcsetattr(fd, TCSANOW, &termios_new));
}

/*
 * 参数   : int baudrate;
 * 返回值 : 
 * 描述   : 设置串口的波特率
 */
static void tty_set_baudrate(int baudrate)
{
    if (115200<= baudrate) {
        termios_new.c_cflag = B115200;
    } else if (57600 <= baudrate) {
        termios_new.c_cflag = B57600;
    } else if (38400 <= baudrate) {
        termios_new.c_cflag = B38400;
    } else if (19200 <= baudrate) {
        termios_new.c_cflag = B19200;
    } else if (9600 <= baudrate) {
        termios_new.c_cflag = B9600;
    } else if (2400 <= baudrate) {
        termios_new.c_cflag = B2400;
    } else if (1200 <= baudrate) {
        termios_new.c_cflag = B1200;
    } else if (600 <= baudrate) {
        termios_new.c_cflag = B600;
    } else if (300 <= baudrate) {
        termios_new.c_cflag = B300;
    } else if (200 <= baudrate) {
        termios_new.c_cflag = B200;
    } else if (150 <= baudrate) {
        termios_new.c_cflag = B150;
    } else if (134 <= baudrate) {
        termios_new.c_cflag = B134;
    } else if (110 <= baudrate) {
        termios_new.c_cflag = B110;
    } else if (75 <= baudrate) {
        termios_new.c_cflag = B75;
    } else if (50 <= baudrate) {
        termios_new.c_cflag = B50;
    } else if (0 <= baudrate) {
        tty_close();
    }
}

/*
 * 参数   : INT8 databit;
 * 返回值 : 
 * 描述   : 数据位设置(Set databit)
 */
static void tty_set_databit(INT8 databit)
{
    termios_new.c_cflag &= ~CSIZE;
    if (7 == databit) {
        termios_new.c_cflag |= CS7;
    } else if (6 == databit) {
        termios_new.c_cflag |= CS6;
    } else if (5 == databit) {
        termios_new.c_cflag |= CS5;
    } else {
        termios_new.c_cflag |= CS8;
    }
}

/*
 * 参数   : int fctrl;
 *     		0: No Flow Control;
 *     		1: Hardware Control;
 *     		2: Software Control;
 * 返回值 : none
 * 描述   : 设置流控制
 */
static void tty_set_flow_control(INT8 fctrl)
{

#if 0
    if (0 == fctrl)             // no flow control  
    {
        termios_new.c_cflag &= ~CRTSCTS;
    } else if (1 == fctrl)      // hardware flow control
    {
        termios_new.c_cflag |= CRTSCTS;
    } else if (2 == fctrl)      // software flow control 
    {
        termios_new.c_iflag |= IXON | IXOFF | IXANY;
    }
    
#endif
            termios_new.c_cflag &= ~CRTSCTS;
}

/*
 * 参数   : INT8 parity;
 * 返回值 : 
 * 描述   : 设置奇偶校验
 */
static void tty_set_parity_check(INT8 parity)
{
    parity = parity % 3;
    if (2 == parity)            // even 
    {
        termios_new.c_cflag |= PARENB;
        termios_new.c_cflag &= ~PARODD;
    } else if (1 == parity)     // odd 
    {
        termios_new.c_cflag |= PARENB;
        termios_new.c_cflag |= ~PARODD;
    } else                      // no parity check 
    {
        termios_new.c_cflag &= ~PARENB;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -