일상다반사 로그

임베디드 리눅스 Push,LED,TextLCD 본문

IT/임베디드 리눅스

임베디드 리눅스 Push,LED,TextLCD

일상다반사로그 2017. 10. 14. 06:04
반응형

#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <asm/fcntl.h>
#include <stdio.h>
#include <time.h>   //랜덤수를 구하기위한 헤더파일
#define ADDRESSOFLED 0x10600000
#define ADDRESSOFPUSHBUTTON 0x10500000
#define ADDRESSOFTEXTLCD 0x10700000

//TextLCD를 사용하기 위한 함수들 선언
void setcommand(unsigned short command);
void initialize_textlcd();
void setcommand(unsigned short command);
void writebyte(char ch);
void initialize_textlcd();
void write_string(char *str,int length);
int function_set(int rows, int nfonts);
int display_control(int display_enable, int cursor_enable, int nblink);
int cusrsor_shit(int set_screen, int set_rightshit);
int entry_mode_set(int increase, int nshift);
int return_home();
int clear_display();
int set_ddram_address(int pos);
unsigned int *pTextlcd;

//TextLCD를 사용하기위한 함수
print_lcd(char * buf1, char *buf2, int *fd)
{
 
        int i, len1=strlen(buf1), len2=strlen(buf2);
 /*mmap을 이용하여 TextLCD의 하드웨어 어드레스를 응용프로그램에서
 사용할 가상주소를 얻기*/
        pTextlcd = mmap(NULL, 4, PROT_WRITE, MAP_SHARED, *fd, ADDRESSOFTEXTLCD);
 
        initialize_textlcd();    //TextLCD초기화
  /*writebyte함수를 이용하여 첫 번째 줄에 buf1에 들어있는 문자열을 쓴다.
 set_ddram_address 함수를 이용하여 TextLCD커서를 두번째 줄의 처음으로
 바꾸고 다시 buf2에 있는 문자열을 쓴다. */
        for(i=0;i<len1;i++) writebyte(buf1[i]);
        for(i=0;i<20-len1;i++) cusrsor_shit(1,1);
 
        clear_display();
        set_ddram_address(0x40);

        for(i=0;i<(19-len2);i++) cusrsor_shit(0,1);
        for(i=0;i<len2;i++) writebyte(buf2[i]);
        for(i=0;i<20-len2;i++) cusrsor_shit(1,0);

  clear_display();
 set_ddram_address(0x40);
 //munmap을 사용하여 mmap을 이용하여 매핑한 메모리를 해제
        munmap(pTextlcd,4);
}

int main(){
 int fd;      //파일기술자
 //LED와 Push button을 사용하기위한 변수들
 unsigned char *addr_led, *addr_button,led_status;
 unsigned char rp;    //버튼값을 받는 변수
 
 //랜덤수를 사용할 변수들
 int s = 0, i,j=0;   
 int a=0; 
 int ran[5];
 
 for(i = 0; i< 5; i++)    //배열초기화
  ran[i] = 5;
 
 if((fd =open("/dev/mem",O_RDWR|O_SYNC)) <0){

  perror("mem open fail \n");
  exit(1);
 }
 /*mmap을 이용하여 LED,Push Button 하드웨어 어드레스를 응용프로그램에서
 사용할 가상주소를 얻기*/
 addr_led = mmap(NULL,1,PROT_WRITE,MAP_SHARED,fd,ADDRESSOFLED);
  addr_button = mmap(NULL,1,PROT_READ,MAP_SHARED,fd,ADDRESSOFPUSHBUTTON);

 *addr_led=0xAA;      //Led초기화
 led_status=1;    
 *addr_led= led_status;
 print_lcd("ON LED","Cheking Random num",&fd);
 
 while(1){
  while(1){
   j = 0;
   srand((unsigned) time(NULL));
   s= rand()%5;   //랜덤함수사용 0~4까지
  
   /*랜덤수를 구할때 중복된 값을 배열에 저장못하게
   ran배열에 어떤위치의 값이 현재구해진 랜덤수와
   같다면 j변수에 1를 넣어준다 이후 조건문에서
   j가 1일때 continue를 해줌으로써 중복된값을
   저장못하게 한다. */
   for(i = 0 ; i < 5; i++)
   {
    if(ran[i]==s){  
     j = 1;
     break;
    }
   }
   if(j == 1){
    continue;
   }
   else{
    break;
   }
  }
  ran[a]=s;
  printf("현재 숫자: %d \n",ran[a]);
  
  //ran[]배열에 있는 숫자에 따른 LED 점등 
  switch(ran[a]){
   case 0 : led_status=128; break;
  case 1 : led_status=64; break;
  case 2 : led_status=32; break;
  case 3 : led_status=16; break;
  case 4 : led_status=8; break;
  default : printf("error\n");
  }
  a++;     
  *addr_led = led_status;
  usleep(500000);
  if(a == 5)
   break; 
 }

 led_status=0;
 *addr_led = led_status;
 
 printf("* 프로그램 시작 *\n");
 print_lcd("Program Start !","You have to remember",&fd);

 i =0;   //이후에 랜덤수비교할때쓰기위해 미리초기화

 //버튼을 누르면 LED가 점등된다.마지막버튼은 종료 버튼
 while(1){
 int cnt =0;  
 int  tmp = 255 - *addr_button;  //버튼주소값을 구하기
 
  switch(tmp){
  case 0x80 : led_status=128; break;
  case 0x40 : led_status=64; break;
  case 0x20 : led_status=32; break;
  case 0x10 : led_status=16; break;
  case 0x8 : led_status=8; break;
  case 0x4 : led_status=4; break;// 현재 사용하지 않는 버튼 
  case 0x2 : led_status=2; break;// 차후 업그래이드 예정
  case 0x1 : printf("* 프로그램 종료 *\n");      print_lcd("Game Over","Thank you",&fd);       *addr_led = 0x00;               munmap(addr_led,1);         munmap(addr_button,1);close(fd); exit(1); break;
  }
 *addr_led = led_status; usleep(10000);
 
  //다섯개 모두 맞췄을경우 알림표시
  if(i==5)
  {
   printf("와우! 당신은 정말 천재이군요!\n");
   print_lcd("Wow Good Choice!","You lucky guy!",&fd);
   break;
  }
  //랜덤수와 현재 버튼눌렀을때와의 비교
  while(1)
  {
   if(tmp != 0){
    if(tmp == 128)
     break;
    else{
     tmp <<= 1;
     cnt++;
   
    }
   }
   else
    break;
  }
 
  if(tmp == 0)
   continue;
  //버튼을 눌러서 맞췄을경우 콘솔에 표시
  if(ran[i]==cnt)
  {
   printf("%d번 맞음 Good Choice !\n", i+1);
   i++;
   usleep(500000);
   continue;
  }
  //틀렸을경우 콘솔에 알려주고 TextLCD에 실패표시
  else
  {
   printf("틀렸습니다 프로그램 종료...\n");
   print_lcd("Fail....T.T","You unlucky guy",&fd);
   break;
  }
  
 }
 
 printf("* 프로그램 종료 *\n");
 print_lcd("Game Over","Thank You",&fd);

 *addr_led = 0x00;     //LED꺼짐
 //munmap을 사용하여 mmap을 이용하여 매핑한 메모리를 해제
 munmap(addr_led,1); munmap(addr_button,1);
 close(fd);     //fd반환
 return 0;
}
//명령어를 받아 TextLCD의 명령값을 전달
void setcommand(unsigned short command)
{
        command &= 0x00FF;
        *pTextlcd = command | 0x0000;
        *pTextlcd = command | 0x0400;
        *pTextlcd = command | 0x0000;
        usleep(100000);
}
/*제어명령표의 DataWrite to GG RAM 혹은 DD RAM을 사용하기위한 함수
TextLCD 직접 글자를 쓰는 함수이다.*/
void writebyte(char ch)
{
        unsigned short data;
        data = ch & 0x00FF;
 
        *pTextlcd = data|0x100;
        *pTextlcd = data|0x500;
        *pTextlcd = data|0x100;
 
        usleep(5000);
}
/*제어 명령표의 Clear Display(0x1)을 설정한후 setcommand()함수로 명령어를 전달
TextLCD의 화면을 지우고 커서를home에 위치시킨다. */
int clear_display(){
        unsigned short command = 0x01;
        setcommand(command);
        usleep(2000);
        return 1;
}
/*제어 명령표의 Return Home(0x02)을 설정한후 setcommand()함수로 명령어를 전달
하여 커서를 home에 위치시킨다.*/
int return_home(){
        unsigned short command = 0x02;
        setcommand(command);
 
        usleep(2000);
        return 1;
}
/*제어 명령표의 Entry Mode Set(0x04)을 설정하고 인수로 받은increase를
데이터의 비트에 대응시키고 setcommand()를 사용하여 TextLCD모듈에 전달 */
int entry_mode_set(int increase, int nshift){
        unsigned short command = 0x04;
        command = increase ? (command | 0x2) : command;
        command = nshift ? (command | 0x1) : command;
        setcommand(command);
        return 1;
}
//인수로 받은 값에 따라 화면을 On/Off 하거나 커서를 깜빡이는 함수
int display_control(int display_enable, int cursor_enable, int nblink){
        unsigned short command = 0x08;
        command = display_enable ? (command | 0x04) : command;
        command = cursor_enable ? (command | 0x02) : command;
        command = nblink ? (command | 0x01) : command;
        setcommand(command);
        return 1;
}
//인수로 받은 값에 따라 화면 또는 커서를 왼쪽 오른쪽으로 시프트 하는 함수
int cusrsor_shit(int set_screen, int set_rightshit){
        unsigned short command = 0x10;
        command = set_screen ? (command | 0x08) : command;
        command = set_rightshit ? (command | 0x04) : command;
        setcommand(command);
        return 1;
}
//이후 나머지 함수들은 TextLCD 초기화를 구현하는 함수들이다.
int function_set(int rows, int nfonts){
        unsigned short command = 0x30;
 
        if(rows == 2) command |= 0x08;
        else if(rows == 1) command &= 0xf7;
        else return -1;
 
        command = nfonts ? (command | 0x04) : command;
        setcommand(command);
        return 1;
}
int set_ddram_address(int pos){
        unsigned short command = 0x80;
        command += pos;
        setcommand(command);
        return 1;
}
void initialize_textlcd(){
        function_set (2,0);
        display_control(1,0,0);
        clear_display();
        return_home();
        entry_mode_set(1,0);
        usleep(200000);
}

반응형

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

임베디드 리눅스 -TextLCD  (0) 2017.10.13
임베디드 리눅스 - LED(2)  (0) 2017.10.12
임베디드 리눅스 - LED  (0) 2017.10.11
임베디드 리눅스 - 텍스트 LCD  (0) 2017.10.11
임베디드 리눅스 - 스톱워치  (0) 2017.10.10
Comments