changheepark-dev / Digital-System-Lab

Atmega128
0 stars 0 forks source link

11-06-2023 #2

Open changheepark-dev opened 10 months ago

changheepark-dev commented 10 months ago
/*
 * 프로그램 이름 : EX3.c
 * 프로그램 내용 : LCD 스위치 버저 LED 인터럽트 타이머 UART 통신
 * Created: 2023-11-06 오후 6:17:00
 * Author : 1922288 박창희
 * 마지막 수정일 : 2023-11-06 오후 11:17:00
 * 마지막 수정내용 :타이머 내용 추가
 */ 

#define F_CPU 16000000UL    // 16MHz의 오실레이터를 사용
#include <avr/io.h> //입출력 포트 사용을 위한 헤더 include
#include <avr/delay.h>  //딜레이 사용을 위한 헤더 inlcude
#include <avr/interrupt.h>  //인터럽트 사용을 위한 헤더 include
#include "lcd.h"    //LCD 사용을 위한 헤더 include -> " "외부의 파일을 include
#include "uart.h"

/* 외부 인터럽트 */
volatile char value1=0;
ISR(INT0_vect)
{
    cli();
    if(!(PIND & (1<<PD0)))
    {
        value1 = (PORTB >> 4);
        PORTB = 0x00;
    }
}
void INTR_Init()
{
    EICRA = (0b10<<ISC00); //하강엣지 트리거
    EIMSK = (1<<INT0);  //인터럽트 0 허용
    PORTD |= (1<<PD0);  //스위치를 PORTD 0번에 연결
    sei();  //전역인터럽트 활성화
}
/* 외부 인터럽트 끝 */

/* 타이머 */
volatile int count = 0, count_m = 0;    //오버플로우가 발생한 횟수
ISR(TIMER1_COMPA_vect)
{
    count++;
    if (count > 30)
    {
        count_m++;
        LCDMove(1,12);
        LCD_nNum(count_m);
        if (count_m >= 999)
        {
            count_m = 0;
        }
        count = 0;
    }
}
void TIMER1_Init()
{
    TCCR1A = (0<<WGM11) | (1<<WGM10); 
    TCCR1B = (0<<WGM13) | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10);
    TIMSK |= (1 << OCIE1A);
    OCR1A = 128;
    sei();  //전역인터럽트 활성화
}
/* 타이머 끝 */

/*AD 변환*/
int readAnalog(unsigned char ch) // AD 채널 값을 받아서 AD를 값을 읽어오는 함수.
{
    int res;

    ADCSRA = 1<<ADEN | 0b111<<ADPS0;    // 128 분주율로 AD를 사용 인에이블 설정
    ADMUX = 0b01<<REFS0 | ch<<MUX0; // AREF를 기준전압으로 사용, AREF와 GND사이에 콘덴서 접속
    ADCSRA |= 1<<ADSC;  // A/D 변환 시작

    while((ADCSRA & (1<<ADIF))) {}  // A/D 변환완료인터럽트플래그비트 ADC 완료 대기

    res = ADC;  // 결과값을 res 변수에 넣음
    return res;
}

int LCD_nNum(unsigned int NUM)
{
    unsigned char Buff[8] = " 0";
    Buff[0] = '0'+((NUM %10000)/1000);
    Buff[1] = '0'+((NUM %1000)/100);
    Buff[2] = '0'+((NUM %100)/10);
    Buff[3] = '0'+(NUM %10);

    for (unsigned char i=0; i<=2; i++)
    {
        if (Buff[i] != '0')
        {
            break;
        }
        Buff[i]=' ';
    }
    Buff[4]= '\0';
    LCDPuts(Buff);
}

int main(void)
{
    DDRB |= 0xf0;   //7~4 LED 3~0 스위치가 연결되어 있다. 상위 니블 7~4까지는 출력을로 설정 하위 니블 3~0 입력으로 설정
    DDRG |= (1<<PG3);   //PG3번에 buzzer 연결되어있음

    static char LCD_Tittle[]="resistance";
    static char string[]="buzzer";
    MCU_Init(); //LCD 사용을 위한 MCU 설정
    LCDInit();  //LCD 사용을 위한 초기화 설정
    LCDMove(0,0);   //표시할 문자의 위치를 선택->HOME 위치
    LCDPuts(LCD_Tittle);
    LCDMove(1,0);   //LCD의 두번쨰 줄
    LCDPuts(string);

    INTR_Init();    // 인터럽트 사용을 위한 초기화
    TIMER1_Init();
    UART_INIT(); // UART 통신 초기화

    int analog = 0;
    unsigned char data=0;
    while (1) 
    {
        analog = readAnalog(6); //가변저항 ADC 6,7번에 연결
        LCDMove(0,12);  //home 위치
        LCD_nNum(analog);

        UART_transmit('a');

        LCDMove(1,6);   //home 위치
        LCD_nNum((PORTB >> 4));

        if(0 == (PINB & (1<<PB0))) {
            _delay_ms(200); //디바운싱을 해결하기위해
            PORTB = PORTB ^ 0x10;
        }
        if(0 == (PINB & (1<<PB1)))
        {
            _delay_ms(200); //디바운싱을 해결하기위해
            PORTB = PORTB ^ 0x20;
        }
        if(0 == (PINB & (1<<PB2)))
        {
            _delay_ms(200); //디바운싱을 해결하기위해
            PORTB = PORTB ^ 0x40;
        }
        if(0 == (PINB & (1<<PB3)))
        {
            _delay_ms(200); //디바운싱을 해결하기위해
            PORTB = PORTB ^ 0x80;
        }

        if(value1 > 0)
        {
            for (int b = value1 ; b > 0 ; b--)
            {   
                PORTG |= (1<<PG3);  //buzzer ON
                _delay_ms(100);
                PORTG &= ~(1<<PG3); //buzzer OFF
                _delay_ms(100);
            }
            value1=0;
        }
    }
}