圣龙扬特-AVR电子

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2283|回复: 3

STM8S实验板演奏音乐示例(板自带例程)

[复制链接]

26

主题

1

好友

3446

积分

超级版主

Rank: 8Rank: 8

UID
7
帖子
140
精华
0
注册时间
2013-2-26
在线时间
20 小时

突出贡献

发表于 2013-2-26 15:34:18 |显示全部楼层
主程序:
/* Includes ------------------------------------------------------------------*/
#include "STM8S105C_S.h"          /* Registers and memory mapping file. */

/******************************************************************************/
/* Macro definitions
/******************************************************************************/
/* Music instruction and note coding. */
#define  _END_      0xFF        /* Music END. */
#define  _PAUSE_    0xFE        /* Pause between different tunes. */

/* Note tone definition...... */
#define  _FA0       0x00        /* FA-  */
#define  _SOL0      0x01        /* SOL- */
#define  _LA0       0x02        /* LA-  */

#define  _SI0       0x03        /* SI-  */
#define  _DO        0x04        /* DO   */
#define  _RE        0x05        /* RE   */
#define  _MI        0x06        /* MI   */
#define  _FA        0x07        /* FA   */
#define  _SOL       0x08        /* SOL  */
#define  _LA        0x09        /* LA   */
#define  _SI        0x0A        /* SI   */
#define  _DO2       0x0B        /* DO+  */
#define  _M         0x0C        /* MUTE */
#define  _RE2       0x0D        /* RE+  */
#define  _SOL2      0x0E        /* SOL+ */
#define  _FAd       0x0F        /* FA#  */

/* Note length definition...... */
#define  sq         0x10        /* Semiquaver notes.  */
#define  q          0x20        /* Quaver notes.      */
#define  qp         0x30        /* 1.5 quaver notes.  */
#define  c          0x40        /* Crotchet notes.    */
#define  cn         0x60        /* 1.5 crotchet notes.*/
#define  m          0x80        /* Minim notes.       */

/******************************************************************************/
/* 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 };

/* TIM2 CCR1 Low byte. */
const unsigned char Low_Note_l[]    /* Lower octave  */
={0xA4,0xDC,0x82,0xA1,0xEE,0xA9,0xAC,0x62,0xEE,0xC1,0xD0,0xF0,0x00, 0x4F, 0xF7, 0x2C };
const unsigned char Hi_Note_l[]     /* Higher octave  */
={0x52,0xEE,0xC1,0xD0,0xF7,0x54,0xD6,0x31,0xF7,0xE0,0xE8,0x78,0x00, 0xA7, 0xFB, 0x96 };

/* 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_,

    /*---------------------------- 新年好 ------------------------------------*/
    _DO+c,_DO+c,_DO+c,_M+sq,_DO+m,_SOL0+m,_MI+c,_MI+c,_M+sq,_MI+m,_DO+m,_DO+c,
    _MI+c,_M+sq,_SOL+m,_SOL+m,_FA+c,_MI+c,_M+sq,_RE+m,_RE+m,_M+sq,_RE+c,_MI+c,
    _FA+m,_M+sq,_FA+m,_MI+c,_RE+c,_MI+m,_DO+m,_M+sq,_DO+c,_MI+c,_RE+m,_SOL0+m,
    _SI0+c,_RE+c,_DO+m,_DO+m,_PAUSE_,

    /*--------------------------- 两只老虎 -----------------------------------*/
    _DO+c,_RE+c,_MI+c,_DO+c,_DO+c,_RE+c,_MI+c,_DO+c,_MI+c,_FA+c,_SOL+m,_MI+c,
    _FA+c,_SOL+m,_SOL+qp,_LA+sq,_SOL+qp,_FA+sq,_MI+c,_DO+c,_SOL+qp,_LA+sq,
    _SOL+qp,_FA+sq,_MI+c,_DO+c,_M+sq,_DO+c,_SOL0+c,_DO+m,_M+sq,_DO+c,_SOL0+c,
    _DO+m,_M+sq,_PAUSE_,

    /*---------------------------- 甜蜜蜜 ------------------------------------*/
    _MI+m,_SOL+c,_LA+c,_MI+m,_MI+c,_DO+c,_RE+cn,_DO+q,_RE+c,_MI+q,_SOL+q,_MI+m,
    _MI+m,_RE+c,_RE+c,_RE+c,_RE+q,_MI+q,_RE+q,_DO+cn,_LA0+q,_SOL0+cn,_DO+m,
    _DO+c,_RE+c,_MI+cn,_RE+q,_MI+q,_RE+q,_MI+q,_SOL+q,_RE+m,_RE+m,_RE+m,_RE+m,
    _MI+m,_SOL+c,_LA+c,_MI+m,_MI+c,_DO+c,_RE+cn,_DO+q,_RE+c,_MI+q,_SOL+q,_MI+m,
    _MI+m,_RE+c,_RE+c,_RE+c,_RE+q,_MI+q,_RE+q,_DO+cn,_LA0+q,_SOL0+cn,_DO+m,
    _DO+c,_MI+c,_RE+q,_DO+q,_DO+c,_LA0+q,_SOL0+cn,_DO+m,_DO+m,_DO+m,_DO+m,_MI+m,
    _MI+m,_SOL0+m,_LA0+q,_DO+q,_SOL0+q,_LA0+q,_DO+m,_DO+m,_DO+m,_DO+m,_LA0+c,
    _SI0+c,_LA0+c,_SI0+c,_LA0+c,_LA0+q,_DO+q,_LA0+q,_SOL0+q,_SOL0+c,_MI+m,_MI+m,
    _MI+m,_MI+m,_LA0+c,_SI0+c,_LA0+c,_SI0+c,_LA0+c,_LA0+q,_DO+q,_LA0+q,_SOL0+q,
    _SOL0+c,_MI+m,_MI+m,_MI+m,_M+c,_SOL+q,_LA+q,_SOL+m,_M+c,_SOL+q,_LA+q,_SOL+m,
    _M+c,_SOL+q,_LA+q,_SOL+c,_SOL+q,_LA+q,_SOL+c,_SOL+q,_LA+q,_SOL+m,_SOL+m,
    _MI+m,_SOL+c,_LA+c,_MI+m,_MI+c,_DO+c,_RE+cn,_DO+q,_RE+c,_RE+q,_SOL+q,_MI+m,
    _MI+m,_RE+c,_RE+c,_RE+c,_RE+q,_MI+q,_RE+q,_DO+cn,_LA0+q,
    _SOL0+cn,_DO+m,_DO+c,_MI+c,_RE+q,_DO+q,_DO+c,_LA0+q,_SOL0+cn,_DO+m,_DO+m,
    _DO+m,_DO+m,_MI+m,_MI+m,_SOL0+m,_LA0+q,_DO+q,_SOL0+q,_LA0+q,_DO+m,_DO+m,
    _DO+m,_DO+m,_PAUSE_,

    /*------------------ _END_ marks to end of the tune ----------------------*/
    _END_   
};


/******************************************************************************/
/* Function definitions                                                       */
/******************************************************************************/
/* -------------------------------------------------------------------------- */
/* ROUTINE NAME: Buzz_Init                                                    */
/* INPUT/OUTPUT: None.                                                        */
/* DESCRIPTION:  Initialize the TIM2 as PWM mode for BUZZ control.            */
/* -------------------------------------------------------------------------- */
void Buzz_Init ( void )
{
    PD_DDR     |= 0x10;      /* Configure PD4 as output (for the PWM). */
    PD_CR1     |= 0x10;      /* PD4 Push pull output.                  */
    TIM2_CCMR1 |= 0x70;      /* Output mode PWM2.                      */
    TIM2_CCER1 |= 0x03;      /* CC polarity low,enable PWM output      */

    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++;
    }
}
回复

使用道具 举报

26

主题

1

好友

3446

积分

超级版主

Rank: 8Rank: 8

UID
7
帖子
140
精华
0
注册时间
2013-2-26
在线时间
20 小时

突出贡献

发表于 2013-2-26 15:35:40 |显示全部楼层
继续:
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.   */

            c1_buf= c1 & 0x0f;

            if (Flag_Octave_Chg==1)
            {
                temp_DCR = ((((unsigned int)Low_Note_h [c1_buf])<<8)+Low_Note_l[c1_buf]);
                TIM2_ARRH = Low_Note_h [c1_buf];
                TIM2_ARRL = Low_Note_l [c1_buf];
            }
            else
            {
                temp_DCR = ((((unsigned int) Hi_Note_h [c1_buf])<<8)+Hi_Note_l [c1_buf]);
                TIM2_ARRH = Hi_Note_h [c1_buf];
                TIM2_ARRL = Hi_Note_l [c1_buf];
            }

            temp_DCR = (temp_DCR*AD_Value)>>9;

            /* 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++;
        }
    }
}

/* -------------------------------------------------------------------------- */
/* ROUTINE NAME: GPIO_Init                                                    */
/* INPUT/OUTPUT: None.                                                        */
/* DESCRIPTION:  Initialize the GPIO for LED,TLI.                             */
/* -------------------------------------------------------------------------- */
void GPIO_Init(void)
{
    /* LED IO Configuration        */
    /* LD3: PD3             */
    /* LD2: PD1             */
    /* LD1: PD0             */
    PD_DDR |= 0x0D;          /* Output. */
    PD_CR1 |= 0x0D;          /* PushPull. */
    PD_CR2  = 0x00;          /* Output speed up to 2MHz. */

    /* PD7 external interrupt */
    EXTI_CR1  = 0x00;        /* External interrupt (TLI) sensitivity. */
    EXTI_CR2  = 0x00;
    PD_DDR   &=~0x80;        /* PD7: Input */
    PD_CR2   |= 0x80;        /* Enable TLI interrupt. */
}

/* -------------------------------------------------------------------------- */
/* ROUTINE NAME: CLK_Init                                                     */
/* INPUT/OUTPUT: None.                                                        */
/* DESCRIPTION:  Initialize the clock source                                  */
/* -------------------------------------------------------------------------- */
void CLK_Init(void)
{
    /* Configure HSI prescaler*/
    CLK_CKDIVR &= ~0x10;          /* 01: fHSI= fHSI RC output/2. */

    /* Configure CPU clock prescaler */
    CLK_CKDIVR |= 0x01;           /* 001: fCPU=fMASTER/2. */
}

/* -------------------------------------------------------------------------- */
/* ROUTINE NAME: ADC_Init                                                     */
/* INPUT/OUTPUT: None.                                                        */
/* DESCRIPTION:  Initialize the AD converter.                                 */
/* -------------------------------------------------------------------------- */
void ADC_Init(void)
{
    ADC_CR2  = 0x00;
    ADC_CR1  = 0x00;
    ADC_CSR  = 0x03;
    ADC_TDRL = 0x20;
}

/* -------------------------------------------------------------------------- */
/* ROUTINE NAME: TIM_Init                                                     */
/* INPUT/OUTPUT: None.                                                        */
/* DESCRIPTION:  Initialize the TIM4 as LED timebase.                         */
/* -------------------------------------------------------------------------- */
void TIM_Init(void)
{
    /* TIM4 Peripheral Configuration */
    /* Time Base configuration */
    TIM4_PSCR = 0x04;              /* Configure TIM4 prescaler. */
    TIM4_ARR   = 0xFF;             /* Configure TIM4 period. */

    /*TIM4 counter enable */
    TIM4_CR1 |= 0x01;              /* Enable TIM4. */
    TIM4_IER |= 0x01;              /* Enable TIM4 OVR interrupt. */
}

/* -------------------------------------------------------------------------- */
/* ROUTINE: main                                                              */
/*          main entry                                                        */
/* -------------------------------------------------------------------------- */
void main ( void )
{
    unsigned int j;
    _asm("sim");               /* Disable interrupts. */

    Flag_Octave_Chg=0;

    CLK_Init();

    GPIO_Init();

    TIM_Init();

    ADC_Init();

    _asm("rim");              /* Enable interrupts. */

    Buzz_Init ();             /* Init TIMER peripheral. */

    while ( 1 )
    {
        /* Play the current score. */  
        Buzz_PlayTune();
        Buzz_Wait(0x80);      /* Wait around one second. */
    }
}
回复

使用道具 举报

26

主题

1

好友

3446

积分

超级版主

Rank: 8Rank: 8

UID
7
帖子
140
精华
0
注册时间
2013-2-26
在线时间
20 小时

突出贡献

发表于 2013-2-26 15:36:35 |显示全部楼层
中断程序:
#include "STM8S105C_S.h"
/*  BASIC INTERRUPT VECTOR TABLE FOR STM8 devices
*  Copyright (c) 2007 STMicroelectronics
*/

unsigned int Count;
extern unsigned char Flag_Octave_Chg;

void CLK_Init(void);

typedef void @far (*interrupt_handler_t)(void);

struct interrupt_vector {
unsigned char interrupt_instruction;
interrupt_handler_t interrupt_handler;
};

@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;
}

@far @interrupt void TLI_Interrupt (void)
{
    Flag_Octave_Chg ^=0x01;
    return;
}

extern void _stext();     /* startup routine */

struct interrupt_vector const _vectab[] = {
    {0x82, (interrupt_handler_t)_stext}, /* reset */
    {0x82, NonHandledInterrupt}, /* trap  */
    {0x82, TLI_Interrupt},       /* irq0  */
    {0x82, NonHandledInterrupt}, /* irq1  */
    {0x82, NonHandledInterrupt}, /* irq2  */
    {0x82, NonHandledInterrupt}, /* irq3  */
    {0x82, NonHandledInterrupt}, /* irq4  */
    {0x82, NonHandledInterrupt}, /* irq5  */
    {0x82, NonHandledInterrupt}, /* irq6  */
    {0x82, NonHandledInterrupt}, /* irq7  */
    {0x82, NonHandledInterrupt}, /* irq8  */
    {0x82, NonHandledInterrupt}, /* irq9  */
    {0x82, NonHandledInterrupt}, /* irq10 */
    {0x82, NonHandledInterrupt}, /* irq11 */
    {0x82, NonHandledInterrupt}, /* irq12 */
    {0x82, NonHandledInterrupt}, /* irq13 */
    {0x82, NonHandledInterrupt}, /* irq14 */
    {0x82, NonHandledInterrupt}, /* irq15 */
    {0x82, NonHandledInterrupt}, /* irq16 */
    {0x82, NonHandledInterrupt}, /* irq17 */
    {0x82, NonHandledInterrupt}, /* irq18 */
    {0x82, NonHandledInterrupt}, /* irq19 */
    {0x82, NonHandledInterrupt}, /* irq20 */
    {0x82, NonHandledInterrupt}, /* irq21 */
    {0x82, NonHandledInterrupt}, /* irq22 */
    {0x82, TIM4_UPD_OVF_IRQHandler},/* irq23 */
    {0x82, NonHandledInterrupt}, /* irq24 */
    {0x82, NonHandledInterrupt}, /* irq25 */
    {0x82, NonHandledInterrupt}, /* irq26 */
    {0x82, NonHandledInterrupt}, /* irq27 */
    {0x82, NonHandledInterrupt}, /* irq28 */
    {0x82, NonHandledInterrupt}, /* irq29 */
};
回复

使用道具 举报

0

主题

1

好友

3101

积分

超级版主

Rank: 8Rank: 8

UID
31
帖子
36
精华
0
注册时间
2013-2-27
在线时间
5 小时
发表于 2013-2-28 14:17:18 |显示全部楼层
表四鄙人纯属随机路过。。。顺带帮顶。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

Archiver|手机版|圣龙扬特-AVR电子 ( 鲁ICP备05022832号 )

GMT+8, 2024-4-19 03:13 , Processed in 0.222433 second(s), 27 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部