일상다반사 로그

임베디드 리눅스 - 스톱워치 본문

IT/임베디드 리눅스

임베디드 리눅스 - 스톱워치

일상다반사로그 2017. 10. 10. 21:59
반응형

스톱워치

 

실습 12 7segment 제어프로그램


 프로그램 작동순서를 보면 사용자가 키보드로 's‘ 입력하면 스톱워치가 시작된다 소스를 보면은 터미널환경설정을 하고 키보드 감지하는 함수 그리고 키보드입력값을 확인하는 함수를 구현해놓고, 스톱워치에 필요한 함수를 구현했다. 스톱워치에 필요한 함수에는 Showsegment(),Getsegcode(), itos() 함수가 있다. 메인함수에서 무한루프를 돌면서 스톱워치가 시작되면 data, strData의 값을 itos()함수로 보내서 ASCII코드로 받아오고 ASCII코드값을 Getsegcode()함수로 보내서 7segmentLED에 표시할수 있는 값으로 만든다. 그리고나서 Showsegment()함수로 보내서 7segmentLED로 출력한다. 이걸 무한루프를 돌면서 반복한다.


- 스톱워치 소스 -


#include <stdlib.h>

#include <unistd.h>

#include <sys/mman.h>

#include <sys/fcntl.h>

#include <termios.h>

#include <stdio.h>



#define segment7_L 0x10300000

#define segment7_H 0x10400000


struct termios initial_settings, new_settings;

int peek_character=-1;

void init_keyboard(){         //터미널 환경설정

        tcgetattr(0,&initial_settings);

        new_settings = initial_settings;

        new_settings.c_lflag &= ~ICANON;

        new_settings.c_lflag &= ~ECHO;

        new_settings.c_lflag &= ~ISIG;

        new_settings.c_cc[ VMIN] =1;

        new_settings.c_cc[ VTIME] =0;

        tcsetattr(0, TCSANOW, &new_settings);

}

void close_keyboard(){      //키보드입력을 종료하는 함수

        tcsetattr(0, TCSANOW, &initial_settings);

}

int kbhit(){               //키보드 입력을 감지하는 함수

        char ch;

        int nread;

        if(peek_character != -1) return 1;

        new_settings.c_cc[ VMIN] = 0;

        tcsetattr(0, TCSANOW, &new_settings);

        nread = read(0, &ch,1);

        new_settings.c_cc[ VMIN] = 1;

        tcsetattr(0, TCSANOW, &new_settings);

        if(nread == 1){

                        peek_character = ch;

                        return 1;

        }

        return 0;

}

int readch(){              //키보드 입력값을 확인하는 함수

        char ch;

        if(peek_character != -1){

                ch = peek_character;

                peek_character = -1;

                return ch;

        }

        read(0, &ch, 1);

        return ch;

}


void Showsegment(unsigned int highValue, unsigned int lowValue)

{       //데이터를 7segment LED로 출력하는 함수


        

        /* 데이터를 7segment LED로 출력 /dev/mem열고 mmap 이용하여 7segmentLED의 하드웨어 절대번        지를 가상메모리에 매핑한다. 넘겨받은 주소를 addr_lseg와 addr_hseg에 저장한다. 주소를 넘겨받지 못        했으면 munmap으로 주소를 해제하고 메모리 파일 기술자를 닫고 프로그램 종료 주소를 넘겨받았으면         그 주소에 값을 출력하고 munmap으로 메모리를 해제하고 메모리 파일 기술자를 닫아준다. */


        int fd;

        unsigned int *addr_hseg;

        unsigned int *addr_lseg;


        //하드웨어 절대번지를 가상메모리에 매핑할 파일기술자 열기


        if((fd = open("/dev/mem",O_RDWR|O_SYNC)) < 0){

                printf("mem open fail\n");

                exit(1);

        }

        

        //넘겨받은 주소를 addr_lseg, addr_hseg에 저장한다.


        addr_lseg = mmap(NULL, 4, PROT_WRITE, MAP_SHARED, fd, segment7_L);

        addr_hseg = mmap(NULL, 4, PROT_WRITE, MAP_SHARED, fd, segment7_H);


        //넘겨받지 못했을때 파일기술자를 닫아줌


        if(addr_lseg < 0 | addr_hseg < 0){

                munmap(addr_lseg, 4);

                munmap(addr_hseg, 4);

                close(fd);

                printf("mmap error\n");

                return;

        }

        

        //addr_lseg = 7segment LED의 아랫부분 addr_hseg = 윗부분

        *addr_lseg = lowValue;      

        *addr_hseg = highValue;

        munmap(addr_lseg, 4);

        munmap(addr_hseg, 4);

        close(fd);

}


char Getsegcode(char x)

{       //입력받은 ASCII 코드를 7segment에 표시 가능한값으로 바꾸어주는 함수

        char code;

        switch(x){

                case '0' : code = 0x3f; break;

                case '1' : code = 0x06; break;

                case '2' : code = 0x5b; break;

                case '3' : code = 0x4f; break;

                case '4' : code = 0x66; break;

                case '5' : code = 0x6d; break;

                case '6' : code = 0x7d; break;

                case '7' : code = 0x07; break;

                case '8' : code = 0x7f; break;

                case '9' : code = 0x6f; break;

                }


                return code;

}


void itos(int val, char *str){                  


        //메인함수에 data,strData값을 받아서 ASCII코드값으로 변환해주는 함수


        int i, div=1000;

        for(i=0;i<4;i++){

                str[i]=val/div+48;

                val %= div;

                div /= 10;

        }

        str[i] = '\0';

}


int main()

{

        int k;

        unsigned int low= 0, high =0;

        char strData[5], ch, status='s';

        int data=0;                       //data변수 초기화


        init_keyboard();                    //터미널환경설정 함수 불러오기

        while(1){                         //무한루프

                if(kbhit()){                 //키보드 입력이 감지되었을때

                        ch= readch();     //ch변수에 키보드입력값을 넣어줌      

        

                        switch(ch){

                                case 's': status= 's'; break;

                                case 'p': status= 'p'; break;

                                case 'r': data= 0; break;

                                case 'q': close_keyboard(); exit(0);

                        }

                }


                if(status == 's'){           //'s'를 입력하면 스톱워치시작

                        data=(data>9999)?0:(data+1);

                }


                itos(data,strData);          //itos함수호출(data,strData)값 넘겨줌


                //high,low변수에 GetsegCode함수를 불러서 strData의 값을 넣어준다.

                그러면 GetsegCode함수가 7segmentLED에 표시할수 있는 값으로 변환해준다.


                high = Getsegcode(strData[0]);

                high = (high<<8) | Getsegcode(strData[1]);

                low = Getsegcode(strData[2]);

                low = (low<<8) | Getsegcode(strData[3]);


                //7segmentLED로 출력하기위해 high,low 변수를 Showsegement함수에 값을 넣어줌

                Showsegment(high,low);


                usleep(10000);            //스톱워치움직임 딜레이주기

        }

}

반응형

'IT > 임베디드 리눅스' 카테고리의 다른 글

임베디드 리눅스 Push,LED,TextLCD  (0) 2017.10.14
임베디드 리눅스 -TextLCD  (0) 2017.10.13
임베디드 리눅스 - LED(2)  (0) 2017.10.12
임베디드 리눅스 - LED  (0) 2017.10.11
임베디드 리눅스 - 텍스트 LCD  (0) 2017.10.11
Comments