国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Linux > 正文

LINUX線程初探

2024-06-28 13:23:32
字體:
來源:轉載
供稿:網友
linux線程初探 Posted on 2014-10-27 14:56 xiabodan 閱讀(...) 評論(...) 編輯 收藏

LINUX程序設計最重要的當然是進程與線程。本文主要以uart程序結合鍵盤輸入控制uart的傳輸。

硬件平臺:樹莓派B+

軟件平臺:raspberry

需要工具:USB轉TTL(PL2303)+GCC

程序設計

首先聲明,在LINUX中已經集成了PL2303的驅動,不用裝驅動。

串口簡介

串行口是計算機一種常用的接口,具有連接線少,通訊簡單,得到廣泛的使用。常用的串口是 RS-232-C 接口(又稱 EIA RS-232-C)它是在 1970 年由美國電子工業協會(EIA)聯合貝爾系統、 調制解調器廠家及計算機終端生產廠家共同制定的用于串行通訊的標準。它的全名是"數據終端設備(DTE)和數據通訊設備(DCE)之間串行二進制數據交換接口技術標準"該標準規定采用一個 25 個腳的 DB25 連接器,對連接器的每個引腳的信號內容加以規定,還對各種信號的電平加以規定。傳輸距離在碼元畸變小于 4% 的情況下,傳輸電纜長度應為 50 英尺。

Linux 操作系統從一開始就對串行口提供了很好的支持,本文就 Linux 下的串行口通訊編程進行簡單的介紹,如果要非常深入了解,建議看看本文所參考的《Serial PRogramming Guide for POSIX Operating Systems》

串口操作

串口操作需要的頭文件

#include     <stdio.h>      /*標準輸入輸出定義*/#include     <stdlib.h>     /*標準函數庫定義*/#include     <unistd.h>     /*Unix 標準函數定義*/#include     <sys/types.h>  #include     <sys/stat.h>   #include     <fcntl.h>      /*文件控制定義*/#include     <termios.h>    /*PPSIX 終端控制定義*/#include     <errno.h>      /*錯誤號定義*/
View Code

打開串口

在 Linux 下串口文件是位于 /dev 下的

串口一 為 /dev/ttyUSB0

串口二 為 /dev/ttyUSB1

打開串口是通過使用標準的文件打開函數操作:

int fd;/*以讀寫方式打開串口*/fd = open( "/dev/ttyS0", O_RDWR);if (-1 == fd){ /* 不能打開串口一*/ perror(" 提示錯誤!");}
View Code

設置串口

最基本的設置串口包括波特率設置,效驗位和停止位設置。

串口的設置主要是設置 struct termios 結構體的各成員值。

struct termio{    unsigned short  c_iflag;    /* 輸入模式標志 */        unsigned short  c_oflag;        /* 輸出模式標志 */        unsigned short  c_cflag;        /* 控制模式標志*/        unsigned short  c_lflag;        /* local mode flags */        unsigned char  c_line;            /* line discipline */        unsigned char  c_cc[NCC];    /* control characters */};
View Code

設置這個結構體很復雜,我這里就只說說常見的一些設置:

波特率設置

下面是修改波特率的代碼:

struct  termios Opt;tcgetattr(fd, &Opt);cfsetispeed(&Opt,B19200);     /*設置為19200Bps*/cfsetospeed(&Opt,B19200);tcsetattr(fd,TCANOW,&Opt);
View Code

設置波特率的例子函數:

/***@brief  設置串口通信速率*@param  fd     類型 int  打開串口的文件句柄*@param  speed  類型 int  串口速度*@return  void*/int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,          B38400, B19200, B9600, B4800, B2400, B1200, B300, };int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300, 38400,            19200,  9600, 4800, 2400, 1200,  300, };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(fd1, TCSANOW, &Opt);        if  (status != 0) {                perror("tcsetattr fd1");          return;           }          tcflush(fd,TCIOFLUSH);       }    }}

效驗位和停止位的設置:

無效驗8位Option.c_cflag &= ~PARENB; Option.c_cflag &= ~CSTOPB; Option.c_cflag &= ~CSIZE; Option.c_cflag |= ~CS8;
奇效驗(Odd)7位Option.c_cflag |= ~PARENB; Option.c_cflag &= ~PARODD; Option.c_cflag &= ~CSTOPB; Option.c_cflag &= ~CSIZE; Option.c_cflag |= ~CS7;
偶效驗(Even)7位Option.c_cflag &= ~PARENB; Option.c_cflag |= ~PARODD; Option.c_cflag &= ~CSTOPB; Option.c_cflag &= ~CSIZE; Option.c_cflag |= ~CS7;
Space效驗7位Option.c_cflag &= ~PARENB; Option.c_cflag &= ~CSTOPB; Option.c_cflag &= &~CSIZE; Option.c_cflag |= CS8;

設置效驗的函數:

/***@brief   設置串口數據位,停止位和效驗位*@param  fd     類型  int  打開的串口文件句柄*@param  databits 類型  int 數據位   取值 為 7 或者8*@param  stopbits 類型  int 停止位   取值為 1 或者2*@param  parity  類型  int  效驗類型 取值為N,E,O,,S*/int set_Parity(int fd,int databits,int stopbits,int parity){     struct termios options;     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);  }
set_Parity

需要注意的是:

如果不是開發終端之類的,只是串口傳輸數據,而不需要串口來處理,那么使用原始模式(Raw Mode)方式來通訊,設置方式如下:

options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);  /*Input*/options.c_oflag  &= ~OPOST;   /*Output*/

讀寫串口

設置好串口之后,讀寫串口就很容易了,把串口當作文件讀寫就是。

  • 發送數據
    char  buffer[1024];int    Length;int    nByte;nByte = write(fd, buffer ,Length)
  • 讀取串口數據

    使用文件操作read函數讀取,如果設置為原始模式(Raw Mode)傳輸數據,那么read函數返回的字符數是實際串口收到的字符數。

    可以使用操作文件的函數來實現異步讀取,如fcntl,或者select等來操作。

    char  buff[1024];int    Len;int  readByte = read(fd,buff,Len);
編程例子:
    int fd,fd1;    int flag11;    int nread;    char buff[512]={};    char *dev ="/dev/ttyUSB0";        /*打開串口0*/    fd = OpenDev(dev);    //open uart dev    if (fd>0)    {            set_speed(fd,57600); //set uart baud speed         printf("success Open Serial Port/n");    }    else    {        printf("Can't Open Serial Port!/n");        exit(0);    }    if (set_Parity(fd,8,1,'N')== FALSE)//set uart odd/even fomat     {        printf("Set Parity Error/n");        exit(1);    }    printf("Set Parity success/n");    printf("open keyboard  success/n");        /*向串口中寫數據*/        write(fd, "1,SVS,2,200/r/n", 16);          write(fd, "1,SVS,1,200/r/n", 16);               printf ("**********Now into while(1)**********/n");         while(1)         {                /*循環讀取其他設備傳入的數據*/           while((nread = read(fd,buff,512))>0)           {                      //write(fd, "I am writo back", 16);                  printf("/nLen %d/n",nread);                  buff[nread+1]='/0';                  printf("/n%s",buff);            }          }       

關閉串口

關閉串口就是關閉文件。

close(fd);
scanf線程

由于scanf是阻塞程序,也就是在程序中出現了scanf的地方那么就要等待用戶的輸入,而不能執行其他的函數,如果我們加入線程處理,那么可以很好的解決這個問題。

線程處理函數

/*線程執行函數*/void *create(void *arg){    unsigned char *a=0;    char pet[20];//字符串    while(1)    {        printf("please input the pet/n");        scanf("%s",pet);        printf("thread : pet = %s/n",pet);    }       return (void *)0;}

main函數

int main( int argc, char** argv ){    pthread_t tidp;        int error;        struct menber b={0};    printf("I am start /n");        unsigned char a;    /*創建線程并運行線程執行函數*/    error = pthread_create(&tidp, NULL, create, (void *)&b);            if( error )            {                printf("phread is not created.../n");                return -1;            }        while(1)    {        /*阻塞等待線程退出*/            //pthread_join(tidp, NULL);        printf("main function/n"); //住函數運行,不影響線程        sleep(1);    }    return 0;}

參考

  

    LINUX下串口編程入門:http://www.ibm.com/developerworks/cn/linux/l-serials/index.html

    

    APUE第11章  

  


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 丰镇市| 巩留县| 镶黄旗| 大姚县| 开鲁县| 满城县| 甘谷县| 达孜县| 鹤壁市| 体育| 塔河县| 田东县| 普陀区| 比如县| 财经| 隆林| 高阳县| 红河县| 宁陕县| 桐梓县| 老河口市| 韶关市| 庄河市| 略阳县| 郯城县| 承德县| 简阳市| 芮城县| 肇庆市| 平果县| 永宁县| 克山县| 公安县| 福安市| 宜丰县| 明水县| 黔江区| 嘉黎县| 称多县| 博湖县| 紫阳县|