📄 music_m48.c
字号:
/******************************************************************************/
/* 单片机放音机源程序(V1.0b) */
/* 创建人:QQQ 创建日期:2005-3-8 */
/* 修改人:QQQ 修改日期:2005-3-18 */
/* 修改人:CWD 修改日期:2005-6-15 */
/******************************************************************************/
/*修改内容:改为M48,并用GCC编译。 */
// 目标CPU : ATmega48
// 晶 振: 默认:8.0000MHz/8
/* ---------
1---| |---28
2---| |---27 PC4-->9012-->SPEAK
3---| |---26
4---| AT |---25
5---| MEGA |---24
6---| 48L |---23
7---| |---22
8---| |---21
9---| |---20
10---| 1MHz |---19
11---| |---18
12---| |---17
13---| |---16
14---| |---15
---------
*/
//============================================================================//
// 头文件和变量定义 //
//============================================================================//
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
//#include <avr/eeprom.h>
#include <avr/pgmspace.h>
//#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/delay.h>
#include <inttypes.h>
#include "music.h"
#include "music_data.h"
#define music_out PC4
volatile byte tone_dl,play_flag;
volatile word nop_time;
byte yinyue,jiepai,play_num,play_tmp,j;
word i;
const byte (*p)[2]; //指向flash存储区的二维数组指针
//============================================================================//
// 函数名称:timer0_ovf_isr() //
// 功 能:定时器0中断服务程序,对节拍等提供时基 //
// 参 数:无 //
// 影响变量:tone_dl //
// 创 建:2005-3-8 by QQQ //
// 修 改: //
//============================================================================//
//#pragma interrupt_handler timer0_ovf_isr:10
//void timer0_ovf_isr(void)
SIGNAL(SIG_OVERFLOW0)
{
TCNT0=0xb7;
tone_dl++;
nop_time++;
}
//==============================================================================
// 函数名称:timer1_compa_isr()
// 功 能:定时器1中断服务程序,翻转PC.0口的状态
// 参 数:无
// 影响变量:无
// 创 建:2005-3-8 by QQQ
// 修 改:
//==============================================================================
//#pragma interrupt_handler timer1_compa_isr:7
//void timer1_compa_isr(void)
SIGNAL(SIG_OUTPUT_COMPARE1A)
{
PORTC^=_BV(music_out);
}
//==============================================================================
// 函数名称:init_device()
// 功 能:初始化各寄存器及I/O口
// 参 数:无
// 影响变量:无
// 创 建:2005-3-8 by QQQ
// 修 改:
//==============================================================================
void init_device(void)
{
cli();
//port initialized
DDRB=0xFF;PORTB=0xFF;
DDRC=0xFF;PORTC=0xef;
DDRD=0xFF;PORTD=0xFF;
//timer0 initialized
TCCR0A=0x00;
TCCR0B=0X00;
TCNT0=0xb7;//定时时长18mS,则1/4拍为 2*5*18ms~~187ms。1M
TIMSK0=0x01;//开溢出中断。
//timer1 initialized
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0xFF;
OCR1AL=0xFF;
TCCR1A=0x00;
TIMSK1=0X02;
//
// MCUCR=0x00;
//EICRA=0X00; //外部中断
//EIMSK=0x03;
set_sleep_mode(SLEEP_MODE_IDLE);
}
//==============================================================================
// 函数名称:get_music_num()
// 功 能:通过曲目值让指针指向对应的歌曲,实现曲目查找
// 参 数:无
// 影响变量:*p
// 创 建:2005-3-9 by QQQ
// 修 改:
//==============================================================================
void get_music_num(void)
{
switch(play_num)
{
case 0 : p=music_dt0;break;
case 1 : p=music_dt1;break;
case 2 : p=music_dt2;break;
case 3 : p=music_dt3;break;
case 4 : p=music_dt4;break;
case 5 : p=music_dt5;break;
case 6 : p=music_dt6;break;
case 7 : p=music_dt7;break;
}
}
//==============================================================================
// 函数名称:sound()
// 功 能:将得到的数据转化为声音信号
// 参 数:无
// 影响变量:yinyue,yinfu,jiepai,num
// 创 建:2005-3-9 by QQQ
// 修 改:2005-3-14 by QQQ
//==============================================================================
void sound(void)
{
yinyue=pgm_read_byte(p);
if(yinyue != 0)
{
OCR1A=pgm_read_word(tone_frq+yinyue);//取得音符对应的频率值
TCCR1B=0x09; //+TCCR1A 0X00,设置为CTC,时钟无分频。
TCNT1=0x00;
}
else TCCR1B=0x00;//若音乐为零,表示休止符
while((tone_dl<jiepai)&&(play_num==play_tmp)&&(play_flag!=0));
if(play_flag==0)
{
// MCUCR|=0xA0;
PORTC=0xef;
j=0x01;//等待标志
sleep_mode();
// MCUCR=0x00;
TCCR0A=0X00;
TCCR0B=0x04;
TCCR1B=0x09;
}
while((tone_dl<jiepai)&&(play_num==play_tmp)&&(play_flag!=0));
tone_dl=0;
p++;
jiepai=pgm_read_byte(*p+1);
}
//==============================================================================
// 函数名称:main()
// 创 建:2005-3-9 by QQQ
// 修 改:2005-3-14 by QQQ
//==============================================================================
int main(void)
{
init_device();
nop_time=0;
play_num=0;
play_flag=0x01;
sei();//开中断
while(1)
{
start:
get_music_num();
play_tmp=play_num;
if(play_flag==0x01)
{TCCR0B=0x04;TCCR1B=0x09;}
jiepai=pgm_read_byte(*p+1);//取得第一个节拍
while(jiepai!=0)//若为零,表示结束
{
if(play_tmp!=play_num)//播放与用户指定乐曲不同
{TCCR0B=0x00;
TCCR1B=0x00;
goto start;} //结束当前播放的曲子
sound();
}
TCCR0B=0x00;TCCR1B=0x00;
if(play_num<7)play_num++;
else play_num=0;
}
}
/******************************************************************************/
/* END */
/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -