Ðăng Nhập

View Full Version : Làm sao tạo ra âm thanh?


phamminh05
30-11-2008, 06:07 PM
Em là 1 newbie,đang viết 1 chương trình nho nhỏ bằng MCC18,đồng hồ có chức năng hẹn giờ(các nút chức năng gần giống với cái đồng hồ Casio).Khi đến giờ đã hẹn,nó sẽ phát âm thanh ra loa.Nhưng em đang gặp phải 2 vấn đề là:
1.Em dùng ngắt INT0 đề chuyển từ chế độ đồng hồ sang chế độ hẹn giờ(thể hiện qua button: ALARM IN trên mạch Proteus kèm theo) nhưng không hiểu vì sao nó không chuyển qua được.
2.Không biết viết hàm play_sound như thế nào để tạo ra âm thanh?
Mấy pro giúp giùm em với,cám ơn rất rất nhiều.

#include<p18f4550.h>
#include<timers.h>
#pragma config WDT=OFF, PWRT=OFF, LVP=OFF, CP0=OFF, CP1=OFF,CP2=OFF,CP3=OFF, WRT0=OFF,WRT1=OFF,WRT2=OFF,WRT3=OFF
#pragma config WRTB=OFF,WRTC=OFF,WRTD=OFF,EBTR0=OFF,EBTR1=OFF,EBT R2=OFF,EBTR3=OFF,EBTRB=OFF

void init(void);
void led(unsigned char x);
void interrupt_timer0(void);//se thiet lap timer0 co interrupt la cao
//void interrupt_timer1(void);//se thiet lap timer1 co interrupt la thap
void global_int(void);
void play_sound(void);
void int0_external(void);
static unsigned char table[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10 };
unsigned char count = 0;
unsigned char mi0; //phut
unsigned char mi1;
unsigned char ho0; //gio
unsigned char ho1;
unsigned char mi02; //hen gio cho phut
unsigned char mi12;
unsigned char ho02; //hen gio cho gio
unsigned char ho12;
unsigned char test; //chuyen che do giua hen gio va dong ho
unsigned char mode; //chon chinh gio,chinh phut hay khong chinh gi ca


#pragma code high_vector = 0x08
void high_vector (void){
_asm
GOTO int0_external
_endasm
}

#pragma code low_vector = 0x18
void low_interrupt(void){
//if(INTCONbits.TMR0IF) interrupt_timer0();
//if(PIR1bits.TMR1IF) interrupt_timer1();
_asm
GOTO interrupt_timer0
_endasm
}
#pragma code
#pragma interrupt int0_external
void int0_external(void){
//INTCONbits.INT0IF = 0;
test = 1; // chuyen qua hen gio
mi02 = 0;
mi12 = 0;
ho02 = 0;
ho12 = 0;
while(1){
if(PORTAbits.RA1 == 0){//chon mode:chinh gio hoac phut hoac khong chinh gi
if(PORTAbits.RA0 == 0)//thoat khoi vong lap
break;
mode++;
mode = mode%3;
if(mode == 0){//khong chinh:2 den led bao hieu khong sang
PORTAbits.RA3 = 0;//2 led gan o 2 chan 3,4 cua PORTA dung de bao hieu cho nguoi dung biet dang chon o mode nao
PORTAbits.RA4 = 0;
}
if(mode == 2){//chinh phut
PORTAbits.RA3 = 0;//den led bao hieu dang chinh o phut se sang
PORTAbits.RA4 = 1;

while(1){
if(PORTAbits.RA2 == 0){ //nut thu 3 dung de chinh tang len 1 don vi
if(PORTAbits.RA1 == 0)
break;
if(mi02 >= 9){
mi02 = 0;
if(mi12 >= 5){
mi12 = 0;
}
else
mi12++;
}else
mi02++;
}
}
}

if(mode == 1){ //chinh gio
PORTAbits.RA3 = 1;//den led bao hieu dang o chinh o gio se sang
PORTAbits.RA4 = 0;
while(1){
if(PORTAbits.RA2 == 0){
if(PORTAbits.RA1 == 0)
break;
if((ho02 >= 9)&&(ho12 == 0)){
ho02 = 0;
ho1++;
}else if((ho02 >=4)&&(ho12 == 2)){
ho02 = 0;
ho12 = 0;
}
else
ho02++;
}
}
}

}
}
test = 0;//ve dong ho binh thuong
}

/*void interrupt_timer1(void){
PIR1bits.TMR1IF = 0;
if(count > 3){
count = 0;
}
led(count);
count++;
}*/
#pragma interruptlow interrupt_timer0
void interrupt_timer0(void){
INTCONbits.TMR0IF = 0;
if(mi0 >= 9){ //vao luc xx:x9
mi0 = 0;
if(mi1 >= 5){ //vao luc xx:59
mi1 = 0;
if((ho0 >= 9)&&(ho1 == 0)){ //vao luc x9:59
ho0 = 0;
ho1++;
}else if((ho0 >=4)&&(ho1 == 2)){
ho0 = 0;
ho1 = 0;
}else
ho0++;
}
else
mi1++;
}
else
mi0++;
}

void led(unsigned char x){
if(test == 0){ //hien thi dong ho
if(x == 0){ //se hien thi o led chi phut thu nhat(led so 0)
PORTD = table[mi0];
//PORTDbits.RD0 = 1; // day la code dung de quet led,chuong trinh se quet led tu phai(led so 0) qua trai(led so 3)
//PORTDbits.RD1 = 0;
//PORTDbits.RD2 = 0;
//PORTDbits.RD3 = 0;
PORTC = 0x10; //dien giai chi tiet ra la 3 dong o tren,hay 3 dong o tren tuong duong voi dong nay

}
else if(x == 1){ //se hien thi o led chi phut thu hai(led so 1)
PORTD = table[mi1];
PORTC = 0x20;
}
else if(x == 2){ // se hien thi o led chi gio thu nhat(led so 2)
PORTD = table[ho0];
PORTC = 0x40;
}
else{ // x == 3 // se hien thi o led chi gio thu hai(led so 3)
PORTD = table[ho1];
PORTC = 0x80;
}
}
if(test == 1){//hien thi o che do hen gio
if(x == 0){
PORTD = table[mi02];
PORTC = 0x10;
}
if(x == 1){
PORTD = table[mi12];
PORTC = 0x20;
}
if(x == 2){
PORTD = table[ho02];
PORTC = 0x40;
}
if(x == 3){
PORTD = table[ho12];
PORTC = 0x80;
}
}


}
void play_sound(void){
}

void init(void){
mi0 = 0;
mi1 = 0;
ho0 = 0;
ho1 = 0;
mi02 = 0;
mi12 = 0;
ho02 = 0;
ho12 = 0;
test = 0;
mode = 0;


//OpenTimer1( TIMER_INT_ON &T1_16BIT_RW &T1_SOURCE_INT &T1_PS_1_1 &T1_OSC1EN_OFF &T1_SYNC_EXT_OFF );
OpenTimer0 (TIMER_INT_ON & T0_SOURCE_INT & T0_16BIT & T0_PS_1_8);
INTCON2bits.TMR0IP = 0; //ngat timer0 la uu tien cao
INTCONbits.INT0IE = 1;
INTCON2bits.INTEDG0 = 0;
//IPR1bits.TMR1IP = 0; //ngat timer1 la uu tien thap
TMR0L = 0xFF;//chay thoi gian
TMR0H = 0xFF;
//TRISB = 0xFF;
TRISD = 0x00;
TRISA = 0x07; // 0b0000 0111 => PORTAbits.RA0-1-2 :dung de input nen bang 1
TRISC = 0x00;

}
void global_int(void){
RCONbits.IPEN = 1;
INTCONbits.GIEH = 1;
INTCONbits.GIEL = 1;
}

void main(){
global_int();
init();
while(1){
int i;
for(i = 0;i<2000;i++){//delay
i++;
}
if(count > 3){
count = 0;
}
led(count);
count++;
//if((mi0 == mi02)&&(mi1 == mi12)&&(ho0 == ho02)&&(ho1 == ho12)){
// play_sound();
//}
}
}

namqn
30-11-2008, 07:19 PM
Không rõ bạn muốn phát âm thanh phức tạp, hay chỉ cần beep để báo thức. Nếu chỉ cần một tiếng beep đơn giản để báo thức thì bạn có thể dùng các buzzer có thể mua dễ dàng ngoài chợ. Một số buzzer có sẵn driver bên trong, do đó bạn chỉ cần cấp điện DC vào là nó beep, và ngắt nguồn DC để tắt nó, chẳng hạn như các buzzer sau:
http://www.cui.com/srchresults.asp?catky=523311&subcatky=934927

Thân,

phamminh05
30-11-2008, 08:19 PM
Em muốn viết 1 đoạn code phát âm thanh đơn giản thôi,giống như cái Casio vậy vô hàm void play_sound(void) ở trên,nhưng em không biết cấu hình PMW như thế nào và xuất ra như thế nào(cần 1 chân hay cả nguyên 1 port) để xuất ra âm thanh?
Mong anh namqn và các bạn giúp giùm mình với,hơi chi tiết 1 chút,mình mới chỉ tìm hiểu PIC và VDK chưa lâu nên chưa biết rõ lắm.

namqn
30-11-2008, 10:23 PM
Em muốn viết 1 đoạn code phát âm thanh đơn giản thôi,giống như cái Casio vậy vô hàm void play_sound(void) ở trên,nhưng em không biết cấu hình PMW như thế nào và xuất ra như thế nào(cần 1 chân hay cả nguyên 1 port) để xuất ra âm thanh?
Mong anh namqn và các bạn giúp giùm mình với,hơi chi tiết 1 chút,mình mới chỉ tìm hiểu PIC và VDK chưa lâu nên chưa biết rõ lắm.
Bạn chỉ cần 1 ngõ ra của PIC (cùng với chân VSS) để xuất âm thanh ra loa (thông qua một mạch khuếch đại, nếu cần thiết).

Một ví dụ về cách tôi thiết lập module CCP2 của PIC18F2320 trong C18 như sau:
PR2 = 200; //PR2 = (PWM period)*Fosc/(4*TMR2 prescale), 10 kHz
CCP2CON = 0x0C; //PWM mode, 2 LSBs of duty cycle are '0'
CCPR2L = 100; //50% duty initially
PIR1bits.TMR2IF = 0;
T2CON = 0x04; //Timer 2 is on (prescale = 1:1, postscale = 1:1)
TRISCbits.TRISC1 = 0; //RC1 is an output (PWM output)


Khi cần thay đổi duty cycle thì bạn thay đổi giá trị CCPR2L (8 bit cao nhất của duty cycle), và các bit <5:4> của thanh ghi CCP2CON (2 bit thấp nhất của duty cycle).

Tự đào sâu tìm hiểu sẽ giúp bạn hiểu rõ hơn.

Thân,