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;
}