BASIC4MCU | 질문게시판 | ATmega128 / HC-05블루투스 시리얼 모듈을 사용한 블루투스 통신 질문 있습니다..
페이지 정보
작성자 범용직렬버스장치 작성일2021-12-01 19:27 조회1,732회 댓글2건본문
길게 고민해보다 조언 얻고자 글 올려봅니다. 도움주시면 정말 감사드리겠습니다.
스마트폰 앱(HC-05 bluetooth terminal)을 통해서,
도 래 미 파 솔 라 시 높은도에 미리 값을 정해놓고, (저는 도에 1 래에 2 미에 3과 같이 설정해두었습니다.)
스마트폰을 통해서 그 정해진 값을 입력받으면, 피에조 버저를 통해서
도 래 미 파 솔 라 시 높은도 가 나오도록 해보려 하는데..
안 나옵니다.
통신이 안 되는 걸까?
- 통신이 잘 이루어 지는지 '0'을 입력받으면 LED가 켜지도록 해놓았는데 이건 잘 됩니다.
버저가 울리도록 하는 코드가 잘못되었는가?
- 원하는 음을 만들기 위해 오버플로우 인터럽트를 사용해보았습니다.
switch 문에서 tone 값을 입력받고(각 음에 맞는 TCNT0값을 미리 배열로 선언해둠)
인터럽트 서비스 루틴에서 펄스(원하는 음에 맞는 펄스)를 형성하고
이것을 길게 음으로 내기 위해 if (!available()) 를 사용하면서 TCNT0 값을 다시 써놓는 것으로,
그 클록 만큼 지난 후에 다시 TCNT0오버플로우 인터럽트가 또 발생되면서 반복적으로 처리되도록 해보았습니다.
그런데 안 됩니다.. 무엇에 문제가 있는걸까요?
ATmega128A 사용중이며
+ microchip studio사용하여 코드 작성중입니다.
+추가로 이 단계를 거쳐서
정해진 값이 아닌, 도 래 미 파 솔 라 시 높은도 의 각 값을 스마트폰으로 정해보려 했는데..
막혀버렸습니다..
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <avr/io.h>
#define F_CPU 16000000UL
#define __DELAY_BACKWARD_COMPATIBLE__
// Atmel Studio 7을 사용하는 경우에 필요
#include <util/delay.h>
#define ON 1
#define OFF 0
char f_table[]={17,43,66,77,97,114,117,137,255}; //도레미파솔라시도와 묵음에 해당하는 TCNT0값을 미리 계산한 값
//char f_table[]={1047, 1175, 1319, 1397, 1568, 1760, 1976, 2093};
#define DO 0
#define RE 1
#define MI 2
#define FA 3
#define SOL 4
#define RA 5
#define SI 6
#define DDO 7
volatile int x;
volatile int state, tone;
void putchar1(char c) // 1 문자를 송신(Transmit)하는 함수
{
while(!(UCSR1A & (1<<UDRE1))) // UDRE1 : UCSR1A 5번 비트,
; // 즉,1을 5번 왼쪽으로 shift한 값이므로 0x20과 &
UDR1 = c; // 1 문자 전송, 송신 데이터를 UDR1에 넣음
}
char available() // 문자 입력을 확인하는 함수
{
if (UCSR1A & (1<<RXC1)) // 입력된 문자가 있는지 확인
return(1); // 입력된 문자가 있으면 "1"의 값으로 return
else return(0); // 입력된 문자가 없으면 "0"의 값으로 return
}
char getchar1() // 1 문자를 수신(receive)하는 함수
{
return(UDR1); // 1 문자 수신, UDR1에서 수신 데이터를 가져옴
}
void init_uart1() // UART1 초기화 함수
{
UCSR1B = 0x18; // 송신 Transmit(TX), Receive(RX) Enable
UCSR1C = 0x06; // UART Mode, 8Bit Data, No Parity, 1 Stop Bit
UBRR1H = 0; // Baudrate 세팅
UBRR1L = 8; // 16Mhz, 115200 baud (주의 :초기 셋팅 값 확인)
}
/*
void buzzer(int hz, int count) // hz의 주파수를 갖는 펄스를 count 개수만큼 생성
{
int i, ms, us;
ms = 1000/(2*hz); // 1개 펄스의 ON 또는 OFF의 ms 단위
us = (1000.0/(2*hz) - 1000/(2*hz)) * 1000;
// 1개 펄스의 ON 또는 OFF의 us 단위
for(i=0; i<count; i++)
{
PORTE |= 1 << 4; // buzzer ON
_delay_ms(ms); // (ms)ms동안 delay
_delay_us(us); // (us)us 동안 delay
PORTE &= ~(1 << 4); // buzzer OFF
_delay_ms(ms); // (ms)ms 동안 delay
_delay_us(us); // (us)us 동안 delay
}
}
void BUZZER_Control()
{
// int i;
// for(i=0; i<2; i++) // 0,1초 정도 짧은 경고음.
// 2개 주파수의 소리 혼합 생성
// {
buzzer(f_table[x], 500); // 480 Hz로 12회
// buzzer(1046, 8); // 320 Hz로 8회
// }
}
*/
ISR(TIMER0_OVF_vect) //Timer/Counter0 오버플로우 인터럽트 서비스 루틴
{
TCNT0= f_table[tone]; //TCNT0 초기화 (주어진 음을 만들기 위한)
if(state==OFF)
{
PORTE |= 1<<4; //버저 포트 ON
state =ON;
}
else
{
PORTE &= ~(1<<4); //버저 포트OFF
state =OFF;
}
}
int main()
{
char c;
int st_light=OFF, st_buzz=OFF; // 전등, 버저, 선풍기 초기 상태
DDRA = 0x0f; // 전등(LED) 포트 = PA3~PA0 : 출력
DDRE = 0x10; // 경고음(버저) 포트 = PE4
TCCR0 =0x03; //프리스케일러 32분주로 설정
TIMSK =0x01; //오버플로우 인터럽트 활성화, TOIE0비트를 set
init_uart1(); // UART1 초기화
while(1) // 명령을 받아서 실행
{
if (!available()) // 만약 입력된 문자가 없으면
{
if (tone == DO) // 버저 ON 상태를 확인한 후 계속 버저 울림
TCNT0=f_table[DO];
else if (tone == RE) // 버저 ON 상태를 확인한 후 계속 버저 울림
TCNT0=f_table[RE];
else if (tone == MI) // 버저 ON 상태를 확인한 후 계속 버저 울림
TCNT0=f_table[MI];
else if (tone == FA) // 버저 ON 상태를 확인한 후 계속 버저 울림
TCNT0=f_table[FA];
else if (tone == SOL) // 버저 ON 상태를 확인한 후 계속 버저 울림
TCNT0=f_table[SOL];
else if (tone == RA) // 버저 ON 상태를 확인한 후 계속 버저 울림
TCNT0=f_table[RA];
else if (tone == SI) // 버저 ON 상태를 확인한 후 계속 버저 울림
TCNT0=f_table[SI];
else if (tone == DDO) // 버저 ON 상태를 확인한 후 계속 버저 울림
TCNT0=f_table[DDO];
continue; // while 문 맨 처음으로 되돌아감
}
c = getchar1(); // 입력된 문자를 스마트폰으로부터 받아서
putchar1(c); // echo back 후
switch(c) // 명령의 종류에 따라 아래를 실행
{
case '0' : PORTA = 0x0f; st_light = ON; break; // 전등 ON
case '1' : tone=DO; TCNT0=f_table[DO]; break;
case '2' : tone=RE; TCNT0=f_table[RE]; break;
case '3' : tone=MI; TCNT0=f_table[MI]; break;
case '4' : tone=FA; TCNT0=f_table[FA]; break;
case '5' : tone=SOL; TCNT0=f_table[SOL]; break;
case '6' : tone=RA; TCNT0=f_table[RA]; break;
case '7' : tone=SI; TCNT0=f_table[SI]; break;
case '8' : tone=DDO; TCNT0=f_table[DDO]; break;
default : break;
}
}
}
댓글 2
조회수 1,732범용직렬버스장치님의 댓글
범용직렬버스장치 작성일+피에조 버저를 출력으로 연결한 포트가 E포트인것을 수정하였습니다.
범용직렬버스장치님의 댓글
범용직렬버스장치 작성일
수정을 거쳤습니다. 소리는 정상적으로 나오지만,
소리가 계속 나오는 것이 아닌 500ms만 나오도록 해보려 하는데.. TCNT0 뒤에 딜레이를 놓는것으로 해결되지 않습니다..
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#define __DELAY_BACKWARD_COMPATIBLE__
// Atmel Studio 7을 사용하는 경우에 필요
#include <util/delay.h>
#define ON 1
#define OFF 0
char f_table[]={17,43,66,77,97,114,117,137,255}; //도레미파솔라시도와 묵음에 해당하는 TCNT0값을 미리 계산한 값
//char f_table[]={1047, 1175, 1319, 1397, 1568, 1760, 1976, 2093};
#define DO 0
#define RE 1
#define MI 2
#define FA 3
#define SOL 4
#define RA 5
#define SI 6
#define DDO 7
#define N4 625
volatile int state=OFF;
volatile int tone;
unsigned char rx;
void putchar1(char c) // 1 문자를 송신(Transmit)하는 함수
{
while(!(UCSR1A & (1<<UDRE1))) // UDRE1 : UCSR1A 5번 비트,
; // 즉,1을 5번 왼쪽으로 shift한 값이므로 0x20과 &
UDR1 = c; // 1 문자 전송, 송신 데이터를 UDR1에 넣음
}
char getchar1() // 1 문자를 수신(receive)하는 함수
{
while (!(UCSR1A & (1<<RXC1)))
; // UCSR0A 7번 비트, RXC의 define 값 = 7
// 즉, 1을 7번 왼쪽으로 shift한
// 값이므로 0x80과 & 하는 효과가 있음
return(UDR1); // 1 문자 수신, UDR0에서 수신 데이터를 가져옴
}
ISR(TIMER0_OVF_vect) //Timer/Counter0 오버플로우 인터럽트 서비스 루틴
{
TCNT0= f_table[tone]; //TCNT0 초기화 (주어진 음을 만들기 위한)
if(state==OFF)
{
PORTE |= 1<<4; //버저 포트 ON
state =ON;
}
else
{
PORTE &= ~(1<<4); //버저 포트OFF
state =OFF;
}
}
void init_uart1() // UART1 초기화 함수
{
UCSR1B = 0x18; // 송신 Transmit(TX), Receive(RX) Enable
UCSR1C = 0x06; // UART Mode, 8Bit Data, No Parity, 1 Stop Bit
UBRR1H = 0; // Baudrate 세팅
UBRR1L = 8; // 16Mhz, 115200 baud (주의 :초기 셋팅 값 확인)
}
int main()
{
char c; // 전등(LED) 포트 = PA3~PA0 : 출력
DDRE |= 0x10;
sei();
TCCR0 =0x03; //프리스케일러 32분주로 설정
TIMSK =0x01; //오버플로우 인터럽트 활성화, TOIE0비트를 set
init_uart1(); // UART1 초기화
sei();
while(1) // 명령을 받아서 실행
{ // echo back 후
c = getchar1(); // 입력된 문자를 스마트폰으로부터 받아서
putchar1(c);
switch(c) // 명령의 종류에 따라 아래를 실행
{ // 전등 ON
case '1' : tone=DO; TCNT0=f_table[DO]; _delay_ms(625); break;
case '2' : tone=RE; TCNT0=f_table[RE]; _delay_ms(625); break;
case '3' : tone=MI; TCNT0=f_table[MI]; _delay_ms(625); break;
case '4' : tone=FA; TCNT0=f_table[FA]; _delay_ms(625); break;
case '5' : tone=SOL; TCNT0=f_table[SOL]; _delay_ms(625); break;
case '6' : tone=RA; TCNT0=f_table[RA]; _delay_ms(625); break;
case '7' : tone=SI; TCNT0=f_table[SI]; _delay_ms(625);break;
case '8' : tone=DDO; TCNT0=f_table[DDO]; _delay_ms(625); break;
default : break;
}
}
}