森宝网络

向单片机高手求助,怎样用C语言编写歌曲程序和歌曲代码?需要用那些工具怎么样编写的要求详细解答。谢谢?

  

向单片机高手求助,怎样用C语言编写歌曲程序和歌曲代码?需要用那些工具怎么样编写的要求详细解答。谢谢?

  

向单片机高手求助,怎样用C语言编写歌曲程序和歌曲代码?需要用那些工具怎么样编写的要求详细解答。谢谢?

  

向单片机高手求助,怎样用C语言编写歌曲程序和歌曲代码?需要用那些工具怎么样编写的要求详细解答。谢谢?

  //绝对调试通过,AVR-GCC,mega16,带数码显示,单键开关多功能控制

  #include <r/io.h>

  #include <r/interrupt.h>

  #include <tone.h>

  #include <r/pgmspace.h>

  #define uchar unsigned char

  #define uint unsigned int

  #define key_input PINA

  #define pgm16(A) ((typeof(A))pgm_read_word(&(A)))

  const unsigned char seg_code[] ={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x7f,0x3f};

  const uint music[] PROGMEM={M3,F2,M5,B1,M3,F4,M2,F4,M1,B2,L6,F2,M1,F2,MM,M1,F2,L6,F2,L5,B2, L6,F2,M1,B1,MM,M1,F2,L6,F2,M6,F2,L5,F2,M3,F2,M2,F2,MM,M2,F4,M1,F4,L6,F2,M3,F2,M2,B2,tttttM3,F2,MM,M3,F2,MM,M3,F2,M2,F2,M1,B2,L6,F2,M1,F2,L7,F2,L5,F2,L6,B2, L5,F2,L6,F2,MM,L6,F2,L5,F2,M6,F2,M5,F2,MM,M5,F2,M3,F2,M2,F2,MM,M2,F4,M3,F4,M3,F2,M2,F2,M1,B2,tttttM6,F2,H1,B1,M6,F2,H2,F2,H1,F2,MM,H1,F2,M6,F2,MM,M6,F2,M5,F2,MM,M5,F2,M3,F2,M5,B2, M6,F2,H1,B1,M6,F2,H2,F2,H1,F2,MM,H1,F2,M6,F2,M5,F2,MM,M5,F2,MM,M5,F2,M3,F2,M2,B2,tttttM3,B1,MM,M3,F2,M5,F2,M6,F2,M5,F2,MM,M5,F2,M3,F2,MM,M3,F2,M2,F2,MM,M2,F2,M1,F2,L6,B2, L5,F2,M5,F4,MM,M5,F4,MM,M5,F2,M6,F2,M5,F2,M3,F2,M2,F2,M3,F2,MM,M3,F2,M2,B1,L6,F2,M1,B2,tttttM6,F2,H1,B1,M6,F2,H2,F2,H1,B1,M6,F2,MM,M6,F2,M5,F2,MM,M5,F2,M3,F2,M5,B2, M6,F2,H1,B1,M6,F2,H2,F2,H1,B1,M6,F2,tttttM5,F2,MM,M5,F2,MM,M5,F2,M3,F2,M2,B2,MM, M2,F2,MM,M2,F4,M1,F4,M2,F2,M3,F2,M5,F2,MM,M5,F2,MM,M5,F2,M3,F2,M2,F2,MM,M2,F4,M3,F4,M2,F2,M1,F2,L6,B2,tttttL5,F2,M5,F4,MM,M4,F4,MM,M5,F2,M6,F2,M5,F2,M3,F2,M2,F2,M2,F4,M3,F4,MM,M3,F2,M2,B1,L6,F2,M1,B3,0XFF,0XFF};

  //因为两个相同的音符之间无停顿,人为插入了MM(极短暂的

  volatile uint i=1;

  volatile uchar timeOK=0;

  uchar key_scan(void);

  ISR(TIMER0_COMP_vect)ttt//CTC模式,控制音调高低

  {

  OCR0=pgm16(music[i-1]);

  }

  ISR(TIMER1_OVF_vect)ttt//时间溢出模式,控制节拍长短

  {t

  i+=2;

  TCNT1H=(65536-pgm16(music[i]))/256;ttttttt//相当于(65536-beat[i])/256

  TCNT1L=(65536-pgm16(music[i]))%256;tt//相当于(65536-beat[i])%256

  if(pgm16(music[i])==0xff)i=1;tttttttt//在音调数组的最后加一个0xff,作为终止信号

  if(pgm16(music[i])==0x00)TIMSK&=(~(1<<OCIE0));

  else TIMSK=(1<<OCIE0);

  }

  ISR(TIMER2_OVF_vect)tt//时间溢出模式,用于检测按键,周期10ms

  {

  TCNT2=100;

  timeOK=1;

  }

  void timer0_init(void)

  {

  TCCR0=0x00;

  TCNT0=0x00;

  OCR0=pgm16(music[i-1]);

  TCCR0=0x1a;

  //TIMSK=(1<<OCIE0);

  }

  void timer1_init(void)

  {

  TCCR1B=0x00;

  TCNT1H=(65536-pgm16(music[i]))/256;

  TCNT1L=(65536-pgm16(music[i]))%256;

  TCCR1A=0x00;

  TCCR1B=0x05;

  //TIMSK=(1<<TOIE1);

  }

  void timer2_init(void)

  {

  TCCR2=0x00;

  TCNT2=100;

  TCCR2=0x03;

  TIMSK=(1<<TOIE2);

  }

  void MCU_init(void)

  {

  DDRA=0X00;

  DDRB=0X00;

  DDRC=0XFF;

  DDRD=0XFF;

  PORTB=0X00;

  PORTC=0xfe;

  PORTD=0xff;

  }

  uchar key_scan(void)ttt//按钮扫描函数

  {

  static uchar key_state=0,key_time1=0,key_time0=0;tt//静态变量,调用以后,值被保留;

  uchar key_press,key_return=0;

  key_press=(~key_input)&0x01;tt//有键1,无键0

  switch(key_state)ttt//状态机

  {

  case 0:tttttttt//状态0:无按钮按下状态

  if(key_press)key_state=1;

  break;

  case 1:tttttttt//状态1:检测到有按钮被按下t

  if(key_press)ttttttt//按钮仍按下,转2

  {

  //TIMSK^=(1<<TOIE0);

  key_state=2;

  key_time1=0;tttttt//按下时间初始

  }

  elsettttttttt//按钮已经释放,消抖

  key_state=0;

  break;

  case 2:tttttttt//状态2:等待释放或等待按下时间达到长按要求

  if(!key_press)ttttttt//按钮已经释放,转3,继续判断是双按还是单按

  {

  key_state=3;

  key_time0=0;tttttt//释放时间初始

  }

  else if (++key_time1>=100)tttt//按下时间达到1000ms,返回值2,作长按判断,转7等待按钮释放

  {

  key_state=8;tttttt

  key_time1=0;

  key_return=2;

  }

  break;

  case 8:

  if(!key_press)

  {

  key_state=0;

  key_time1=0;

  }

  else if (++key_time1>=50)

  {

  key_return=2;

  key_time1=0;

  }

  break;

  case 3:tttttttt//状态3:双按的第二次按钮输入前的等待间隙,设定100ms(经过测试,100ms为比较合适的时间间隙,即为人体普通可以双击的速度

  if(key_press)key_state=4;tt//在此时间,如果有按钮被按下,将当作释放抖动,转4进一步作出判断

  else if (++key_time0>4)tt//如果没有按钮被按下,则等待此100ms过去,然后转5

  {

  key_state=5;

  key_time0=0;

  }

  break;

  case 4:tttttttt//状态4:第二按的消抖处理

  if(key_press)key_state=2;tt//快速连按(被认为人手指达不到要求的速率)将被返回到2,当作第一按处理

  else key_state=3;tttt//如果第二按只出现一次,不到10ms,消抖

  break;

  case 5:tttttttt//状态5:第二按前等待时间到达,进入正常的第二按等待输入状态,第二按只允许在此时间内输入方为有效

  if(key_press)key_state=6;tt//此时间内有被按下,转6,判决抖动;

  else if(++key_time0>14)ttt//无输入,则等待输入有效时间过去,时间满后,判定为单按,返回值1,状态位回到0

  {

  key_state=0;

  key_time0=0;tttt//双击间隔时间一般为100ms,能够稳定做到第二击完成时间总共约180~200ms(因人而异)

  key_return=1;tttt//为增加采样成功率,可适当缩短第二按前的间隙时间,增加第二按等待输入时间,但总时间不可短于150ms

  }tttttttt//小于150ms,手指将很难达到双击的速度要求,如果时间太长则单按判断时间过长,按钮不灵敏,此处180ms经测试较为合适

  break;

  case 6:tttttttt//状态6:第二按的抖动判断

  if(key_press)tttttt//按钮仍有效,按下有效,返回3,双按成立,转7等待按钮释放

  {

  key_state=7;

  key_return=3;

  }

  else key_state=5;ttttt//抖动消除,退回5继续等待输入或等待输入有效时间过去

  case 7:tttttttt//按钮释放等待状态,所有已按下并被识别操作目的的按钮状态都将转到7等待按钮释放,并将所有计时初始

  if(!key_press)key_state=0;

  key_time1=0;

  key_time0=0;

  break;

  }

  return key_return;

  }

  int main(void)

  {

  MCU_init();

  timer0_init();

  timer1_init();

  timer2_init();

  sei();

  while(1)

  {

  if(timeOK)

  {

  cli();

  uchar key;

  key=key_scan();

  if(key>0)PORTD=seg_code[key];

  switch(key)

  {

  case 1:

  TIMSK^=((1<<OCIE0)(1<<TOIE1)); ttttttDDRB^=(1<<DDB3);ttttttttPORTC=0xfd;

  break;

  case 2:

  //TIMSK=((1<<OCIE0)&(1<<TOIE1));

  if(i>1)i+=10;

  if (i>=(sizeof(music)-20))

  {

  i=1;

  TIMSK&=(~((1<<OCIE0)(1<<TOIE1)));

  DDRB&=~(1<<DDB3);

  }

  PORTC=0xf0;

  break;

  case 3:

  TIMSK&=(~((1<<OCIE0)(1<<TOIE1)));

  i=1;

  TIMSK=((1<<OCIE0)(1<<TOIE1));

  PORTC=0xfe;

  break;

  default:

  break;

  }

  timeOK=0;

  sei();

  }

  }

  }

未经允许不得转载:五金工具_五金配件_五金建材_机械设备-森宝五金网 > 向单片机高手求助,怎样用C语言编写歌曲程序和歌曲代码?需要用那些工具怎么样编写的要求详细解答。谢谢?

评论

留言与评论(共有 0 条评论)
   
验证码: