串口uart读取时间,gpio脉冲触发epoll同步系统时间

uart串口操作头文件

#include <stdio.h>      /*标准输入输出定义*/
#include <stdlib.h>     /*标准函数库定义*/
#include <unistd.h>     /*Unix 标准函数定义*/
#include <sys/types.h>  /*数据类型,比如一些XXX_t*/
#include <sys/stat.h>   /*定义了一些返回值的结构*/
#include <fcntl.h>      /*文件控制定义*/
#include <termios.h>    /*PPSIX 终端控制定义*/
#include <errno.h>      /*错误号定义*/
#include <string.h>

int uart_option(char *dev_path, int speed, int option, char *buff, int len);

uart串口操作

#include "uart_sync_rtc.h"

#define FALSE  -1
#define TRUE   0


/*********************************************************************/
static int OpenDev(char *Dev)
{
    int fd = open(Dev, O_RDWR | O_NOCTTY);         //| O_NOCTTY | O_NDELAY    
    if (-1 == fd)   
    {           
        perror("Can't Open Serial Port");
        return -1;      
    }   
    else    
        return fd;
}


int speed_arr[] = {B38400, B19200, B115200, B9600, B4800, B2400, B1200, B300,
                    B38400, B19200, B115200, B9600, B4800, B2400, B1200, B300,};
int name_arr[] = {38400,  19200,  115200, 9600,  4800,  2400,  1200,  300, 38400,  
                    19200,  115200, 9600, 4800, 2400, 1200,  300,};
/**
*@brief  设置串口通信速率
*@param  fd     类型 int  打开串口的文件句柄
*@param  speed  类型 int  串口速度
*@return  void
*/
void set_speed(int fd, int speed)
{
    int   i; 
    int   status; 
    struct termios   Opt;
    tcgetattr(fd, &Opt); 
    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++) { 
        if  (speed == name_arr[i]) {     
            tcflush(fd, TCIOFLUSH);     
            cfsetispeed(&Opt, speed_arr[i]);  
            cfsetospeed(&Opt, speed_arr[i]);   
            status = tcsetattr(fd, TCSANOW, &Opt);  
            if  (status != 0) {        
                perror("tcsetattr fd1");  
                return;     
            }    
            tcflush(fd,TCIOFLUSH);   
        }  
    }
}


/**
*@brief   设置串口数据位,停止位和效验位
*@param  fd     类型  int  打开的串口文件句柄
*@param  databits 类型  int 数据位   取值 为 7 或者8
*@param  stopbits 类型  int 停止位   取值为 1 或者2
*@param  parity  类型  int  效验类型 取值为N,E,O,,S
*/
static int set_Parity(int fd, int databits, int stopbits, int parity)
{ 
    struct termios options = {0}; 
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/
    options.c_oflag &= ~OPOST;   /*Output*/
    if  ( tcgetattr( fd,&options) !=  0) { 
        perror("SetupSerial 1");     
        return(FALSE);  
    }
    options.c_cflag &= ~CSIZE; 
    switch (databits) /*设置数据位数*/
    {   
    case 7:     
        options.c_cflag |= CS7; 
        break;
    case 8:     
        options.c_cflag |= CS8;
        break;   
    default:    
        fprintf(stderr, "Unsupported data size/n"); return (FALSE);  
    }
    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); /* 设置为奇效验*/  
            options.c_iflag |= INPCK;             /* Disnable parity checking */ 
            break;  
        case 'e':  
        case 'E':   
            options.c_cflag |= PARENB;     /* Enable parity */    
            options.c_cflag &= ~PARODD;   /* 转换为偶效验*/     
            options.c_iflag |= INPCK;       /* Disnable parity checking */
            break;
        case 'S': 
        case 's':  /*as no parity*/   
            options.c_cflag &= ~PARENB;
            options.c_cflag &= ~CSTOPB;break;  
        default:   
            fprintf(stderr,"Unsupported parity/n");    
            return (FALSE);  
    }  
    /* 设置停止位*/  
    switch (stopbits)
    {   
        case 1:    
            options.c_cflag &= ~CSTOPB;  
            break;  
        case 2:    
            options.c_cflag |= CSTOPB;  
           break;
        default:    
             fprintf(stderr,"Unsupported stop bits/n");  
             return (FALSE); 
    } 
    /* Set input parity option */ 
    if (parity != 'n')   
        options.c_iflag |= INPCK; 
    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)   
    { 
        perror("SetupSerial 3");   
        return (FALSE);  
    } 
    return (TRUE);  
}


/**
*@brief  串口操作函數
*@param  dev_path 类型 char * 设备地址
*@param  speed 类型  int 波特率   
*@param  option 类型  int 读/写操作   读为1,写为2
*@param  buff 类型 char * 读写字符串缓存区
*@param  len  类型  int  buff长度
*/
int uart_option(char *dev_path, int speed, int option, char *buff, int len)
{
    int fd;
    int nread;
    fd = OpenDev(dev_path);
    if (fd == -1)
        return -1;
    set_speed(fd,speed);
    /*if (set_Parity(fd,8,1,'N') == FALSE)  
    {
        printf("Set Parity Error/n");
        return -1;
    }*/

    if (option == 1)
    {

        if ((nread = read(fd, buff, len))>0)
        { 
            //printf("/nLen %d/n",nread); 
            buff[nread + 1] = 0;   
            //printf( "/n%s", buff);   
        }

        close(fd); 
        return nread;
    }
    else if (option == 2)
    {
        printf("------buff--->%s<--------/n",buff);
        int num = strlen(buff);
        printf("--------num---->%d<--------------/n",num);
        if (num > 0)
        {
            printf("Wirte num not NULL./r/n");
            nread = write(fd, buff, num);
            if (nread == -1)
            {
                printf("Wirte sbuf error./n");
                return -1;
            }
            printf("--nread---->%d<-----------/n",nread);
        }
        close(fd); 
    }
    
    return 0;
}

gpio获取脉冲信号,并同步系统时间

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include "uart_sync_rtc.h"
#include <time.h>    
#include <pthread.h>

#define GPIO1_26_DEV_NUM 290

int debug_mode = 0;

#define DEBUG_MSG(fmt, arg ...) \
    if (debug_mode) printf("[DEBUG] system_rtc_sync " fmt ,  ##arg )
    

enum GPIO_EDGE_MODE{
    GPIO_EDGE_MODE_NONE=0,
    GPIO_EDGE_MODE_RISING,
    GPIO_EDGE_MODE_FALLING,
    GPIO_EDGE_MODE_BOTH,
};

enum GPIO_DIRECTION_MODE{
    GPIO_DIRECTION_MODE_IN=0,
    GPIO_DIRECTION_MODE_OUT,
};
 
//函数声明
static int gpio_export(int pin);
static int gpio_unexport(int pin);
static int gpio_direction(int pin, int dir);
static int gpio_write(int pin, int value);
static int gpio_read(int pin);
static int gpio_edge(int pin, int edge);
 
 
static int gpio_export(int pin)  
{  
    char buffer[64];  
    int len;  
    int fd;  
  
    fd = open("/sys/class/gpio/export", O_WRONLY);  
    if (fd < 0) 
    {  
        DEBUG_MSG("Failed to open export for writing!\n");  
        return(-1);  
    }  
  
    len = snprintf(buffer, sizeof(buffer), "%d", pin);  
    DEBUG_MSG("%s,%d,%d\n",buffer,(int)sizeof(buffer),len);
    if (write(fd, buffer, len) < 0) 
    {  
        DEBUG_MSG("Failed to export gpio!");  
        return -1;  
    }  
     
    close(fd);  
    return 0;  
}  


static int gpio_unexport(int pin)  
{  
    char buffer[64];  
    int len;  
    int fd;  
  
    fd = open("/sys/class/gpio/unexport", O_WRONLY);  
    if (fd < 0) 
    {  
        DEBUG_MSG("Failed to open unexport for writing!\n");  
        return -1;  
    }  
  
    len = snprintf(buffer, sizeof(buffer), "%d", pin);  
    if (write(fd, buffer, len) < 0) 
    {  
        DEBUG_MSG("Failed to unexport gpio!");  
        return -1;  
    }  
     
    close(fd);  
    return 0;  
} 


//dir: 0-->IN, 1-->OUT
static int gpio_direction(int pin, int dir)  
{  
    static const char dir_str[] = "in\0out";  
    char path[64];  
    int fd;  
  
    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);  
    fd = open(path, O_WRONLY);  
    if (fd < 0) 
    {  
        DEBUG_MSG("Failed to open gpio direction for writing!\n");  
        return -1;  
    }  
  
    if (write(fd, &dir_str[dir == GPIO_DIRECTION_MODE_IN ? 0 : 3], dir == GPIO_DIRECTION_MODE_IN ? 2 : 3) < 0) 
    {  
        DEBUG_MSG("Failed to set direction!\n");  
        return -1;  
    }  
  
    close(fd);  
    return 0;  
}  


//value: 0-->LOW, 1-->HIGH
static int gpio_write(int pin, int value)  
{  
    static const char values_str[] = "01";  
    char path[64];  
    int fd;  
  
    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);  
    fd = open(path, O_WRONLY);  
    if (fd < 0) 
    {  
        DEBUG_MSG("Failed to open gpio value for writing!\n");  
        return -1;  
    }  
  
    if (write(fd, &values_str[value == 0 ? 0 : 1], 1) < 0) 
    {  
        DEBUG_MSG("Failed to write value!\n");  
        return -1;  
    }  
  
    close(fd);  
    return 0;  
}


static int gpio_read(int pin)  
{  
    char path[64];  
    char value_str[3];  
    int fd;  
  
    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);  
    fd = open(path, O_RDONLY);  
    if (fd < 0) 
    {  
        DEBUG_MSG("Failed to open gpio value for reading!\n");  
        return -1;  
    }  
  
    if (read(fd, value_str, 3) < 0)
    {  
        DEBUG_MSG("Failed to read value!\n");  
        return -1;  
    }  
  
    close(fd);  
    return (atoi(value_str));
}  


// none表示引脚为输入,不是中断引脚
// rising表示引脚为中断输入,上升沿触发
// falling表示引脚为中断输入,下降沿触发
// both表示引脚为中断输入,边沿触发
// 0-->none, 1-->rising, 2-->falling, 3-->both
static int gpio_edge(int pin, int edge)
{
    const char dir_str[] = "none\0rising\0falling\0both"; 
    char ptr;
    char path[64];  
    int fd; 

    switch(edge)
    {
        case GPIO_EDGE_MODE_NONE:
            ptr = 0;
            break;
        case GPIO_EDGE_MODE_RISING:
            ptr = 5;
            break;
        case GPIO_EDGE_MODE_FALLING:
            ptr = 12;
            break;
        case GPIO_EDGE_MODE_BOTH:
            ptr = 20;
            break;
        default:
            ptr = 0;
    } 
  
    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);  
    fd = open(path, O_WRONLY);  
    if (fd < 0) 
    {  
        DEBUG_MSG("Failed to open gpio edge for writing!\n");  
        return -1;  
    }  
  
    if (write(fd, &dir_str[ptr], strlen(&dir_str[ptr])) < 0) 
    {  
        DEBUG_MSG("Failed to set edge!\n");  
        return -1;  
    }  
  
    close(fd);  
    return 0;  
}

typedef struct st_uart_sync_time_data{
    time_t timesec;
    int pre_flag;
}uart_sync_time_data;

uart_sync_time_data sync_data = {0};

pthread_rwlock_t rwlock;

void *uart_thread(void){
    int gpio_fd, ret;
    char uart_buff[64];
    struct tm tm_time;
    struct timeval stime;
    while(1)
    {
        ret = uart_option("/dev/ttyS4", 115200, 1,  uart_buff, 64);
        if (ret > 0){
            DEBUG_MSG("rtc_time: %s\n", uart_buff);
            strptime(uart_buff, "UTC:%Y-%m-%dT%H:%M:%SZ", &tm_time);
            pthread_rwlock_wrlock(&rwlock);
            DEBUG_MSG("write sync_data\n");
            sync_data.timesec = mktime(&tm_time);
            sync_data.pre_flag = 1;
            pthread_rwlock_unlock(&rwlock);

        }
        usleep(100000);
    }
}

//GPIO1_26
int main(int argc, char ** argv)  
{  
    int gpio_fd, ret;
    char buff[10];
    int len;
    struct tm tm_time;
    struct timeval stime;
    pthread_t pthid;
    struct epoll_event evd;
    struct epoll_event * events;
    int epollfd;

    if (argc == 2){
        debug_mode = atoi(argv[1]);
    }

    //p1_26 init
    gpio_unexport(GPIO1_26_DEV_NUM);
    gpio_export(GPIO1_26_DEV_NUM);
    gpio_direction(GPIO1_26_DEV_NUM, GPIO_DIRECTION_MODE_IN);//input in
    gpio_edge(GPIO1_26_DEV_NUM, GPIO_EDGE_MODE_RISING);
    gpio_fd = open("/sys/class/gpio/gpio290/value",O_RDWR|O_NOCTTY|O_NDELAY);
    if (gpio_fd < 0)
    {
        DEBUG_MSG("Failed to open value!\n");  
        return -1;  
    }

    epollfd = epoll_create(10);

    events = calloc (10, sizeof(struct epoll_event));
    evd.data.fd = gpio_fd;  //fd 即为open /sys/class/gpio/gpioN/value返回的句柄
    evd.events = EPOLLPRI;
    epoll_ctl(epollfd,EPOLL_CTL_ADD,gpio_fd,&evd); 

    pthread_rwlock_init(&rwlock,NULL);
    ret = pthread_create(&pthid, NULL, (void*)uart_thread, NULL);
    if (ret == -1)
        return ret;
    DEBUG_MSG("uart thread id: %d\n", pthid);  

    while (1) {
        int n = epoll_wait(epollfd,events,10,-1);
        for (int i = 0;i < n;i++) {
            if (events[i].events & EPOLLPRI) {
                memset(buff,0x00,sizeof(buff));
                read(events[i].data.fd,buff,sizeof(buff));
                lseek(events[i].data.fd,0,SEEK_SET);
                DEBUG_MSG("read buff\n");
            
                pthread_rwlock_rdlock(&rwlock);
                DEBUG_MSG("read sync_data\n");
                if (sync_data.pre_flag)
                {
                    stime.tv_sec = sync_data.timesec + 1;
                    stime.tv_usec = 0;
                    settimeofday(&stime, NULL);
                    DEBUG_MSG("set time sync\n");
                    sync_data.pre_flag = 0;
                }
                pthread_rwlock_unlock(&rwlock);
            }
        }
        usleep(100);
    }

    DEBUG_MSG("wait thread\n");
    pthread_join(pthid, NULL);
    pthread_rwlock_destroy(&rwlock);
    return 0;
}
上一篇:【操作系统】I/O多路复用 select poll epoll


下一篇:linux定时备份mysql数据库