JZ_uart.c 7.5 KB
/* Includes----------------------------------------------------*/
#include "JZ_uart.h"
#include "JZ_beurteilten.h"
/* Private constants-------------------------------------------*/

/* Private types-----------------------------------------------*/

/* Private values----------------------------------------------*/
JzSerData *ser;
pthread_mutex_t mutex;//互斥锁
/* Private functions declaration ---------------------------------------------*/

/* Exported functions definition ---------------------------------------------*/
/************************************
*串口初始化
*函数名:JzUartSet
*函数参数:
          @path:串口设备路径 
          @bitRate:串口波特率
*返回值:成功返回 0 错误返回-1
*函数作者:wzy
*************************************/
int JzUartInit(const char *path,int bitRate)
{     
    //串口结构体申请内存
    ser = (JzSerData *)malloc(sizeof(JzSerData));
    if(ser == NULL)
    {
        return -1;
    }
    ser->serFd = JzUartSet(path,bitRate);//设置串口参数
    //ser->dataBuf,0,
    memset(ser->dataBuf,0,sizeof(ser->dataBuf));
    ser->dataLen =0;

    //初始化互斥锁
    pthread_mutex_init(&mutex,NULL);
    //创建串口接收线程
    pthread_t thread;
    pthread_attr_t task_attr;
    pthread_attr_init(&task_attr);  //初始化线程属性
	pthread_attr_setdetachstate(&task_attr, PTHREAD_CREATE_DETACHED);      //设置线程分离属性
    // 创建线程
    int result = pthread_create(&thread, &task_attr, Recv_Task, (void *)(intptr_t)ser->serFd);
    if (result != 0) {
        printf("线程创建失败\n");
        return -1;
    }
    return 0;
}
/************************************
*串口设置
*函数名:JzUartSet
*函数参数: @path:串口设备路径 
          @bitRate:串口波特率
*返回值:
      成功返回 文件标识符   错误返回-1   
*函数作者:wzy
*************************************/
int JzUartSet(const char *path,int bitRate)
{   
    
    /*   进行串口参数设置  */
    termios_t *ter_s = malloc(sizeof(*ter_s));
    
   int serport1fd = open(path, O_RDWR | O_NOCTTY | O_NDELAY); // 不成为控制终端程序,不受其他程序输出输出影响
    if (serport1fd < 0)
    {
        printf("%s open faild\r\n", path);
        return -1;
    }
    
    bzero(ter_s, sizeof(*ter_s));

    ter_s->c_cflag |= CLOCAL | CREAD; // 激活本地连接与接受使能

    ter_s->c_cflag &= ~CSIZE; // 失能数据位屏蔽
    ter_s->c_cflag |= CS8;    // 8位数据位

    ter_s->c_cflag &= ~CSTOPB; // 1位停止位

    ter_s->c_cflag &= ~PARENB; // 无校验位

    ter_s->c_cc[VTIME] = 0;
    ter_s->c_cc[VMIN] = 0;

    /*1 VMIN> 0 && VTIME> 0
        VMIN为最少读取的字符数,当读取到一个字符后,会启动一个定时器,在定时器超时事前,如果已经读取到了VMIN个字符,则read返回VMIN个字符。如果在接收到VMIN个字符之前,定时器已经超时,则read返回已读取到的字符,注意这个定时器会在每次读取到一个字符后重新启用,即重新开始计时,而且是读取到第一个字节后才启用,也就是说超时的情况下,至少读取到一个字节数据。
        2 VMIN > 0 && VTIME== 0
        在只有读取到VMIN个字符时,read才返回,可能造成read被永久阻塞。
        3 VMIN == 0 && VTIME> 0
        和第一种情况稍有不同,在接收到一个字节时或者定时器超时时,read返回。如果是超时这种情况,read返回值是0。
        4 VMIN == 0 && VTIME== 0
        这种情况下read总是立即就返回,即不会被阻塞。----by 解释粘贴自博客园
    */
   //3、设置比特率
	switch (bitRate)
	{
        case 115200:
            cfsetispeed(ter_s, B115200);// 设置输入波特率
            cfsetospeed(ter_s, B115200);// 设置输出波特率
            break;
        case 230400:
            cfsetispeed(ter_s, B230400);
            cfsetospeed(ter_s, B230400);
            break;
        case 460800:
            cfsetispeed(ter_s, B460800);
            cfsetospeed(ter_s, B460800);
            break;
        case 921600:
            cfsetispeed(ter_s, B921600);
            cfsetospeed(ter_s, B921600);
            break;
        case 1000000:
            cfsetispeed(ter_s, B1000000);
            cfsetospeed(ter_s, B1000000);
            break;
		default:
            printf("bitRate error\n");
			return -1;           
			break;
	}

    tcflush(serport1fd, TCIFLUSH); // 刷清未处理的输入和/或输出

    if (tcsetattr(serport1fd, TCSANOW, ter_s) != 0)
    {
        printf("com set error!\r\n");
    }
    
    return serport1fd;

}
/************************************
   串口发送任务函数   
*************************************/
static void *send_task(void *arg)
{    
   pthread_mutex_lock(&mutex); 
   JzSerData * sendser = (JzSerData *)arg;
   
    int ret = write(ser->serFd, ser->dataBuf,ser->dataLen);
    if (ret <= 0)//错误处理
    {               
        printf("send error!\r\n");       
    }
   pthread_mutex_unlock(&mutex);//释放锁
   // tcflush(ser->serFd, TCOFLUSH);//清除输出缓冲区
      
}
// int uart_send(uint8_t *dataBuf,int dataLen)
// {          
//     //pthread_mutex_lock(&mutex);//获取锁
//     int ret = write(ser->serFd, dataBuf,dataLen);
//     if (ret <= 0)//错误处理
//     {               
//         printf("send error!\r\n");
//         return -1;       
//     }
//    // pthread_mutex_unlock(&mutex);//释放锁
//     tcflush(ser->serFd, TCOFLUSH);//清除输出缓冲区
// }      
/************************************
*串口发送函数
*函数名:uart_send
*函数参数:
        @dataBuf:发送的数据
        @dataLen:发送数据长度
*返回值:无
*函数作者:wzy
*************************************/
int uart_send(uint8_t *dataBuf,int dataLen)
{             
   
    pthread_t thread;
    pthread_attr_t task_attr;
    pthread_attr_init(&task_attr);  //初始化线程属性
	pthread_attr_setdetachstate(&task_attr, PTHREAD_CREATE_DETACHED);      //设置线程分离属性
        
    memcpy(ser->dataBuf,dataBuf,dataLen);
    ser->dataLen = dataLen;
    //  for(int i=0;i<dataLen;i++)
    //     {
    //         printf("%02x ",dataBuf[i]);
    //     }
    //     printf("\n"); 
    // 创建线程
    int result = pthread_create(&thread, &task_attr, send_task,(void *)ser);
    if (result != 0) {
        printf("线程创建失败\n");
        return -1;
    }
    return 0;
}

/************************************
   串口接收任务函数   
*************************************/
static void *Recv_Task(void *arg)
{       
  int ret = 0;    
  char recvBuf[256];
  char frames[4][32];
  int index = 0;
  int currentFrame = 0;
  int serFd = (int)(intptr_t)arg;
 
  while (1)
  {  
    pthread_mutex_lock(&mutex);//获取锁  
    ret = read(serFd,recvBuf, 256);
    
    pthread_mutex_unlock(&mutex);//释放锁
    if (ret > 0)
    {   //分开数据帧
      
          for(int j=0;j<ret;j++)
         {
           frames[currentFrame][index++] = recvBuf[j];
         
           if(recvBuf[j-1] == 0x00 && recvBuf[j] == 0x23)
           {            
              Received_Content_Determinatio(frames[currentFrame],index);//判断内容 
              currentFrame++;//下一帧
              index = 0;  
           }           
         }             
        memset(recvBuf, '\0', 256);//清空缓冲区      
        memset(frames, '\0', 128);
        // tcflush(serFd, TCIFLUSH);//清除输入缓冲区
    }  
       currentFrame = 0;  
       usleep(100);
  }
}