BASIC4MCU | 질문게시판 | 답변 : 8051 프로세서 사거리 신호등 질문드립니다.
페이지 정보
작성자 master 작성일2018-12-04 09:52 조회3,107회 댓글0건
https://www.basic4mcu.com/bbs/board.php?bo_table=gac&wr_id=6240
본문
// MCU BASIC: https://www.basic4mcu.com// DateTime : 2018-12-04 오전 9:51:25// by Ok-Hyun Park//#include <REGX51.H>/*딜레이 설정한다.주의할점은 D_GREEN 값이 D_GREEN_M+D_GREEN_M_ON_OFF 보다 커야 한다.*/#define D_GREEN_M 5#define D_GREEN_M_ON_OFF 20#define D_GREEN 28#define D_YEL 2/*PORT0*/#define E_RED 0x01#define E_YEL 0x02#define DD0 0x04#define E_GREEN 0x08#define E_RED_M 0x10#define E_GREEN_M 0x20#define DD1 0x40#define E_CLK 0x80#define E_DATA_1 P0|=E_DATA#define E_DATA_0 P0&=~E_DATA#define E_CLK_1 P0|=E_CLK#define E_CLK_0 P0&=~E_CLK#define DD0_1 P0|=DD0;#define DD0_0 P0&=~DD0;#define DD1_1 P0|=DD1;#define DD1_0 P0&=~DD1;/*PORT1*/#define W_RED 0x01#define W_YEL 0x02#define DD2 0x04#define W_GREEN 0x08#define W_RED_M 0x10#define W_GREEN_M 0x20#define DD3 0x40#define W_CLK 0x80#define W_DATA_1 P1|=W_DATA#define W_DATA_0 P1&=~W_DATA#define W_CLK_1 P1|=W_CLK#define W_CLK_0 P1&=~W_CLK#define DD2_1 P1|=DD2;#define DD2_0 P1&=~DD2;#define DD3_1 P1|=DD3;#define DD3_0 P1&=~DD3;/*PORT2*/#define S_RED 0x01#define S_YEL 0x02#define DD4 0x04#define S_GREEN 0x08#define S_RED_M 0x10#define S_GREEN_M 0x20#define DD5 0x40#define S_CLK 0x80#define S_DATA_1 P2|=S_DATA#define S_DATA_0 P2&=~S_DATA#define S_CLK_1 P2|=S_CLK#define S_CLK_0 P2&=~S_CLK#define DD4_1 P2|=DD4;#define DD4_0 P2&=~DD4;#define DD5_1 P2|=DD5;#define DD5_0 P2&=~DD5;/*PORT3*/#define N_RED 0x01#define N_YEL 0x02#define DD6 0x04#define N_GREEN 0x08#define N_RED_M 0x10#define N_GREEN_M 0x20#define N_CLK 0x80#define N_DATA_1 P3|=N_DATA#define N_DATA_0 P3&=~N_DATA#define N_CLK_1 P3|=N_CLK#define N_CLK_0 P3&=~N_CLK#define DD6_1 P3|=DD6;#define DD6_0 P3&=~DD6;/*Port C*/#define A 0x01#define B 0x02#define C 0x04#define D 0x08#define E 0x10#define F 0x20#define G 0x40#define DOT 0x80//unsigned char SEG7[10]={A|B|C|D|E|F, // 0B| C, // 1A|B| D|E| G, // 2A|B|C|D| G, // 3B| C| F|G, // 4A| C|D| F|G, // 5A| C|D|E|F|G, // 6A|B|C| F, // 7A|B|C|D|E|F|G, // 8A|B|C|D| F|G // 9};unsigned sec_500m,sec_1s,count_sec;/* 아래의 변수는 위에서 세팅된 딜레이 값들을 처음 기준값에 의한 시간으로 계산하기 위한 변수 선언이다.초기화할때 처음 실행한다. */unsigned d_green_m,d_green_m_on_off,d_green,d_yel;unsigned char ON_OFF_CHK;/*아래의 변수 NEWS 는 파란불 켜짐이 어느쪽인지를 알기위해서 사용되는 변수이다NEWS=0 일때,북쪽에 파란불 켜짐,NEWS=1 일때,동쪽에 파란불 켜짐.NEWS=2 일때,남쪽에 파란불 켜짐.NEWS=3 일때,서쪽에 파란불 켜짐.*/unsigned char NEWS;/*세그먼트 관련*/unsigned char SEG_flag=0,seg_data=0;unsigned int segment_cnt=0;//void Data_8(unsigned char dt){if(dt&0x01){ DD0_1; } else DD0_0;if(dt&0x02){ DD1_1; } else DD1_0;if(dt&0x04){ DD2_1; } else DD2_0;if(dt&0x08){ DD3_1; } else DD3_0;if(dt&0x10){ DD4_1; } else DD4_0;if(dt&0x20){ DD5_1; } else DD5_0;if(dt&0x40){ DD6_1; } else DD6_0;}//void E_7segment(unsigned char dt){ /*동쪽 세그먼트 숫자 표기 함수*/unsigned char seg; seg=SEG7[dt]; seg=~seg; Data_8(seg); E_CLK_1; E_CLK_0;}//void W_7segment(unsigned char dt){ /*서쪽 세그먼트 숫자 표기 함수*/unsigned char seg; seg=SEG7[dt]; seg=~seg; Data_8(seg); W_CLK_1; W_CLK_0;}//void S_7segment(unsigned char dt){ /*남쪽 세그먼트 숫자 표기 함수*/unsigned char seg; seg=SEG7[dt]; seg=~seg; Data_8(seg); S_CLK_1; S_CLK_0;}//void N_7segment(unsigned char dt){ /*북쪽 세그먼트 숫자 표기 함수*/unsigned char seg;seg=SEG7[dt];seg=~seg; /*Andoe Common 이기 때문*/Data_8(seg); N_CLK_1; N_CLK_0;}//void interrupt_init(void){TH1=0X38; TL1=0X38; TMOD=0X20; TR1=1; ET1=1; EA=1;}//void initialize(void){P2=0xff;P3&=~(N_GREEN);P0&=~E_GREEN_M;P0&=~E_RED;P1&=~W_RED;P2&=~S_RED;P3&=~N_RED_M;P1&=~W_RED_M;P2&=~S_RED_M;E_CLK_0;W_CLK_0;S_CLK_0;N_CLK_0;E_7segment(0); /*동쪽 횡단보도 숫자 0 표시*/W_7segment(0); /*서쪽 횡단보도 숫자 0 표시*/S_7segment(0); /*남쪽 횡단보도 숫자 0 표시*/N_7segment(0); /*북쪽 횡단보도 숫자 0 표시*//*처음에 세팅한 딜레이 값들을 기준 0 시간에 대한 값으로 부터 다시 세팅한다.소문자 변수에...*/d_green_m=D_GREEN_M;d_green_m_on_off=d_green_m+D_GREEN_M_ON_OFF;d_green=D_GREEN;d_yel=d_green+D_YEL;}//void control_on_off(void){ /*횡단보도에서 파란불 깜빡 거리는 함수*/switch(NEWS){case 0: P0^=E_GREEN_M; break; /*북쪽에 파란색 불이 켜져있으면,동쪽의 횡단보드의 파란불을 깜빡인다.*/case 1: P2^=S_GREEN_M; break; /*동쪽에 파란색 불이 켜져있으면,남쪽의 횡단보도의 파란불을 깜빡인다.*/case 2: P1^=W_GREEN_M; break; /*남쪽에 파란색 불이 켜져있으면,서쪽의 횡단보도의 파란불을 깜빡인다.*/case 3: P3^=N_GREEN_M; break; /*서쪽에 파란색 불이 켜져있으면,북쪽의 횡단보도의 파란불을 깜빡인다.*/}}//void control_on_off_end(void){ /*횡단 보도에서 깜빡이던 파란색불 끄고 적색 불을 킨다.*/switch(NEWS){case 0: P0|=E_GREEN_M; P0&=~E_RED_M; break; /*북쪽에 파란색 불이 켜져있으면,동쪽의 횡단보드 파란불을 끄고 적색불을킨다.*/case 1: P2|=S_GREEN_M; P2&=~S_RED_M; break; /*동쪽에 파란색 불이 켜져있으면,남쪽의 횡단보드 파란불을 끄고 적색불을킨다.*/case 2: P1|=W_GREEN_M; P1&=~W_RED_M; break; /*남쪽에 파란색 불이 켜져있으면,서쪽의 횡단보드 파란불을 끄고 적색불을킨다.*/case 3: P3|=N_GREEN_M; P3&=~N_RED_M; break; /*서쪽에 파란색 불이 켜져있으면,북쪽의 횡단보드 파란불을 끄고 적색불을킨다.*/}}//void control_yel(void){ /*파란색불을 끄고,노란색(황색)불로 바꾸는 함수*/N_7segment(0); E_7segment(0); W_7segment(0); S_7segment(0);switch(NEWS){case 0: P3|=(N_GREEN); P3&=~N_YEL; break; /*북쪽에 파란색 불이 켜져있으면,북쪽에 파란불을 끄고 노란색(황색)으로 킨다*/case 1: P0|=(E_GREEN); P0&=~E_YEL; break; /*동쪽에 파란색 불이 켜져있으면,동쪽에 파란불을 끄고 노란색(황색)으로 킨다.*/case 2: P2|=(S_GREEN); P2&=~S_YEL; break; /*남쪽에 파란색 불이 켜져있으면,남쪽에 파란불을 끄고 노란색(황색)으로 킨다.*/case 3: P1|=(W_GREEN); P1&=~W_YEL; break; /*서쪽에 파란색 불이 켜져있으면,서쪽에 파란불을 끄고 노란색(황색)으로 킨다.*/}}//void control_change(void){ /*신호등켜기를 시계방향으로 돌려서 다음차례에 대한 신호등을 켠다.*/switch(NEWS){case 0: P3|=N_YEL; P3&=~N_RED; P0&=~(E_GREEN); P0|=E_RED; P2&=~S_GREEN_M; P2|=S_RED_M; break; /*북쪽에 노란색불을 끄고 적색불을 키며,동쪽신호등에 파란불을켜며 적색불을 끄며,남쪽에 있는 횡단보도에 파란색불을 키고 적색불은 끈다.*/case 1: P0|=E_YEL; P0&=~E_RED; P2&=~(N_GREEN); P2|=N_RED; P1&=~W_GREEN_M; P1|=W_RED_M; break; /*동쪽에 노란색불을 끄고 적색불을 키며,남쪽신호등에 파란불을켜며 적색불을 끄며,서쪽에 있는 횡단보도에 파란색불을 키고 적색불은 끈다.*/case 2: P2|=S_YEL; P2&=~S_RED; P1&=~(W_GREEN); P1|=W_RED; P3&=~N_GREEN_M; P3|=N_RED_M; break; /*남쪽에 노란색불을 끄고 적색불을 키며,서쪽신호등에 파란불을켜며 적색불을 끄며,북쪽에 있는 횡단보도에 파란색불을 키고 적색불은 끈다.*/case 3: P1|=W_YEL; P1&=~W_RED; P3&=~(N_GREEN); P3|=N_RED; P0&=~E_GREEN_M; P0|=E_RED_M; break; /*서쪽에 노란색불을 끄고 적색불을 키며,북쪽신호등에 파란불을켜며 적색불을 끄며,동쪽에 있는 횡단보도에 파란색불을 키고 적색불은 끈다.*/}/*신호등 켜진 방향에 대한 내용 기록 변수인 NEWS 를+1 하여서 다음을 알리고,시간 계산 변수 count_sec 를 초기화 한다.*/NEWS=(NEWS++)&3;count_sec=0;}//void control_segment(unsigned char dt){switch(NEWS){case 0: E_7segment(dt); break; /*북쪽 도로가 통행일때 동쪽 횡단보도의 세그먼트 표시*/case 1: S_7segment(dt); break; /*동쪽 도로가 통행일때 남쪽 횡단보도의 세그먼트 표시*/case 2: W_7segment(dt); break; /*남쪽 도로가 통행일때 서쪽 횡단보도의 세그먼트 표시*/case 3: N_7segment(dt); break; /*서쪽 도로가 통행일때 북쪽 횡단보도의 세그먼트 표시*/}}//void T1_int(void)interrupt 3{ // 0x1B Timer 1 // 100u Sec interrupt rutif(++sec_500m>5000){ sec_500m=0; // 횡단 보도 깜빡이는 부분if(ON_OFF_CHK==1)control_on_off();}//if(++segment_cnt>20000){ segment_cnt=0; /*2초*/if(SEG_flag==1)control_segment(seg_data);seg_data--;}/*******************/if(++sec_1s>10000){count_sec++;if(count_sec==d_green_m ){ ON_OFF_CHK=1; SEG_flag=1; segment_cnt=0; seg_data=9; } /*횡단보도에서 파란색불에 대한 시간이 다되면,깜빡control_on_off()인다.세그먼트 카운트한다.*/else if(count_sec==d_green_m_on_off){ ON_OFF_CHK=0; SEG_flag=0; control_on_off_end(); } /*깜빡이는 시간이 다된다면,깜빡이던 횡단보도에 파란불을끄며,빨간불을킨다.*/else if(count_sec==d_green ){ control_yel(); } /*파란색불의 켜짐 시간이 다된다면,노란색불로 바꾼다.*/else if(count_sec==d_yel ){ control_change(); control_segment(9); } /*노란색(황색)불에대한 시간이 다된다면,적색으로 만들고 시계방향으로 이동한다.*/sec_1s=0;}}/*신호등은 시계방향으로 돌리는 것으로 한다.북쪽이 먼저 켜지며,다음엔 동쪽,다음엔 남쪽,다음엔 서쪽 순서로 한다.*/void main(){initialize();interrupt_init();control_segment(9);while(1);}
소스코드가 복잡하지만
신호등은 순차 제어라서 분석이 어렵지 않습니다.
잘 분석해서 원하는대로 수정해보세요
void control_change(void){ /*신호등켜기를 시계방향으로 돌려서 다음차례에 대한 신호등을 켠다.*/switch(NEWS){case 0: P3|=N_YEL; P3&=~N_RED; P0&=~(E_GREEN); P0|=E_RED; P2&=~S_GREEN_M; P2|=S_RED_M; break; /*북쪽에 노란색불을 끄고 적색불을 키며,동쪽신호등에 파란불을켜며 적색불을 끄며,남쪽에 있는 횡단보도에 파란색불을 키고 적색불은 끈다.*/case 1: P0|=E_YEL; P0&=~E_RED; P2&=~(N_GREEN); P2|=N_RED; P1&=~W_GREEN_M; P1|=W_RED_M; break; /*동쪽에 노란색불을 끄고 적색불을 키며,남쪽신호등에 파란불을켜며 적색불을 끄며,서쪽에 있는 횡단보도에 파란색불을 키고 적색불은 끈다.*/case 2: P2|=S_YEL; P2&=~S_RED; P1&=~(W_GREEN); P1|=W_RED; P3&=~N_GREEN_M; P3|=N_RED_M; break; /*남쪽에 노란색불을 끄고 적색불을 키며,서쪽신호등에 파란불을켜며 적색불을 끄며,북쪽에 있는 횡단보도에 파란색불을 키고 적색불은 끈다.*/// case 3: P1|=W_YEL; P1&=~W_RED; P3&=~(N_GREEN); P3|=N_RED; P0&=~E_GREEN_M; P0|=E_RED_M; break; /*서쪽에 노란색불을 끄고 적색불을 키며,북쪽신호등에 파란불을켜며 적색불을 끄며,동쪽에 있는 횡단보도에 파란색불을 키고 적색불은 끈다.*/}/*신호등 켜진 방향에 대한 내용 기록 변수인 NEWS 를+1 하여서 다음을 알리고,시간 계산 변수 count_sec 를 초기화 한다.*/if(++NEWS>2)NEWS=0;count_sec=0;}
단순히 서쪽방향을 주석처리하고
NEWS를 0~2까지 증가시켜서 되는 것이 아니라면
동작시키면서 디버깅하세요
댓글 0
조회수 3,107등록된 댓글이 없습니다.