/******************************************************************************/
/* RAM SEGMENT variables */
/******************************************************************************/
/* Global variable used to store the ADC result. */
unsigned int AD_Value;
/* Global variable used to store the Key pressed for changing octave. */
unsigned char Flag_Octave_Chg;
/* Global variable used as index for the array of notes: position in the tune.*/
unsigned int current_note = 0;
/* Global variable used as index for the array of notes. */
unsigned char c1,c1_buf;
/* Music note coding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* FA0 SOL0 LA0 SI0 DO RE MI FA SOL LA SI DO2 MUTE RE2 SOL2 FA# */
/* TIM2 CCR1 High byte. */
const unsigned char Low_Note_h[] /* Lower octave */
={0x2C,0x27,0x23,0x1F,0x1D,0x1A,0x17,0x16,0x13,0x11,0x0F,0x0E,0x00, 0x0D, 0x09, 0x15 };
const unsigned char Hi_Note_h[] /* Higher octave */
={0x16,0x13,0x11,0x0F,0x0E,0x0D,0x0B,0x0B,0x09,0x08,0x07,0x07,0x00, 0x06, 0x04, 0x0A };
/* The actual tune sequence: an array of notes. */
const unsigned char tune[] =
{
_M+sq, _M+sq, /* Two "buffer" mutes needed to manage smoothly the */
/* current_note/current_note_init comparison. */
/*------------------ DO RE MI FA SOL LA SI DO2 --------------------------*/
/*------------------ DO2 SI LA SOL FA MI RE DO --------------------------*/
_DO+c,_RE+c,_MI+c,_FA+c,_SOL+c,_LA+c,_SI+c,_DO2+c,_M+m, _PAUSE_,
_DO2+c,_SI+c,_LA+c,_SOL+c,_FA+c,_MI+c,_RE+c,_DO+c,_M+m, _PAUSE_,
TIM2_ARR = 0; /* Freq control register: ARR */
TIM2_CCR1 = 0; /* Dutycycle control register: CCR */
TIM2_PSCR |= 0x00; /* fCK_CNT is equal to fCK_PSC. */
TIM2_CR1 |= 0x01; /* Enable TIM2. */
current_note = 1;
}
void Buzz_Wait(unsigned char duration)
{
int i = 0;
unsigned char uc = 0;
unsigned long Temp;
/* Sample AIN voltage in ADC single mode. */
ADC_CR1 |= 0x01; /* First set ADON to power on the ADC module. */
i = 6; /* Wait >7us to ensure the ADC power on finished.*/
while(i--);
ADC_CR1 |= 0x01; /* Set ADON again to start AD convert. */
while(!(ADC_CSR & 0x80));/* Waiting for AD convert finished (EOP=1). */
/* Store ADC value to AD_Value */
AD_Value = ((((unsigned int)ADC_DRH)<<2)+ADC_DRL)>>2;
if (AD_Value < 0x01)
{ AD_Value = 0x01; }
if (AD_Value > 0xC0)
{ AD_Value = 0xC0; }
if (Flag_Octave_Chg==1)
{
Temp = ((((unsigned int) Low_Note_h [c1_buf])<<8)+Low_Note_l [c1_buf]);
}
else
{
Temp = ((((unsigned int) Hi_Note_h [c1_buf])<<8)+Hi_Note_l [c1_buf]);
}
Temp = (Temp*AD_Value)>>9;
TIM2_CCR1H=(unsigned char)(((unsigned int)Temp & 0xff00)>>8);
TIM2_CCR1L=(unsigned char)((unsigned int)Temp & 0x00ff);
while ( uc < duration ) /* The following loop is run "duration" times. */
{
while ( i < 1200 ) /* This loop "Y" waits approximately 4.3ms. */
{
i++;
}
i = 0;
uc++;
}
} 作者: 铜河 时间: 2013-2-26 15:35
继续:
void Buzz_PlayTune ( void )
{
unsigned ui;
unsigned long temp_DCR;
unsigned char temp;
while(1)
{
if(tune[current_note] == _END_)
{
/* End of the music, reset to beginning. 1 is a mute at the */
/* beginning of the array of notes; differs from 0. */
current_note = 1;
break;
}
else if(tune[current_note] == _PAUSE_)
{
/* End of a tune, save the position in the music, stop playing. */
current_note++;
break;
}
else
{
c1 = tune[current_note];
/* Loads a note (or mute) on the relevant registers */
/* The note information is carried only by the 4 lowest bits. */
/* The new duty cycle value is written in DCR0. */
temp=((unsigned int)temp_DCR & 0xff00)>>8;
TIM2_CCR1H=(unsigned char)temp;
temp=((unsigned int)temp_DCR & 0x00ff);
TIM2_CCR1L=(unsigned char)temp;
/* Waits for the duration of the note. */
/* The duration info is carried by the 4 highest bits. */
Buzz_Wait(c1&0xF0);
/* Progressing in the array of notes: the tune. */
current_note++;
}
}
}
@far @interrupt void NonHandledInterrupt (void)
{
/* in order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction
*/
return;
}
@far @interrupt void TIM4_UPD_OVF_IRQHandler (void)
{
Count++;
switch (Count)
{
case 400: PD_ODR |=0x01;
break;
case 800: PD_ODR |=0x04;
break;
case 1200: PD_ODR |=0x08;
break;
case 1600: PD_ODR &=~0x0D;
Count=0;
break;
}
/* Clear the update IT pending Bit */
TIM4_SR &=~(0x01);
return;
}