C\C++/임베디드 시스템

임베디드시스템 간단한 택시미터기

sundori 2023. 11. 8. 23:57
#include <mega128.h>
#include <delay.h>
#define LED_CON               *((unsigned char *)0x8000) // LED Control bus
#define SET_CON              *((unsigned char *)0x8100) // FND, Buzzer, RELAY Control bus
#define LCD_CON          *((unsigned char *)0x8200) // TLCD, GLCD Control bus
#define LCD_DATABUS     *((unsigned char *)0x8300) // TLCD, GLCD, FND, Dotmatrix Data bus
#define DOT_YELLOW         *((unsigned char *)0x8400) // Dotmatrix Yellow LED
#define DOT_RED             *((unsigned char *)0x8500) // Dotmatrix Yellow RED
#define STEPMOR           *((unsigned char *)0x8600) // Stepping Motor Control bus
#define DCSERVO                  *((unsigned char *)0x8700) // DC, Servo Motor Control bus

#define FND1 2
#define FND2 3
#define FND3 4
#define FND4 5
#define FND1_ON (1<<FND1)
#define FND2_ON (1<<FND2)
#define FND3_ON (1<<FND3)
#define FND4_ON (1<<FND4)
#define FND1_OFF (0<<FND1)
#define FND2_OFF (0<<FND2)
#define FND3_OFF (0<<FND3)

#define FND4_OFF (0<<FND4)

char Num[11] = { 0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X27,0X7F,0X6F };  
//0~9 배열선언


int CountM, CountS;   // 카운팅 변수 (분 과 초를 이용해 가격으로 변동)
int TimeCount = 2000; // 2000ms 카운팅 (2초마다 100원씩 요금이 상승)
int stop = 0;         // 정지 변수     


interrupt[TIM0_OVF] void switch(void) // 타이머 오버플로우와 버튼선택 인터럽트
{
    static int cnt = 0; // cnt 선언     
    
    switch (PINB) { 
    case 0xfe: // 1번 버튼 (운행시 미터기 실행버튼)
        stop = 0;
        CountS = 0;
        CountM = 30;
        cnt = 0; 
        break;      
    case 0xfd: // 2번 버튼 (운행종료시 미터기를 정지해 가격이 오르지 않게함)    
        stop = 1;   
        break;            
    case 0xfb : // 3번 버튼 (미터기를 정지후 계속 이어나갈때 사용)
        stop = 0;
        break; 
    default: // 버튼이 눌리지 않을 때
        break;                                              
    }

    cnt++;  // 카운트 증가

    if (cnt == TimeCount) // 카운트가 3000ms가 됬을때
    {
        cnt = 0;
        CountS += 60;  // 1원의 카운트를 60올린다
        
        if (CountS == 60) // 1원의 카운트가 60
        {
            CountS = 0; // 초의 카운트는 다시 0
            CountM+=1;   // 분의 카운트가 2증가
             
               if (CountM == 99) //  카운트가 99이 됬을때 
            {  
                     LED_CON=0x01;  //만원이 넘어가는순간 led 왼쪽 첫번째 불이 들어와 만원이 넘었음을 알린다
                     
                     SET_CON=0xff;  // 버저 소리와 함께 만원이 넘었음을 알린다
            } 
            if (CountM == 100) //  카운트가 100이 됬을때 
            {  
            
                CountM = 0; // 분의 카운트는 다시 0 이되고 led 첫번쨰칸에 불이들어온다   들어온 불의 개수로 만원단위를 계산한다  } 
        }
    }
        
    TCNT0 += 0x06; 
    }
}

void main(void)
{

    DDRB = 0x00;  //PORTB INPUTPORT Set

    TCCR0 = 0x04;  //64Prescale, Overflow Interrupt Select
    TCNT0 = 0x06; //Timer Counter Register Init Value //256-6(6부터 시작하니까)
    TIMSK = 0x01; //timer0 Timer Overflow Interrupt Enable

    MCUCR = 0X80; //enable External memory and I/O control     
        
    LED_CON = 0X00;       // LED GLCD Control bus
    SET_CON = 0X00;       // FND, Buzzer, RELAY Control bus
    LCD_CON = 0X00;       // TLCD, GLCD Control bus
    LCD_DATABUS = 0X00;   // TLCD, GLCD, FND, Dotmatrix Data bus
    DOT_YELLOW = 0X00;    // Dotmatrix Yellow LED
    DOT_RED = 0X00;       // Dotmatrix Yellow RED
    STEPMOR = 0X00;       // Stepping Motor Control bus
    DCSERVO = 0X00;       // DC, Servo Motor Control bus     
    SREG = 0X80; //전역 인터럽트 허용  
    
    SREG = 0X80; //전역 인터럽트 허용  
    
    while (1)
    {   
        static int cnt = 0;  // 카운트변수
        static char j, k, l, m;  //분,초를 계산하여 넣는 변수
        cnt++; // 카운트 증가
        
        if(stop == 0)  // 시간을 멈추지 않았을때(정지변수 값이 0일때)
        {    
            j = CountM / 10;      //분의 10의자리
            k = (CountM % 10);    //분의 1의자리   
            l = CountS / 10;      //초의 10의자리 
            m = (CountS % 10);    //초의 1의자리  

            switch (cnt)
            {
                case 1: SET_CON = FND1_ON | FND2_OFF | FND3_OFF | FND4_OFF;
                    LCD_DATABUS = Num[j]; //분의 10의자리
                    break;
                case 2: SET_CON = FND2_ON | FND1_OFF | FND3_OFF | FND4_OFF;
                    LCD_DATABUS = Num[k]; //분의 1의 자리
                    break;
                case 3: SET_CON = FND3_ON | FND1_OFF | FND2_OFF | FND4_OFF;
                    LCD_DATABUS = Num[l]; //초의 10의 자리  
                    break;
                case 4: SET_CON = FND4_ON | FND1_OFF | FND2_OFF | FND3_OFF; 
                    LCD_DATABUS = Num[m]; //초의 1의 자리
                    break;
                default:cnt = 0; //cnt 초기화  
            }  
        }
        else  // 시간을 멈췄을때 (정지변수 값이 1일때)
        {
            switch (cnt)
            {
                case 1: SET_CON = FND1_ON | FND2_OFF | FND3_OFF | FND4_OFF;
                    LCD_DATABUS = Num[j]; //분의 10의자리
                    break;
                case 2: SET_CON = FND2_ON | FND1_OFF | FND3_OFF | FND4_OFF;
                    LCD_DATABUS = Num[k]; //분의 1의 자리
                    break;
                case 3: SET_CON = FND3_ON | FND1_OFF | FND2_OFF | FND4_OFF;
                    LCD_DATABUS = Num[l]; //초의 10의 자리  
                    break;
                case 4: SET_CON = FND4_ON | FND1_OFF | FND2_OFF | FND3_OFF; 
                    LCD_DATABUS = Num[m]; //초의 1의 자리
                    break;
                default:cnt = 0; //cnt 초기화  
            } 
            delay_ms(2); //FND 숫자 깔끔하게 표시하기위한 딜레이
        }
    }  
}