铜河 发表于 2013-2-28 20:09:35

ICCAVR:用M16演奏音乐的实验

/*****************************************
*      用M16单片机I/O口生成模拟音乐             *
* 功    能:用I/O口生成模拟音乐                         *
* 时钟频率:内部8M(频率太低音乐不准)         *
* 设    计:tonghe                                                 *
* 修改日期:2007年04月13日                                 *
* 参考资料:ICC AVR应用实例                                 *
* 编译环境:ICC-AVR6.31                                         *
* 实验环境:M16学习板                                 *
* 发    声:无源蜂鸣器                                         *
* 结    果:试验通过                                         *
*****************************************/
#include <iom16v.h>
#include <macros.h>

#define uchar unsigned char
#define uint unsigned int

/****************************************
*     定义音乐数据二维数组{x,y}                        *
*  x:对应音符音阶(频率),0表示休止符        *
*  y:对应音符节拍                                                *
****************************************/
//以下音乐数据为《卡秋莎》,位于程序区
flash uint music_data[]=
    {
        {440,600},{494,200},{523,600},{440,200},{523,400},{494,200},
        {440,200},{494,400},{330,400},{494,600},{523,200},{587,600},
        {494,200},{587,400},{523,200},{494,200},{440,800},{659,400},
        {880,400},{784,400},{880,200},{784,200},{698,400},{659,200},
        {587,200},{659,400},{440,400},{  0,200},{698,400},{578,200},
        {659,600},{523,200},{494,200},{330,200},{523,200},{494,200},
        {440,800},{659,400},{880,400},{784,400},{880,200},{784,200},
        {698,400},{659,200},{587,200},{659,400},{440,400},{  0,200},
        {698,400},{587,200},{659,600},{523,200},{494,200},{330,200},
        {523,200},{494,200},{440,800},{  0,  0}
        };
       
#pragma data:data                                         //设置回到数据存储器区
uint delay=0;

/************************************
*         端口初始化函数                        *
************************************/
void port_init(void)
    {
        MCUCR=0x00;
        DDRC=0x01;
        }
/***********************************
*        定时器0初始化函数                   *
***********************************/
void timer0_init(void)
    {
        TCCR0 = 0x00;                                           //暂停定时器0
        TCNT0 = 0x19;                                         //装初值
        TCCR0 = 0x04;                                         //启动定时器0
        }
/**********************************
*定时器0中断入口函数:产生音乐节拍*
**********************************/
#pragma interrupt_handler timer0:8        //_ovf_isr:10
void timer0(void)                                          //_ovf_isr(void)
    {
        delay++;
        TCNT0 = 0x19;                                          //重装初值
        }

/***********************************
*        定时器1初始化函数                   *
***********************************/
void timer1_init(void)                                   //定时器1初始化:1秒定时,预分频256
    {
        TCCR1B = 0x00;                                            //停止定时器
//        TCNT1H = 0xF0;                                           //初值高字节
//        TCNT1L = 0xBE;                                           //定时初值低字节
        TCCR1A = 0x00;
        TCCR1B = 0x04;                                             //启动定时器
        }
/**********************************
*定时器1中断入口函数:产生方波发声*
**********************************/
#pragma interrupt_handler timer1:5        //_ovf_isr:9
void timer1(void)                                          //_ovf_isr(void) //定时器1中断入口
    {
//        TCNT1H = 0xF0;                                          //重装初值
//        TCNT1L = 0xBE;                                          //
        PORTC^=0x01;                                        //产生方波,发声
        }
/*********************************
SOUND函数
功能:输出频率为x的方波,延时y MS
范围:x:100-20000Hz,0:不发声
          y:0-65536 MS
*********************************/
void sound(uint x,uint y)
    {
        SEI();                                                              //
        delay=0;
        if(x!=0)
            {
                x=4000000/x;
                OCR1A=x;
                TCNT1=0x00;
                TIMSK|=0x40;
                while(delay<y)
                    ;
                TIMSK&=0xBF;
                }
        else
                {
                TIMSK&=0xBF;
                while(delay<y)
                        ;
                }
        CLI();
        }
/***********************
*************************/
void main(void)
        {
        uchar i=0;
        port_init();
        timer0_init();
        timer1_init();
        while(1)
            {
                while(music_data!=0)
                        {
                        sound(music_data,music_data);
                        i++;
                        }
                i=0;
                }
        }
       
       
页: [1]
查看完整版本: ICCAVR:用M16演奏音乐的实验