View
237
Download
2
Category
Preview:
Citation preview
7-SEGMENT DEVICE CONTROL- DEVICE DRIVER
Jo, Heeseung
2
디바이스 드라이버 구현: 7-SEGMENT
HBE-SM5-S4210의 M3 Module에는 6자리를 가지는 7-Segment 모듈이 아래 그림처럼 실장
6 Digit 7-Segment
3
디바이스 드라이버 구현: 7-SEGMENT
6-Digit 7-Segment LED controller
• 16비트로 구성된 2개의 레지스터에 의해 제어
• SEG_Sel_Reg(Segment Select Register)
• SEG_Data_Reg(Segment Data Register)
• 레지스터들은 Read와 Write 모두 가능하도록 설계
SEG_Sel_Reg
• 0~5bit에 0 또는 1을 써 넣음으로써 display될 digit를 선택
SEG_Data_Reg
• 0~7bit에 0 또는 1을 써 넣음으로써 display될 segment들을 선택
4
디바이스 드라이버 구현: 7-SEGMENT
Segment Select Register와 Segment Data Register
• 각 비트에 대응되는 6Digit 7-Segment의 핀 배치도
SEG_E
SEG_G
SEG_F
SEG_D
SEL2
SEL1
SEL4
SEL5
SEL6
SEG_C
SEG_B
SEG_A
SEG_H
SEL3
6
디바이스 드라이버 구현: 7-SEGMENT
SEG_Sel_Reg 비트 구조
SEL1 ~ SEL6
• 6-Digit 7-Segment LED 중 display될 digit를 선택하는 bit
• 1을 입력할 경우 선택 해제
• 0을 입력할 경우 선택
Bits Name Description
0 SEL1 Digit 1 Select Bit0 (Active Low)
1 SEL2 Digit 1 Select Bit1 (Active Low)
2 SEL3 Digit 1 Select Bit2 (Active Low)
3 SEL4 Digit 1 Select Bit3 (Active Low)
4 SEL5 Digit 1 Select Bit4 (Active Low)
5 SEL6 Digit 1 Select Bit5 (Active Low)
bit
reset
Physical Address 0x0500_0030 SEG_Sel_Reg
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
SEL_6
SEL_5
SEL_4
SEL_3
SEL_2
SEL_1
x x x x x x x x x x 0 0 0 0 0 0
8
디바이스 드라이버 구현: 7-SEGMENT
SEG_Data_Reg 비트 구조
SEG_A ~ SEG_G
• 6 Digit 7-Segment 중 display될 digit의 segment들을 선택하는 bit
• 0을 입력할 경우 선택해제
• 1을 입력할 경우 선택
Bits Name Description
0 SEG_A Segment Display Bit0 (Active High)
1 SEG_B Segment Display Bit1 (Active High)
2 SEG_C Segment Display Bit2 (Active High)
3 SEG_D Segment Display Bit3 (Active High)
4 SEG_E Segment Display Bit4 (Active High)
5 SEG_F Segment Display Bit5 (Active High)
6 SEG_G Segment Display Bit6 (Active High)
7 SEG_H Segment Display Bit7 (Active High)
bit
reset
Physical Address 0x0500_0032 SEG_Data_Reg
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
SEG_A
SEG_B
SEG_C
SEG_D
SEG_E
SEG_F
SEG_G
SEG_H
x x x x x x x x 0 0 0 0 0 0 0 0
10
디바이스 드라이버 구현: 7-SEGMENT
6개의 7-Segment Array에 "123456"의 숫자를 표시하기 위한과정과 각 신호 라인의 펄스 타이밍도
• 지속해서 신호를 주어야 불이 켜진 것 처럼 보임
1 2
6 3
5 4
7
1 2
3 4
5 6
12
디바이스 드라이버 구현: 7-SEGMENT
Device driver 소스파일
• 7-Segment 리눅스 디바이스 드라이버는 커널에 포함
• menuconfig 실행
- Device Drivers -> [*] Misc devices -> [*] Hanback Electronics M3(FPGA) Device Support -> <*>7 Segment
• linux-2.6.35-s4210/drivers/misc/hanback/segment.c 참조
13
디바이스 드라이버 구현: 7-SEGMENT
linux-2.6.35-s4210/drivers/misc/hanback/segment.c
unsigned short Getsegmentcode (short x){
unsigned short code;switch (x) {
case 0x0 : code = 0xfc; break;case 0x1 : code = 0x60; break;case 0x2 : code = 0xda; break;case 0x3 : code = 0xf2; break;case 0x4 : code = 0x66; break;case 0x5 : code = 0xb6; break;case 0x6 : code = 0xbe; break;case 0x7 : code = 0xe4; break;case 0x8 : code = 0xfe; break;case 0x9 : code = 0xf6; break;
case 0xa : code = 0xfa; break;case 0xb : code = 0x3e; break;case 0xc : code = 0x1a; break;case 0xd : code = 0x7a; break;case 0xe : code = 0x9e; break;case 0xf : code = 0x8e; break;default : code = 0; break;
}return code;
}
SEG_E
SEG_G
SEG_F
SEG_D
SEL2
SEL1
SEL4
SEL5
SEL6
SEG_C
SEG_B
SEG_A
SEG_H
SEL3
14
디바이스 드라이버 구현: 7-Segmentssize_t segment_write(struct file *inode, const char *gdata, size_t length, loff_t*off_what){
unsigned char data[6];unsigned char digit[6]={0x20, 0x10, 0x08, 0x04, 0x02, 0x01};unsigned int i,num,ret;unsigned int count=0,temp1,temp2;
ret=copy_from_user(&num,gdata,4);
count = num;
if(num!=0) {data[5]=Getsegmentcode(count/100000);temp1=count%100000;data[4]=Getsegmentcode(temp1/10000);temp2=temp1%10000;data[3]=Getsegmentcode(temp2/1000);temp1=temp2%1000;data[2]=Getsegmentcode(temp1/100);temp2=temp1%100;data[1]=Getsegmentcode(temp2/10);data[0]=Getsegmentcode(temp2%10);
15
디바이스 드라이버 구현: 7-Segmentswitch (mode_select) {
case MODE_0_TIMER_FORM:break;case MODE_1_CLOCK_FORM:// dot printdata[4] += 1;data[2] += 1;break;
}// printfor(i=0;i<6;i++) {
*segment_grid = digit[i];*segment_data = data[i];mdelay(1);
}}
*segment_grid = ~digit[0];*segment_data = 0;
return length;}
16
디바이스 드라이버 구현: 7-SEGMENT
seg_test.c 프로그램 작성
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <time.h>
int main (int argc, char *argv[]){
int fd, value = 1, i, count, clock, ch;unsigned short input, dir = 0;
if (argc <= 1){
printf ("please input the parameter! ex) %s 123456\n", argv[0]);return -1;
}
17
디바이스 드라이버 구현: 7-Segment
if ((fd = open ("/dev/segment", O_RDWR | O_SYNC)) < 0){
printf ("FND open fail\n");exit (1);
}count = atoi(argv[1]);
for (i = 0; i < 400; i++){
write (fd, &count, 4);usleep (1000);
}
close (fd);return 0;
}
18
디바이스 드라이버 구현: 7-SEGMENT
Makefile 작성
CC = arm-linux-gccCFLAGS = -DNO_DEBUGEXEC = seg_testOBJS = $(EXEC).o
all: $(EXEC)$(EXEC): $(OBJS)
$(CC) -o $@ $^clean:
rm -f $(OBJS) $(EXEC)
19
디바이스 드라이버 구현: 7-SEGMENT
컴파일
• make clean하면 먼저 컴파일 된 실행예제 파일 삭제
• make 명령어로 컴파일 실행
테스트
• board에서 실행
root@ubuntu:/working/device_driver/seg_driver# lsMakefile seg_test.croot@ubuntu:/working/device_driver/seg_driver# make clean; make------------------다음과 같은 메시지가 출력된다 -----------------rm -f seg_test.o seg_testarm-linux-gcc -c -DNO_DEBUG -o seg_test.o seg_test.carm-linux-gcc -o seg_test seg_test.oroot@ubuntu:/working/device_driver/seg_driver# lsMakefile seg_test seg_test.c seg_test.o
20
EXERCISE
1초 마다 랜덤한 6자리 숫자가 표시되는 프로그램을 작성
7-SEGMENT DEVICE CONTROL- MMAP()
Jo, Heeseung
23
7-SEGMENT 제어
7-Segment
• 원하는 자리에 원하는 부분(세그먼트)를 켜서 데이터를 출력
• 해당 데이터에 따라 7-Segment에 숫자나 영문자를 표시
• 그리드 선택 번지 : 0x05000030
• 세그먼트 선택 번지 : 0x05000032
그리드 선택 번지의 데이터 형식
• 0x01 – SEG1을 선택
• 0x02 – SEG2를 선택
• 0x04 – SEG3을 선택
• 0x08 – SEG4를 선택
• 0x10 – SEG5를 선택
• 0x20 – SEG6을 선택
24
7-SEGMENT 제어
다음으로 세그먼트 데이터 형식
• 숫자 0 : 0xfc
• 숫자 1 : 0x60
• 숫자 2 : 0xda
• 숫자 3 : 0xf2
• 숫자 4 : 0x66
• 숫자 5 : 0xb6
• 숫자 6 : 0xbe
• 숫자 7 : 0xe4
• 숫자 8 : 0xfe
• 숫자 9 : 0xf6
• 영문 a : 0xfa
• 영문 b : 0x3e
• 영문 c : 0x1a
• 영문 d : 0x7a
• 영문 e : 0x9e
• 영문 f : 0x8e
SEG_E
SEG_G
SEG_F
SEG_D
SEL2
SEL1
SEL4
SEL5
SEL6
SEG_C
SEG_B
SEG_A
SEG_H
SEL3
25
7-SEGMENT 제어
segment.c 작성
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <sys/mman.h>#include <fcntl.h>
unsigned short Getsegcode(short x);
#define FPGA_BASEADDRESS 0x05000000#define SEG_GRID_OFFSET 0x30#define SEG_DATA_OFFSET 0x32
int main(){
int fd;volatile int i,j;unsigned int count=1,num,temp1,temp2;unsigned short data[6];unsigned short digit[6]={0x20, 0x10, 0x08, 0x04, 0x02, 0x01};unsigned short *addr_fpga;unsigned short *addr_grid, *addr_data;
26
7-Segment 제어if((fd=open("/dev/mem",O_RDWR|O_SYNC)) < 0) {
printf("mem open fail\n");exit(1);
}
addr_fpga= (unsigned short *)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, FPGA_BASEADDRESS);
if(*addr_fpga == (unsigned short)-1) {close(fd);printf("mmap error\n");exit(1);
} addr_grid=addr_fpga+SEG_GRID_OFFSET;addr_data=addr_fpga+SEG_DATA_OFFSET;
printf("- 7 Segment\n");
28
7-Segment 제어while(count!=0) {
num=0;printf("Input count value: [1-999999] (0 : exit program) \n");scanf("%d", &count);while(num<=count ) {
data[5]=Getsegcode(num/100000);temp1=num%100000;data[4]=Getsegcode(temp1/10000);temp2=temp1%10000;data[3]=Getsegcode(temp2/1000);temp1=temp2%1000;data[2]=Getsegcode(temp1/100);temp2=temp1%100;data[1]=Getsegcode(temp2/10);data[0]=Getsegcode(temp2%10);
for(j=0;j<20;j++) { for(i=0;i<6;i++) {
*addr_grid = digit[i];*addr_data = data[i];usleep(1000);
}}num++;
}*addr_grid = ~digit[0];*addr_data = 0;
}
29
7-Segment 제어munmap(addr_fpga,4096);close(fd);return 0;
}unsigned short Getsegcode(short x){
unsigned short code;switch (x) {
case 0x0 : code = 0xfc; break;case 0x1 : code = 0x60; break;case 0x2 : code = 0xda; break;case 0x3 : code = 0xf2; break;case 0x4 : code = 0x66; break;case 0x5 : code = 0xb6; break;case 0x6 : code = 0xbe; break;case 0x7 : code = 0xe4; break;case 0x8 : code = 0xfe; break;case 0x9 : code = 0xf6; break;
case 0xa : code = 0xfa; break;case 0xb : code = 0x3e; break;case 0xc : code = 0x1a; break;case 0xd : code = 0x7a; break;case 0xe : code = 0x9e; break;case 0xf : code = 0x8e; break;default : code = 0; break;
}return code;
}
30
7-SEGMENT 제어
Makefile 작성
CC = arm-linux-gccCFLAGS = -DNO_DEBUGEXEC = segmentOBJS = $(EXEC).o
all: $(EXEC)$(EXEC): $(OBJS)
$(CC) -o $@ $^clean:
rm -f $(OBJS) $(EXEC)
31
7-SEGMENT 제어
컴파일
• make clean하면 먼저 컴파일 된 실행예제 파일 삭제
• make 명령어로 컴파일 실행
테스트
• board에서 실행
root@ubuntu:/working/mmap/segment# makearm-linux-gcc -c -DNO_DEBUG -o segment.o segment.carm-linux-gcc -o segment segment.oroot@ubuntu:/working/mmap/segment# lsMakefile segment segment.c segment.o
Recommended