본문 바로가기
코스웨어/16년 스마트컨트롤러

20160331_김도관_업무일지_C언어 기초및 라즈베리파이 시리얼통신_Canonical

by 알 수 없는 사용자 2016. 4. 5.
728x90
반응형

C언어 기초


LocalVariable.c


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
 
int SimpleFuncOne(void)
{
    int num = 10;
    num++;
    printf("SimpleFuncOne num: %d \n", num);
    return 0;
}
 
int SimpleFuncTwo(void)
{
    int num1=20;
    int num2=30;
    num1++;
    num2--;
    printf("num1 & num2: %d %d \n", num1, num2);
    return 0;
}
 
int main(void)
{
    int num = 17;
    SimpleFuncOne();
    SimpleFuncTwo();
    printf("main num : %d \n", num);
    return 0;
}
cs

지역변수 num 이 현재 2개가 있으나 

각각 함수내에서만 존재하는 지역변수 이므로...

함수를 벗어나면 영향을 끼치지 않음


그래서 26번째줄의 num은 17의 값을 가지고

SimpleFunOne은 내부의 num값 10으로 값을 증가해서 11의 값을 출력시킴


LocalValHideval.c


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
int main()
{
    int num = 1;
    
    if(num == 1)
    {
        int num = 7;
        num+=10;
        printf("if문 내 지역변수 num: %d \n", num);
        printf("if문 내 지역변수 num주소: %p \n", &num);
 
    }
    printf("main 함수 내 지역변수 num: %d \n",num);
    printf("main 함수 내 지역변수 num주소: %p \n", &num);
    return 0;
}
 
 
cs


if문 내의 지역변수와 외부의 지역변수는 각각 다른 메모리 주소를 가지고 있는것을 볼수있음



리눅스


장치 폴더 구조


유닉스및 리눅스는 장치를 각각의 파일로 취급

파일개념으로 접근하여 제어함


/dev 에 각각 장치 설정 파일들이 들어있음


/dev/ram 메모리

/dev/std 모니터 접근 화면출력

/dev/tty 터미널 접속 파일


man 페이지 : 명령어 메뉴얼을 확인할수있는 메뉴얼

사용방법 : man 해당명령어 

ex) man  vi 




POSIX(Portable Operating System Interface)

POSIX[포직스]는 유닉스 운영체계에 기반을 두고 있는 일련의 표준 운영체계 인터페이스이다. 표준화에 관한 필요성은, 컴퓨터를 사용하고 있는 기업들이 다시 코딩하지 않고서도 다른 컴퓨터 회사가 만든 컴퓨터 시스템에도 운영할 수 있도록, 호환성이 있는 프로그램을 개발하기 원하는 데에서 기인함


Canonical Mode Input Processing ( 특정행위시에만 값을 반환 )

흔히 정규모드라고 하며 기본적으로 라인단위로 입출력을 처리. 여기에서 말하는 라인의 개념은 우리들이 에디터에서 작업할때의 라인과 같은 개념으로 '\n' 혹은 EOF(End-Of-File) 를 만날때까지의 문자열을 말한다. 보통 사용자와 컴퓨터와 대화하기 위한 입출력은 정규모드 상태에서 행해진다. 이상태에서는 문자열 입력후 Enter 키를 눌러야 리턴이 됨. (혹은 Ctrl+d 를 눌러서 EOF 를 발생시킬경우)

또한 정규 방식에서는 ERASE와 KILL 문자등이 허용된다. 정규방식 자체가 라인단위 입출력작동임으로 당연히 Erase, kill 문자를 사용할수 있을것이다.

기본적으로 터미널은 정규모드로 시작됨


NonCanonical Mode Input Processing( 실시간 값을 반환 )

비정규모드. 정규모드가 라인단위로 입출력을 처리하는 것과 달리 비정규모드는 한바이트씩 처리. 

한바이트씩 처리하게 됨으로 정규모드에서 가능했던 여러가지 특수문자들(ERASE, KILL, EOF, NL, CR)을 사용할수 없게 됨 

예제 echo_off.c 가 비정규모드로 작동하는 프로그램인데, delete 키등이 먹지 않음을 알수 있다. 

비정규모드에서는 ERASE 문자가 사용되지 않기 때문이다. echo_off.c 를 비정규 모드로 작성한 이유는 정규모드로 할경우 개행문자 '\n' 이 입력되기 전까지는 리턴되지 않음으로 바이트단위로 리턴하도록 하기 위해서이다. 위 예제코드에서 new_settings.c_lflag &= (~ICANON); 을 주석처리 한다음에 실행시키면 엔터키를 입력하기 전까지는 화면에 "*" 이 출력되지 않음을 알수 있을것이다. 대신 Delete 와 같은 몇몇 특수문자의 전달이 가능함을 알수 있다.



라즈베리파이


시리얼 통신 RX / TX


라즈베리파이 GPIO 핀 배열


UART RX/TX통신을 위해 8번(TX)과 10번(RX)핀을 사용 



termios 각각 터미널 속성값 


표 1. 터미널 속성값 - c_iflag

설명터미널 입력과 관련된 제어를 한다. 입력제어 값들은 모드 on 되어있는 상태이다.
IGNBRKbreak 컨디션을 무시한다. break 컨디션은 연속된 0의 값을 가지는 비트로 정의된다. 만약 IGNBRK 가 on 되어 있고 입력데이타에 break 컨디션이 전달된다면 무시하게 된다.
BRKINT이것은 break 컨디션 상에서 SIGINT 를 가로채기 위해서 사용된다. 만약 IGNBRK 가 off 되어있고, BRKINT가 세팅되어 있는 상태에서 break 컨디션이 입력된다면 이것은 출력쿠에 쌓이게 된다. 만약 터미널이 foreground process 상태로 돌고 있는 도중이라면, SIGINT 신호를 발생시키게 된다.
IGNPARparity 에러무시한다.
INPCKparity 체크를 실시한다.
ISTRIP만약 이 플레그를 on 시키면, 유효한 입력 문자를 처음 7bit 로 세팅하게 된다. 그렇지 않을경우 8bit 입력으로 처리한다.
INLCRNL 문자(new-line)를 CR(carriage return) 문자로 대체시킨다. 만약 이 플레그가 on 된다면, NL 문자는 CR 문자로 변경된다.
IGNCRCR 문자를 무시한다. on 될경우 입력되는 CR 문자를 무시한다. (읽지 않는다)
ICRNLCR 문자를 NL 문자로 대체시킨다. IGNCR 이 on 되어 있지 않은 상태에서 ICRNL이 on 되어 있을경우 받은 CR 을 NL 로 변경한다.
IXONstart 와 stop 출력제어를 활성화 한다. 만약 플레그가 on 인 상태에서 STOP 캐릭터를 받았다면 출력을 멈추게 된다. 그러다가 START 캐릭터를 받게 되면 다시 출력을 시작하게 된다. 이것은 flow-control(흐름제어)를 위한 용도로 사용되며, 실제 STOP, START 캐릭터를 읽어들이지는 않는다. 만약 플레그가 off 상태라면 STOP, START 캐릭터를 읽어들인다.
IXOFF입력제어를 위해서 start 와 stop 를 활성화 한다. 만약에 플레그가 on 으로 되어있다면 시스템은 입력큐가 가득 찼을때 STOP 캐릭터를 전송한다. 그리고나서 입력큐에 있는 데이타를 모두 읽었다면 START 캐릭터를 전송한다. IXON과 함께 흐름제어를 위해서 사용된다.
IXANY어떤 문자에 대해서라도 출력을 한다. 이 플레그가 on 이라면 입력된 어떤 문자라도 출력을 시작 하게 된다.
IMAXBEL만약 입력스트림이 overflows 될경우 ASCII BEL 을 반향한다.


표 2. 터미널 속성값 - c_iflag

설명출력을 어떻게 다룰지에 관한 설정을한다. 기본설정은 모든 비트에 대해서 on(1) 의 상태이다.
  
OPOSTPost-process output 모드. 만약 이 플레그가 off 상태라면 문자는 변화없이 전달된다. 그렇지 않고 on 이라면, 뒤에 오는 flag 에 의해서 변경될수 있다.
OLCUC이 플레그가 on 되어 있을경우 영문소문자 는 영문대문자로 치환되어서 전달된다.
ONLCR이 플레그가 on 되어 있을경우 NL 문자는 CR-NL 문자로 치환되어서 전달된다.
OCRNL이 플레그가 on 되어 있다면 CR 문자는 NL 문자로 치환된다.
ONOCR이 플레그가 on 되어 있다면 CR이 아닌 첫번째 문자부터 전달되게 된다.
OFILL시간지연을 위해서 fill 문자를 이용한다. 이 플레그가 on 되어 있다면, 문자 전달시간지연을 위해서 time 지연을 사용하지 않고 fill 문자를 전달하는 것으로 대신한다.
OFDEL이 플레그가 on 되어 있다면 fill 문자로 DEL이 전달된다.
NLDLYnew-line 문자지연이다. NL0 과 NL1 두개의 값이 준비되어 있다. NL0 은 지연없음이며, NL1 의 경우 약 0.1 초 정도의 지연시간이 생긴다. 만약 OFILL 플레그가 on 되어 있다면, 지연을 만들기 위해서 두개의 fill 문자를 전달한다.
CRDLYCR 문자지연이다. 여기에는 CR0, CR1, CR2, CR3 의 값이 준비되어 있다. CR0 은 지연없음, CR1 은 컬럼위치에 따라 지연시간 결정, CR2 는 약 0.10 초, CR3 는 약 0.15초의 지연이 생긴다.
TABDLY수평탭 시간지연이다. TAB0, TAB1, TAB2, TAB3 의 값이 준비되어 있다. TAB0은 지연없음, TAB1 은 컬럼위치에 따라 지연시간 결정, TAB2 는 0.1초가량의 지연된다. TAB3 로했을경우 탭은 스페이스로 확장된다.
BSDLY백스페이스키 시간지연이다. BS0과 BS1 이 준비되어 있으며, BS0은 지연없음, BS1 은 약 0.05 의 시간지연을 나타낸다. OFILL 플레그가 세팅되어 있으며 BS1 이라면 한개의 fill 문자를 보낸다.


표 3. 터미널 속성값 - c_cflag

설명하드웨어의 터미널제어에 관련된 속성들이다. 모뎀과 같은 하드웨어 제어에 많이 쓰인다.
CBAUDbaud rate 에 대한 설정이다. 하드웨어에 따라서 속도의 변화가 불가능한경우도 있다. 모뎀을 사용해본적이 있다면 baud rate 에 대해서 자주 들어보았을것이다. 자주 사용되는 baud rate 는 B4800, B9600, B19200, B38400 으로 각숫자가 baud 속도를 나타낸다. 참고로 baud 는 하드웨어의 데이타 처리 속도를 나타낸다. 이외에 B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400 이 있다. 마찬가지로 B 다음의 숫자가 baud 속도이다.
CSIZE문자의 크기를 지정하기 위해서 사용한다. CS5, CS6, CS7, CS8 이 준비되어 있으며, 각각 5, 6, 7, 8bit 를 나타낸다.
CSTOPBstop 비트의 수를 정한다. 이 플레그가 on 되어있다면 2개의 stop 비트를 그렇지 않다면 1개의 stop 비트를 보낸다.
CREADreceiver 을 활성화한다.
HUPCL이 플레그가 세팅되어 있다면, 마지막 프로세스가 종료되거나, 마지막 프로세스의 line(회선)이 닫힐경우 disconnect 가 발생한다.
PARENBparity 를 추가한다. 이 플레그가 on 되어 있으면, parity 를 생성하고 검색하게 된다. 각문자에 parity bit 가 추가된다.


표 4. 터미널 속성값 - c_lflag

설명로컬(사용자) 터미널에 관한 속성과 관련되어 있다. 초기값은 모두 on 상태이다.
ISIGsignal 을 받아들인다. 이 플레그가 on 되어 있다면, INTR, QUIT, SUSP, DSUSP 과 같은 특수 문자를 받아들인다.
ICANON이 플레그가 on되면 정규모드로 입력이 이루어진다.
NOFLSHqueue flush 를 비활성화 시킨다.
ECHO반향을 설정한다. 만약 이 플레그가 off 되어있다면 입력은 반향되지 않는다.
ECHOEerase 문자를 반향한다. 만약 이 플레그와 함께 ECHO 플레그가 on 되어있다면 ERASE 가 발생할경우 스크린에서 마지막 문자를 지우게 된다.
ECHOEerase 문자를 반향한다. 만약 이 플레그와 함께 ECHO 플레그가 on 되어있다면 ERASE 가 발생할경우 스크린에서 마지막 문자를 지우게 된다.
ECHOPRT만약 ECHO 플래그가 on 되어있고 ECHOPRT가 on 되었을경우 ERASE 가 발생한다면 (back 스페이스키를 입력한다면) 삭제되는 문자가 '\' 뒤에 표시되게 된다. 만약 모든 문자를 삭제했다면 '/' 가 출력되게 된다.
ECHOKEBackspace-Space-Backspace entire line on line kill
ECHONLNL문자가 반향된다. ECHONL 플레그가 on 되어있다면, ECHO 플래그가 on 되어있지 않더라도 NL 문자가 반향된다.
ECHOCTL제어문자가 반향되도록 한다. 제어문자는 0에서 37 까지의 ASCII 코드이다. 이 플레그를 on 시킨상태에서 CTRL+X 같은 제어문자를 입력할경우 ^X 로 화면에 표시될것이다.


표 5. 제어문자 속성값 - c_cc

설명c_cc 배열은 제어문자를 제어하기 위해서 사용한다. 즉 CTRL+X, CTRL+X, CTRL+C 등의 문자와 관련된 제어를 할수 있다.
VINTR일시중지(Ctrl+C)와 관련된 제어이다. 만약 ISIG 플레그가 on 되어 있다면 일시중지 문자를 입력시키면 포그라운드 프로세스에 SIGINT 시그널이 발생된다.
VQUITQuit 제어문자 Ctrl+\ 와 관련된다. ISIG 플래그가 on 되어 있고 Quit 제어문자가 입력되면 SIGQUIT 시그널이 발생한다.
VERASEERASE 제어문자(백스페이스) 와 관련된다. 정규모드(ICANON) 플래그 가 on 되어 있고, ERASE 제어문자가 발생하면 가장 마지막 문자가 지워진다.
VKILLKILL 제어문자 (Ctrl+u)와 관련된다.
VEOFCtrl-d 제어문자와 관련된다. ICANON 플래그가 on 되어 있고, EOF가 발생하면 읽기 대기중인 모든문자들은 개행문자를 만나지 않더라도 바로 프로세스에게 전달된다.
VSTOPSTOP 제어문자(Ctrl+s)와 관련된다.
VSUSPSUSP 제어문자 (Ctrl+z)와 관련된다. ISIG 플래그가 on 되어있는 상태에서 Ctrl+z 가 입력되면 모든 포그라운드 프로세스에 SIGSTOP 신호가 전달된다.
VWERSEWERASE 제어문자 (Ctrl+w) 와 관련된다.





sread.c - 수신RX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART
#include <sys/types.h>
#include <sys/stat.h>
 
#define SPEED B115200 //데이터 전송속도
#define SPORT "/dev/ttyAMA0" //라즈베리파이 터미널 접속
int main(void)
{
    char cBuff[255]; //수신한 데이터를 저장할 버퍼 변수
 
    int iDev = 0; //통신 포트를 파일 개념으로 사용하기 위한 디스크립터
    int iRet = 0; // 데이터 수신용
 
    struct termios stOldState; //처음 상태저장
    struct termios stNewState; //새 상태저장
    
    iDev = open(SPORT,O_RDWR | O_NOCTTY); //
 
    if(0 > iDev)
    {
        perror(SPORT);
        return -100;//exit(-100);
    }
 
    tcgetattr(iDev, &stOldState);
    bzero(&stNewState, sizeof(stNewState));
 
    stNewState.c_cflag = SPEED | CRTSCTS | CS8 | CLOCAL | CREAD;
    stNewState.c_iflag = IGNPAR | ICRNL;
    stNewState.c_oflag = 0;
    
    stNewState.c_lflag = ICANON; //Cannonical 설정
    bzero(stNewState.c_cc, NCCS);
    stNewState.c_cc[VMIN] = 1;
 
    tcflush(iDev, TCIFLUSH);
    tcsetattr(iDev, TCSANOW, &stNewState);
 
    iRet = read(iDev, cBuff, 255);
    cBuff[iRet] = 0;
    printf("[%s]:[%d]\n", cBuff, iRet);
 
    tcsetattr(iDev, TCSANOW, &stOldState);
    close(iDev);
 
    //return 0;
}
 
 
cs


코드 설명 




swrite.c - 송신 RX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
 
#define SPEED B115200
#define SPORT "/dev/ttyAMA0"
int main(void)
{
    char cBuff[255];
 
    int iDev = 0;
    int iRet = 0;
 
    struct termios stOldState;
    struct termios stNewState;
    
    iDev = open(SPORT,O_RDWR | O_NOCTTY);
 
    if(0 > iDev)
    {
        perror(SPORT);
        exit(-100);
    }
 
    tcgetattr(iDev, &stOldState);
    bzero(&stNewState, sizeof(stNewState));
 
    stNewState.c_cflag = SPEED | CRTSCTS | CS8 | CLOCAL | CREAD;
    stNewState.c_iflag = IGNPAR | ICRNL;
    stNewState.c_oflag = 0;
    
    stNewState.c_lflag = ICANON;
    bzero(stNewState.c_cc, NCCS);
    stNewState.c_cc[VMIN] = 1;
 
    tcflush(iDev, TCIFLUSH);
    tcsetattr(iDev, TCSANOW, &stNewState);
 
    iRet = write(iDev, "test\n"5);
 
    printf("write complete: %d \n",iRet);
    tcsetattr(iDev, TCSANOW, &stOldState);
    close(iDev);
 
    return 0;
}
cs


43번 : iRet에 입력 "test\n"


728x90