ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Microchip Studio를 통해 아두이노에 프로그램 업로드 하기 (버튼, 피에조 부저 제어)
    Arduino/Atmel Studio 2021. 1. 4. 18:07

    아래의 내용을 이어서 진행해보자.

    designatedroom87.tistory.com/355?category=914742

     

    Microchip Studio를 통해 아두이노에 프로그램 업로드 하기 (LED 제어)

    MPU가 제거되지 않은 아두이노를 연결한다. 아두이노 프로그램을 띄운다. 툴에서 기본적인 세팅은 아래와 같다. 아두이노 보드를 테스트 하자. 앞 장에서와 같이 예제 소스 파일을 하나 띄우자.

    designatedroom87.tistory.com

     

    앞에서는 출력만 했다. 이번에는 입력을 알아보자. ( 아래와 같이 구성하면 문제점이 있다. )
    DDR을 0으로 설정한다.
    PORT가 아닌, PIN을 통해 읽어들인다.
    PIN은 오직 읽기만 가능한 레지스터이다.

    버튼을 연결해보자. 

    하드웨어의 연결 사진은 아래에 있다.
    LED는 13번핀에 연결하고, 저항은 220옴이다.
    버튼은 위쪽에는 12번핀(흰색선)에 연결하고, 나머지 한 선은 5V선(붉은선)에 연결한다.
    PB0는 8번핀이다. PB1은 9번핀이다. PB4 ~ PB5는 각 각 12번 13번핀이다.

    0           b          0            0         1         0           0          0        0             0 
                                                  PB5      PB4

     

    즉, 13번핀은 출력, 12번핀은 입력으로 DDR을 설정해야 한다.
    DDR의 설정은 0x20으로 하면 된다.
    그러면 PB5는 1로, PB4는 0으로 설정이 된다.

     

     

     

     

    소스 파일

    위의 방식대로 하면 되지 않는다.

    즉, 아래와 같이 해야 한다.

     

     

     

     

    버튼을 아두이노의 D2핀에 연결하고, GND에 연결해야 한다.
    인터럽트 핀은 정해져 있다.

    버튼의 흰색선은 D2핀에 연결한다. 붉은색선은 GND에 연결한다.

    하드웨어의 연결은 아래와 같다.

     

     

     

    소스 파일1

    더보기
    #include <avr/io.h>
    #define F_CPU 16000000UL	//	16MHz
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    /*	레지스터 설정	*/
    void INIT_PORT()
    {
    	DDRB = 0x20;	//	D13번핀을 출력으로 설정
    	PORTB = 0x00;	//	D13번핀을 출력 0v
    	
    	DDRD = 0x00;	//	버튼 입력 설정
    	PORTD = 0x04;	//	D2번핀(인터럽트핀) 풀업저항 설정
    }
    
    void INIT_INT0()
    {
    	//	EICRA, INT0, EIMSK, ISC00는 모두 레지스터이다.
    	EICRA |= ( 1 << INT0);		//	인터럽트 활성화
    	EIMSK |= ( 1 << ISC00 );	//	버튼 상태 변화 감지
    	sei();						//	전역적으로 인터럽트 허용
    }
    
    /*	
    	인터럽트를 처리하는 함수(Interrupt Service Routine)이다.
    	하드웨어 변화가 있을 때 호출된다.	
    	함수는 아래와 같이 그 정의가 정해져 있다.
    	시스템이 호출하는 함수이다.
    	아두이노에서는 인터럽트를 담당하는 핀은 D2(INT0), D3(INT1)번핀이다.
    	버튼을 D2핀에 연결하고 GND에 연결해야 한다.
    */
    ISR(INT0_vect)
    {
    	if ( (PIND & 0x04) == 0x04 )	PORTB = 0x00;	//	LED ON
    	else							PORTB = 0x20;	//	LED OFF
    }
    
    int main(void)
    {
        /* Replace with your application code */
    	
    	INIT_PORT();	//	포트 설정
    	INIT_INT0();	//	인트럽트 설정
    	
        while (1) 
        {
    		
        }
    }

     

    위의 소스 파일을 이해하기 어려우면 아래의 내용을 보도록 하자.

    내용을 조금 풀어서 썼다.

    소스 파일2

    더보기
    #include <avr/io.h>
    #define F_CPU 16000000UL	//	16MHz
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    /*	
    	인터럽트를 처리하는 함수(Interrupt Service Routine)이다.
    	하드웨어 변화가 있을 때 호출된다.	
    	함수는 아래와 같이 그 정의가 정해져 있다.
    	시스템이 호출하는 함수이다.
    	아두이노에서는 인터럽트를 담당하는 핀은 D2(INT0), D3(INT1)번핀이다.
    	버튼을 D2핀에 연결하고 GND에 연결해야 한다.
    */
    ISR(INT0_vect)
    {
    	if ( (PIND & 0x04) == 0x04)		PORTB = 0x00;	//	LED ON
    	else							PORTB = 0x20;	//	LED OFF
    }
    
    int main(void)
    {
        /* Replace with your application code */
    	
    	DDRB = 0x20;	//	D13번핀을 출력으로 설정
    	PORTB = 0x00;	//	D13번핀을 출력 0v
    	
    	DDRD = 0x00;	//	버튼 입력 설정
    	PORTD = 0x04;	//	D2번핀(인터럽트핀) 풀업저항 설정
    	
    	//	EICRA, INT0, EIMSK, ISC00는 모두 레지스터이다.
    	//EICRA |= ( 1 << INT0);		//	인터럽트 활성화
    	EICRA |= 0b00000001;
    	//EIMSK |= ( 1 << ISC00 );	//	버튼 상태 변화 감지
    	EIMSK |= 0b00000001;		//	논리적인 변화가 생겼을 때
    	sei();						//	전역적으로 인터럽트 허용
    	
        while (1) 
        {
    		//if ( PIND & 0x04 ) PORTB = 0x20;
    		//else               PORTB = 0x00;
        }
    }

     

     

     

    이번에는 버튼을 하나 더 연결해보자. ( 버튼 하나는 동작하지 않는다. )

    하드웨어의 연결을 보자.

    추가가 된 버튼은 아래쪽의 버튼이다. 남색선은 아두이노의 D3번핀에 연결하고,

    주황색선은 GND에 연결한다.

     

     

     

     

    소스 파일

    더보기
    #include <avr/io.h>
    #define F_CPU 16000000UL	//	16MHz
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    /*	
    	인터럽트를 처리하는 함수(Interrupt Service Routine)이다.
    	하드웨어 변화가 있을 때 호출된다.	
    	함수는 아래와 같이 그 정의가 정해져 있다.
    	시스템이 호출하는 함수이다.
    	아두이노에서는 인터럽트를 담당하는 핀은 D2(INT0), D3(INT1)번핀이다.
    	버튼을 D2핀에 연결하고 GND에 연결해야 한다.
    */
    ISR(INT0_vect)
    {
    	if ( (PIND & 0x04) )		PORTB = 0x00;	//	LED ON
    	else						PORTB = 0x20;	//	LED OFF
    }
    
    /*	ISR도 하나 더 만들어야 한다.	*/
    ISR(INT1_vect)
    {
    	if ( (PIND & 0x08) )		PORTB = 0x00;	//	LED ON
    	else						PORTB = 0x20;	//	LED OFF
    }
    
    int main(void)
    {
        /* Replace with your application code */
    	
    	DDRB = 0x20;	//	D13번핀을 출력으로 설정
    	PORTB = 0x00;	//	D13번핀을 출력 0v
    	
    	DDRD = 0x00;	//	버튼 입력 설정
    	PORTD = 0x0C;	//	D3번핀과 D2번핀을 같이 사용
    	
    	//	EICRA, INT0, EIMSK, ISC00는 모두 레지스터이다.
    	//EICRA |= ( 1 << INT0);		//	인터럽트 활성화
    	EICRA |= 0b00000101;
    	//EIMSK |= ( 1 << ISC00 );	//	버튼 상태 변화 감지
    	EIMSK |= 0b00000001;		//	논리적인 변화가 생겼을 때
    	sei();						//	전역적으로 인터럽트 허용
    	
        while (1) 
        {
    		//if ( PIND & 0x04 ) PORTB = 0x00;
    		//else               PORTB = 0x20;
    		
    		//if ( PIND & 0x08 ) PORTB = 0x00;
    		//else               PORTB = 0x20;
        }
    }

     

     

     

     

    부저를 다음과 같이 연결하자.

    부저는 PB4를 출력핀으로 나머지는 GND에 연결하면 된다.

    즉, 2진수로 표현하면,

    0 b      0              0             0            1            0             0             0              0

                                                        PB4

     

    그러면, 16진수로는 0x10로 표현된다. PB4는 아두이노에서 D12번핀에 맵핑된다.

    부저와 아두이노의 12번핀과 연결하고 나머지는 GND와 연결한다.

    아래에서 남색선은 12번핀에 연결된 선이고, 노란색선은 GND와 연결된 선이다.

    designatedroom87.tistory.com/251?category=899738

     

    피에조 부저와 아두이노를 연결해서 여러 음을 출력하기

    부저와 아두이노의 하드웨어 연결 부저를 자세히 보면, 부저에 (+) 모양이 보인다. 이 (+)모양의 선을 아두이노의 9번핀으로 연결한다. 그 밑에 있는 검은 선은 아두이노의 GND에 연결한다. 부저를

    designatedroom87.tistory.com

     

    아래는 피에조 부저와 아두이노의 하드웨어 연결이다.

     

     

     

    소스 파일

     

     

     

    그리고, 피에조 부저를 이용해서 전화벨음을 만들어보자.

     

    소스 내용

    더보기
    /*	전화벨음 만들기	*/
    #define F_CPU 16000000UL	//	16MHz
    #define __DELAY_BACKWARD_COMPATIBLE__ //AVR4를 쓰는 경우는 필요 없음
    #include <avr/io.h>
    #include <util/delay.h>
    
    /*	매개변수는 주파수		*/
    void Buzzer(int hz, int count);
    
    int main(void)
    {
    	int i;
    	
    	DDRB = 0x10;	//	PB4(D12번핀)를 출력으로 설정
    	 
        while (1) 
        {
    		//	1초 동안 2개 주파수의 소리 혼합 생성
    		for ( i = 0; i < 20; i++ )
    		{
    			Buzzer(480, 12);	//	480Hz로 12회
    			Buzzer(320,8);		//	320Hz로 8회
    		}
    		_delay_ms(2000);		//	2초 딜레이로 2초 동안 묵음을 표현
        }
    }
    
    /*	매개변수는 주파수		*/
    void Buzzer(int hz, int count)
    {
    	int i, sec, ms, us;		//	ms는 10^(-3), us = 10^(-6) 이다. us는 마이크로 세컨드
    	
    	sec = 1 / ( 2 * hz );	//	2로 나누는 이유는 한 주기가 아닌, 반 주기만 설정
    	
    	//	1개 펄스의 ON 또는 OFF의 ms 단위 시간						
    	ms = 1000 / ( 2 * hz );	//	hz는 초당 진동수이므로, ms로 계산하기 위해 1000을 곱함
    	
    	//	1개 펄스의 ON 또는 OFF의 us 단위 시간							
    	us = (1000.0 / ( 2 * hz )  - 1000 / ( 2 * hz ) * 1000 );
    	
    	for ( i = 0; i < count; i++ )
    	{
    		PORTB |= 1 << 4;			//	buzzer on
    		_delay_ms(ms);				//	(ms)ms동안 delay
    		_delay_us(us);				//	(us)us동안 delay
    		
    		PORTB &= ~( 1 << 4 );		//	buzzer off
    		_delay_ms(ms);				//	(ms)ms동안 delay
    		_delay_us(us);				//	(us)us동안 delay
    	}
    }

     

     

     

     

     

    소스 내용

    더보기
    #define F_CPU 16000000UL	//	16MHz
    #define __DELAY_BACKWARD_COMPATIBLE__ //AVR4를 쓰는 경우는 필요 없음
    #include <avr/io.h>
    #include <util/delay.h>
    
    /*	매개변수는 주파수		*/
    void Buzzer(int hz, int count);
    
    int main(void)
    {
    	int i, j;
    	
    	DDRB = 0x10;	//	PB4(D12번핀)를 출력으로 설정
    	
    	const int hertz[] = { 1047, 1175, 1319, 1397, 1568, 1760, 1795, 2093 };
    	const int loop[] = { 1047, 1175, 1319, 1397, 1568, 1760, 1795, 2093 };	
    	 
        while (1) 
        {
    		//	1초 동안 2개 주파수의 소리 혼합 생성
    		for ( i = 0; i < 8; i++ )
    		{
    			Buzzer( hertz[i], loop[i] );	//	도~도 음 생성. 1초간
    			_delay_ms(1000);				//	도~도 음 생성 후, 1초 동안 묵음
    		}
        }
    }
    
    /*	매개변수는 주파수		*/
    void Buzzer(int hz, int count)
    {
    	int i, sec, ms, us;		//	ms는 10^(-3), us = 10^(-6) 이다. us는 마이크로 세컨드
    	
    	sec = 1 / ( 2 * hz );	//	2로 나누는 이유는 한 주기가 아닌, 반 주기만 설정
    	
    	//	1개 펄스의 ON 또는 OFF의 ms 단위 시간						
    	ms = 1000 / ( 2 * hz );	//	hz는 초당 진동수이므로, ms로 계산하기 위해 1000을 곱함
    	
    	//	1개 펄스의 ON 또는 OFF의 us 단위 시간							
    	us = (1000.0 / ( 2 * hz )  - 1000 / ( 2 * hz ) * 1000 );
    	
    	for ( i = 0; i < count; i++ )
    	{
    		PORTB |= 1 << 4;			//	buzzer on
    		_delay_ms(ms);				//	(ms)ms동안 delay
    		_delay_us(us);				//	(us)us동안 delay
    		
    		PORTB &= ~( 1 << 4 );		//	buzzer off
    		_delay_ms(ms);				//	(ms)ms동안 delay
    		_delay_us(us);				//	(us)us동안 delay
    	}
    }

    댓글

Designed by Tistory.