原创 AVR开发板程序

2009-12-14 13:44 2539 3 3 分类: MCU/ 嵌入式

    /*
* Copyright (c) 2007, Owen Studio
* All rights reserved.
*
* 文件名称:AVRMain.c
* 当前版本:Version 1.0
*
* 本程序为通过调试的源程序
*
* 功能描述:本程序演示了MEGA48/88/168的绝大多数功能,具体功能如下:
* 1.上电后系统进入综合演示程序,6个数码管开始显示电子时钟,初始时间为10:00:00,
* 同时循环播放5首音乐。5首音乐的来源分别为MEGA48/88/168内部FLASH、内部EEPROM、
* 24C02、93C46。在音乐播放的同时,继电器也按照播放音乐的节拍打开和关闭,驱动大
* LED亮灭,并配合音乐产生低音伴奏。另外开发板任何时候都会把开发板的运行情况定时
* 发送到PC机,配合PC机端的配套软件可以显示开发板的状态和控制开发板的运行。
* 2.系统中,按不同键对应不同的功能。
* A键:电子时钟<-->A/D数字电压表切换键。当切换到A/D数字电压表模式时,6个数码管只
* 显示4位电压值,最高位为个位,其他三位为小数位。调节电位器时电压也会随之变化。
* 当切换回电子时钟模式时,6个数码管又继续显示时间。
* B键:音乐自动循环播放<-->停止切换键。5首音乐源循环播放的次序为MEGA48/88/168内
* 部FLASH、内部EEPROM、24C02、93C46、MEGA48/88/168内部FLASH。
* C键:电机运行<-->停止切换键。切换到运行时,电机会从1V软启动到恒定电压3V稳定运
* 行,直到用户停止。
*
* 另外本程序集成了与PC通信的串口服务程序,所有按键的功能也可以通过PC机的控制软件
* 实现。状态也可以反馈到此控制软件上。
*
*/
/******************************************************************************/
//////////////////////////////Beginning of Program//////////////////////////////
/******************************************************************************/
// Target : M48
// Crystal: 8.000Mhz


#include <iom48v.h>
#include <macros.h>


#define  uchar unsigned char  
#define  uint  unsigned int


/*TWI Micros*/
#define  START         0x08
#define  MT_SLA_ACK    0x18
#define  MT_DATA_ACK   0x28
#define  MR_SLA_ACK    0x40
#define  MR_DATA_ACK   0x50
#define  MR_DATA_NACK  0x58


#define  PAI_BASE      15
#define  MUSIC_NUM     4
#define  SCAN_CYCLE    1000
#define  CS(x)         x ? (PORTB |= 0x04) : (PORTB &= 0xfb)
#define  ERROR(x) 
#define  AREF_5


/*当需要修改EEPROM、24C02、93C46内容时打开相应编译选项*/
//#define INIT_EEPROM
//#define INIT_24C02
//#define INIT_93C46


enum ShowFlag{
  SHOW_TIME,
  SHOW_AD
};


enum KeyCode{
  KEY0=0,
  KEY1,
  KEY2,
  KEY3,
};
/******************************************************************************/
/*Constant Tables*/
#pragma data:code
const char c_music1[]={0x82,0x01,0x81,0x94,0x84,             /*生日快乐歌*/
                       0xb4,0xa4,0x04,
        0x82,0x01,0x81,0x94,0x84,
        0xc4,0xb4,0x04,
        0x82,0x01,0x81,0xf4,0xd4,
        0xb4,0xa4,0x94,
        0xe2,0x01,0xe1,0xd4,0xb4,
        0xc4,0xb4,0x04,
        0x00};
#ifdef INIT_EEPROM
const char c_music2[]={0x54, 0x64, 0x64,                /*大长今*/
                       0x64, 0x02, 0x52, 0x44,
                       0x24, 0x44, 0x44,
                       0x51, 0x43, 0x44, 0x44,
                       0x54, 0x64, 0x64,
                       0x64, 0x02, 0x82, 0x64,
                       0x64, 0x54, 0x64,
                       0x64, 0x64, 0x64,
                       0x84, 0x94, 0x94,
                       0x94, 0x84, 0x64,
                       0x64, 0x84, 0x94,
                       0x81, 0x91, 0x82, 0x84, 0x84,
                       0x54, 0x64, 0x64,
                       0x54, 0x02, 0x62, 0x64,
                       0x54, 0x64, 0x24,
                       0x41, 0x23, 0x94, 0x94,
                       0x24, 0x24, 0x24,
                       0x54, 0x64, 0x64,
                       0x64, 0x02, 0x52, 0x44,
                       0x24, 0x44, 0x44,
                       0x51, 0x43, 0x44, 0x44,
                       0x54, 0x64, 0x64,
                       0x64, 0x02, 0x82, 0x64,
                       0x64, 0x54, 0x64,
                       0x64, 0x64, 0x64,
                       0x84, 0x94, 0x94,
                       0x94, 0x02, 0x82, 0x64,
                       0x64, 0x84, 0x94,
                       0x84, 0x84, 0x84,
                       0x54, 0x64, 0x64,
                       0x54, 0x02, 0x62, 0x64,
                       0x54, 0x64, 0x24, 
                       0x41, 0x23, 0x24, 0x24,
                       0x24, 0x24, 0x24,
                       0x54, 0x02, 0x42, 0x24,
                       0x54, 0x02, 0x42, 0x24,
                       0x54, 0x64, 0x44,
                       0x54, 0x02, 0x62, 0x84,
                       0x94, 0x02, 0x82, 0x64,
                       0x54, 0x02, 0x42, 0x24,
                       0x24, 0x14, 0x24,
                       0x41, 0x23, 0x24, 0x24,
                       0x24, 0x24, 0x24,
                       0x14, 0x14, 0x14,
                       0x14, 0x02, 0x22, 0x42, 0x52,
                       0x62, 0x52, 0x44, 0x02, 0x22,
                       0x44, 0x44, 0x54,
                       0x64, 0x64, 0x64,
                       0x64, 0x64, 0x84,
                       0x94, 0x02, 0xb2, 0x94,
                       0x84, 0x84, 0x84,
                       0x84, 0x61, 0x81, 0x92, 0x04,
                       0x92, 0x82, 0x64, 0x02, 0x52,
                       0x64, 0x02, 0x52, 0x62, 0x52,
                       0x44, 0x44, 0x44,
                       0x41, 0x23, 0x24, 0x44,
                       0x54, 0x54, 0x54,
                       0x54, 0x64, 0x64,
                       0x44, 0x41, 0x23, 0x24,
                       0x24, 0x24, 0x24,
                       0x00};
#endif /*INIT_EEPROM*/


#ifdef INIT_24C02
const char c_music3[]={0xb2, 0x41, 0x51, 0x62, 0x81, 0x91, 0x84, 0x84,  /*1000年以后*/
                       0x72, 0x61, 0x41, 0x42, 0x61, 0x51, 0x54, 0x54,
                       0xb2, 0x41, 0x51, 0x62, 0x92, 0xa1, 0x91, 0x82, 0x82, 0x61, 0x91,
                       0x94, 0x94, 0xa1, 0xa1, 0xa1, 0xb1, 0xc1, 0xb1, 0xa2,
                       0xb2, 0xa1, 0xb1, 0xb1, 0xd2, 0x01, 0xa2, 0x91, 0xa1, 0xa1, 0x81, 0x82,
                       0x91, 0x91, 0xa1, 0xb1, 0xc1, 0xb1, 0xc1, 0xe1, 0xd1, 0xc1, 0xc1, 0xc1, 0xc2, 0xc1, 0xb1,
                       0xb2, 0xa1, 0xb1, 0xb1, 0xd2, 0x01, 0xa2, 0x91, 0xa1, 0xa1, 0x81, 0x82,
                       0x92, 0xb4, 0x02, 0xb1, 0xb1, 0xb1, 0xc1, 0xd2, 0xc1, 0xb1,
                       0xb2, 0xc2, 0xc4, 0x02, 0xa1, 0xb1, 0xb1, 0xc2, 0x01,
                       0xd2, 0xc1, 0xb1, 0xb1, 0x82, 0x01, 0xc4, 0x02, 0xd1, 0xc1,
                       0xb2, 0xa1, 0x91, 0x92, 0x62, 0xa4, 0x02, 0xb1, 0xa1,
                       0x92, 0xa1, 0xb1, 0xb1, 0xc2, 0x01, 0x82, 0xc1, 0xd1, 0xd2, 0x01, 0xd1,
                       0xe2, 0xd2, 0xb1, 0xc2, 0xc1, 0xc2, 0x01, 0xa1, 0xb1, 0xc2, 0x01,
                       0xd2, 0xc1, 0xb1, 0xb1, 0x82, 0x01, 0xc4, 0xc1, 0xc1, 0xd1, 0xc1,
                       0xb2, 0xa2, 0x91, 0xc2, 0x01, 0xa4, 0x02, 0xb1, 0xa1,
                       0x92, 0x81, 0x91, 0x91, 0xb1, 0x82, 0x82, 0xc1, 0xb1, 0xb2, 0xd1, 0xd1,
                       0xe1, 0xd1, 0xc4, 0xb1, 0xc1, 0xd2, 0xc1, 0xb1, 0xd2, 0xc1, 0x81,
                       0x82, 0xb2, 0xb4, 0xb4, 0xb4,
                       0x00};
#endif /*INIT_24C02*/


#ifdef INIT_93C46
const char c_music4[]={0x24, 0x42, 0x52, 0x64, 0x62, 0x92,  /*漫步人生路*/
                       0x84, 0x62, 0x52, 0x64, 0x02, 0x62,
                       0x72, 0x62, 0x62, 0x52, 0x52, 0x42, 0x41, 0x31, 0x22,
                       0x44, 0x02, 0x52, 0x34, 0x34,
                       0x24, 0x42, 0x52, 0x64, 0x62, 0x92,
                       0xa4, 0x82, 0x62, 0x64, 0x02, 0x62,
                       0x72, 0x62, 0x52, 0x42, 0x32, 0x42, 0x52, 0x62,
                       0x42, 0x32, 0x22, 0x12, 0x24, 0x24,
                       0x42, 0x32, 0x42, 0x52, 0x64, 0x52, 0x62,
        0x74, 0x74, 0x72, 0x81, 0x71, 0x62, 0x52,
                       0x64, 0x74, 0x84, 0x02, 0x62,
                       0x94, 0x92, 0x82, 0x94, 0x92, 0xb2,
                       0x92, 0x82, 0x82, 0x92, 0x64, 0x52, 0x42,
                       0x54, 0x52, 0x42, 0x54, 0x42, 0x42, 0x82,
                       0x62, 0x62, 0x52, 0x42, 0x34, 0x62, 0x62,
                       0x94, 0x92, 0x82, 0x94, 0x92, 0xb2,
                       0x92, 0x82, 0x82, 0x92, 0x64, 0x52, 0x42,
                       0x54, 0x42, 0x82, 0x64, 0x52, 0x42,
                       0x52, 0x61, 0x51, 0x42, 0x32, 0x24, 0x24,
                       0x00};
#endif /*INIT_93C46*/


const uint c_musicFreq[]={64260,64400,64524,64580,   /*低音5,6,7,中音1*/
                          64684,64777,64820,64898,   /*中音2,3,4,5*/
        64968,65030,65058,65110,   /*中音6,7,高音1,2*/
        65157,65178,65217};        /*高音3,4,5*/
/*Constant Tables Over*/
/*************************************************************************/
/*System Variables*/ 
#pragma data:data         
uchar hour="10";min=0;sec=0;
uchar displayArray[6]={0,0,0,0,0,0};
uchar modifyTimeFlag="0";
uchar TenMsFlag="0";
uchar s_musicCounter=1,s_tableCounter=0,musicPlayFlag=0;
uchar musicFlag,g_TH,g_TL;
enum ShowFlag showFlag="SHOW"_TIME;
uchar scanNum="6";
uchar relayFlag="0", motorFlag="0";
/*System Variables Over*/
/*************************************************************************/
/*System Functions*/
void port_init(void);       /*GPIO初始化模块*/
void uart0_init(void);  /*UART初始化模块*/
void timer0_init(void);  /*TIMER0初始化模块*/
void init_devices(void); /*系统和外设初始化模块*/


void TxData(char data);  /*通过串口发送一个字节数据*/
void Print(char* info);  /*通过串口发送字符串信息*/
void ModifyTime(void);  /*修改时间模块*/
void ClearScr(void);  /*清屏*/
void ScanSeg7(void);  /*扫描6个七段数码管模块*/
void MusicHandler(void); /*音乐播放模块*/
void ADHandler(void);  /*A/D电压采集模块*/
void RelayHandler(void); /*继电器控制模块*/
void MotorHandler(void); /*直流电机的PWM调速模块*/
void Delay(int num);  /*延时模块*/
char ScanKeys(void);  /*键盘扫描模块*/
void Key1Handler(void);  /*按键A处理模块*/
void Key2Handler(void);  /*按键B处理模块*/
void Key3Handler(void);  /*按键C处理模块*/
void Key4Handler(void);  /*模拟按键D处理模块*/
void StatusSend(void);


#ifdef INIT_EEPROM
void EEPROMInit(void);  /*初始化EEPROM内容*/
#endif /*INIT_EEPROM*/
void EEPROM_Write(uint addr, const char* dat, int len);  /*EEPROM写函数*/
void EEPROM_Read(uint addr, char* dat, int len);     /*EEPROM读函数*/


#ifdef INIT_93C46
void AT93C46Init(void);  /*初始化AT93C46内容*/
#endif /*INIT_93C46*/
void AT93C46_Eren(void); /*AT93C46写允许*/
void AT93C46_Erds(void); /*AT93C46写禁止*/
void AT93C46_EraseAll(void);/*AT93C46全擦*/
void AT93C46_Read(char addr, char* dat, int len);    /*AT93C46写函数*/
void AT93C46_Write(char addr, const char* dat, int len); /*AT93C46读函数*/


#ifdef INIT_24C02
void Twi24C02Init(void); /*初始化24C02内容*/
#endif /*INIT_24C02*/
void TwiWrite(char sladdr, char addr, const char* dat, int len);/*24C02写函数*/
void TwiRead(char sladdr, char addr, char* dat, int len);       /*24C02读函数*/
/*System Functions Over*/
/*************************************************************************/
void main(void)
{
  int count="0";
 
  init_devices();       
  ClearScr();         
  ModifyTime();
  showFlag = SHOW_TIME;                   /*初始设定为显示时间*/
 
#ifdef INIT_EEPROM           
  EEPROMInit();            /*打开EEPROM改写编译选项才参加编译*/
#endif /*INIT_EEPROM*/


#ifdef INIT_24C02 
  Twi24C02Init();            /*打开24C02改写编译选项才参加编译*/
#endif /*INIT_24C02*/


#ifdef INIT_93C46
  AT93C46Init();           /*打开AT93C46改写编译选项才参加编译*/
#endif /*INIT_93C46*/
 
  while(1)
  {
    switch(ScanKeys())
 {
 case KEY0: break;
 case KEY1: Key1Handler(); break;
 case KEY2: Key2Handler(); break;
 case KEY3: Key3Handler(); break;
 }
 
    if(TenMsFlag == 1)        /*10ms到了*/
    {
      TenMsFlag="0"; 
   if(musicPlayFlag==1)        /*根据标志决定是否播放音乐*/     
   {
  MusicHandler();
   }
 
   if(count%5 == 0)          /*50ms到了*/
   {
     if(showFlag == SHOW_AD){    /*需要显示A/D电压数据时则显示4位电压数据*/
       scanNum="4";
       ADHandler(); 
     }else{
       scanNum="6";      /*需要显示时间时则显示6位时间数据*/
    ModifyTime();
     } 
  
  MotorHandler();
  StatusSend();
   }
  
   if(++count >= 100)         /*1s到了*/
   {
     count="0";
     sec++;
        ModifyTime();     /*调整时间*/
   }
    }
  }
}
/*************************************************************************/
void port_init(void)
{
  PORTB = 0x00;
  DDRB  = 0x2F; /*PB6,PB7作为按键输入;PB4作为SPI的MISO;PB2,3,5作为SPI的SS,MOSI,SCK;*/
  PORTC = 0x00;
  DDRC  = 0xFE; /*AD0作为AD电压采集输入*/
  PORTD = 0x00;
  DDRD  = 0xFB; /*PD2作为按键输入*/
}
/*************************************************************************/
void uart0_init(void)
{
  UCSR0B = 0x00; /*设定波特率前禁用UART*/
  UCSR0A = 0x00;
  UCSR0C = 0x06; /*设定数据格式*/
  UBRR0L = 0x0C; /*波特率设定为38400*/
  UBRR0H = 0x00;
  UCSR0B = 0x98; /*使能UART*/
}
/*************************************************************************/
void timer0_init(void)
{
  TCCR0B = 0x08; /*停止Timer0*/
  TCCR0A = 0x33; /*COM0B[0:1]=11, WGM[0:1]=11, Fast PWM模式*/
  TCNT0 = 0x00;
  OCR0A = 0x64;  /*PWM周期范围为0~100, tPWM="100"*8/8M=100us*/
  OCR0B = 0x64;  /*初始占空比设为0%*/
  TCCR0B |= 0x02;/*启动Timer0*/
  DDRD |= 0x60;  /*OC0A引脚设为输出*/
  //****THIS MUST BE DONE AFTER TCCR0A IS SET TO 0x33!!!
}
/*************************************************************************/
void timer1_init(void)
{
  uchar temp;
  temp="65536-SCAN"_CYCLE;
  TCCR1B = 0x00; /*停止Timer1*/
  TCNT1H=temp>>8;
  TCNT1L=temp-((temp>>8)<<8);
  TCCR1A = 0x00;
  TCCR1B = 0x02; /*启动Timer1*/
}
/*************************************************************************/
void adc_init(void)
{
  ADCSRA = 0x00; /*禁止ADC*/
#ifdef AREF_5
  ADMUX = 0x40;  /*选择ADC0,AREF选为AVCC*/
#endif


#ifdef AREF_11
  ADMUX = 0xc0;  /*选择ADC0,AREF选为内部1.1V*/
#endif
  ADCSRB = 0x00; /*不需要触发源*/
  ADCSRA = 0xE1; /*使能ADC并启动转换*/
}
/*************************************************************************/
void spi_init(void)
{
  SPCR = 0x53; /*使能SPI,主模式,CPHA=0,CPOL=0,fSPI=fOSC/128*/
  SPSR = 0x00; /*禁止中断*/
}
/*************************************************************************/
void twi_init(void)
{
  TWCR= 0x00; /*禁止TWI*/
  TWBR= 0x98; /*设定波特率=8M/(16+2*152*1)=25000*/
  TWSR= 0x00; /*Prescale设为1*/
  TWAR= 0x00; /*Master模式无需设定Slave地址*/
  TWCR= 0x04; /*使能TWI*/
}
/*************************************************************************/
void init_devices(void)
{
  CLI(); //disable all interrupts
  port_init();
  uart0_init();
  timer0_init();
  timer1_init();
  adc_init();
  spi_init();
  twi_init();


  MCUCR = 0x00;
  EICRA = 0x00; //extended ext ints
  EIMSK = 0x00;
 
  TIMSK0 = 0x01; //timer 0 interrupt sources, enable OVF INT
  TIMSK1 = 0x01; //timer 1 interrupt sources, enable OVF INT
  TIMSK2 = 0x00; //timer 2 interrupt sources


  PCMSK0 = 0x00; //pin change mask 0
  PCMSK1 = 0x00; //pin change mask 1
  PCMSK2 = 0x00; //pin change mask 2
  PCICR = 0x00; //pin change enable
  PRR = 0x00; //power controller*/
  SEI(); //re-enable interrupts
}
/*************************************************************************/
#pragma interrupt_handler uart0_rx_isr:19
void uart0_rx_isr(void)  //uart has received a character in UDR
{
  switch(UDR0){  /*解析接收到的命令*/
   case '1': Key1Handler(); break; /*按键A命令*/
   case '2': Key2Handler(); break; /*按键B命令*/
   case '3': Key3Handler(); break; /*按键C命令*/
   case '4': Key4Handler(); break; /*按键D命令*/
  }
}
/*************************************************************************/
#pragma interrupt_handler timer0_ovf_isr:17
void timer0_ovf_isr(void) /*CYCLE=100*8(prescaler)/8M(fosc=fsys=fclki/o)=100/1M=100(us) when fast PWM mode*/
{        
  static int counter="0";
 
  if(counter++ >= 30000){ /*30000*100us=3s到了*/
    counter="0";
  }
 
  if(counter%100 == 0){     /*100*100us=10ms到了*/
    TenMsFlag="1";    /*设置10ms标识位*/
  }
}
/*************************************************************************/
#pragma interrupt_handler timer1_ovf_isr:14
void timer1_ovf_isr(void) /*每SCAN_CYCLE us中断一次*/
{
  uint temp; 
  ScanSeg7();   /*扫描7个数码管*/
  if(musicFlag==0)  /*如果不需要产生音乐频率则按固定扫描时间改变Timer0的中断周期*/
  { 
    temp="65536-SCAN"_CYCLE;
 TCNT1H=temp>>8;
    TCNT1L=temp-((temp>>8)<<8);   
  }
  else              /*如果需要产生音乐频率则按音频改变Timer0的中断周期*/
  {
    PORTB = (PINB & 0xfe) | (~PINB & 0x01); /*翻转一下PORTB0的电平以产生相应频率的方波*/
    TCNT1H=g_TH;    /*重载Timer1中断周期*/
 TCNT1L=g_TL;
  } 
}
/*************************************************************************/
void TxData(char data)  /*UART发送一个字节函数*/
{
  while (!( UCSR0A & (1<<UDRE0)));
  UDR0=data;
}
/*************************************************************************/
void Print(char* info)  /*打印字符串信息*/
{
  int i="0";
  while(*(info+i) != '\0'){
    TxData(*(info + i++));
  }
}
/*************************************************************************/
void ModifyTime(void)         /*调整时间*/
{
  uchar ucharTemp;
  ucharTemp="sec";   
  sec%=60;            /*秒除60取余数为sec*/
  min+=ucharTemp/60;      /*分加上秒的进位先暂存于min*/
  ucharTemp="min";
  min%=60;            /*分再除60取余数为min*/
  hour=(hour+ucharTemp/60)%24; /*时加上分的进位除24取余数为hour时*/
   
  if(showFlag == SHOW_TIME)
  {
 displayArray[0]=(sec%10); /*将时间存入显示缓冲区*/ 
    displayArray[1]=(sec/10);  
    displayArray[2]=(min%10);  
    displayArray[3]=(min/10);  
    displayArray[4]=(hour%10); 
    displayArray[5]=(hour/10);
  }  
}  
/*************************************************************************/
void ClearScr(void)  /*清屏*/
{
  uchar i;   
  for(i=0;i<6;i++)  
  {
    displayArray=0x00;
  }   
}
/*************************************************************************/  
void ScanSeg7()   /*数码管扫描显示*/
{
  static uchar s_scanCounter;
  s_scanCounter++;
  if(s_scanCounter>=scanNum) s_scanCounter=0; /*s_scanCounter>scanNum表示6个数码管都已经扫描过*/
  PORTC = (PINC & 0xf1) | (0x0e & s_scanCounter<<1);
  PORTD = (PIND & 0x27) | (0xc0 & displayArray[s_scanCounter]<<4) | (0x18 & displayArray[s_scanCounter]<<3);

/*************************************************************************/   
void MusicHandler(void)  /*音乐处理模块*/
{
  uchar ucharTemp,ucharTemp1;
  uint temp;
  static uchar s_paiCounter,s_paiNum;
 
  if(++s_paiCounter>=s_paiNum) /*音乐一拍的时间到了*/
  {
    s_paiCounter=0;
 
 if(relayFlag == 1){         /*如果继电器标志打开处理继电器*/
   RelayHandler();
 }
 
    switch(s_musicCounter)      /*根据当前音乐编号查找下一个音乐标识码*/
    {
 case 0x01: ucharTemp="c"_music1[s_tableCounter++];break;
 case 0x02: EEPROM_Read(s_tableCounter++, &ucharTemp, 1);break;
 case 0x03: TwiRead(0x50, s_tableCounter++, &ucharTemp, 1);break;
 case 0x04: AT93C46_Read(s_tableCounter++, &ucharTemp, 1);break;
 }   
  
 if(ucharTemp==0x00)             /*如果查到0x00则表示本首歌曲结束*/
 {
   musicFlag="0";                  /*产生音乐频率标志置零*/
   temp="65536-SCAN"_CYCLE;
   TCNT1H=temp>>8;               /*temp/256相当于右移8位*/
   TCNT1L=temp-((temp>>8)<<8);   /*temp%256*/
   s_paiNum=4*PAI_BASE;          /*本首歌曲结束后停顿4*PAI_BASE*10ms=600ms再继续播放*/
   PORTB |= 0x01;                /*把喇叭关掉*/
   s_tableCounter=0;
   if(++s_musicCounter>(uchar)MUSIC_NUM)  /*几首音乐都播放完了就重新开始*/
   {
  s_musicCounter=0x01;
   }
 }
 else                                     /*如果查到非0x00则表示是音乐标识码*/
 {      
   s_paiNum=(ucharTemp&0x0f)*PAI_BASE;    /*音乐标识码的低四位为节拍码*/
   ucharTemp1=(ucharTemp&0xf0)>>4;        /*音乐标识码的高四位为音频码*/
   if(ucharTemp1==0)                      /*如果音频码为零则表示不发音*/
   {
  musicFlag=0;
     temp="65536-SCAN"_CYCLE;
  TCNT1H=temp>>8;                      /*temp/256相当于右移8位*/
  TCNT1L=temp-((temp>>8)<<8);          /*temp%256*/
  musicFlag=0;
   }
   else                                   /*如果音频码不为零则按此改变Timer0的中断周期*/
   {
  musicFlag=0;
  temp=c_musicFreq[ucharTemp1-1];
  g_TH=TCNT1H=temp>>8;                 /*temp/256相当于右移8位*/
  g_TL=TCNT1L=temp-((temp>>8)<<8);     /*temp%256,同时保存新的代表音频的Timer0周期值*/
  musicFlag=1;
   }
 }
  }
}
/*************************************************************************/
void ADHandler(void)  /*数据采集模块*/
{
  uint adresult,sum;
  uchar tmpL,tmpH;
  uchar i;
 
  tmpL="ADCL";
  tmpH="ADCH";


  adresult = (((uint)tmpH)<<8) + tmpL;  /*得到10位A/D采集数据*/
#ifdef AREF_5
  adresult = (adresult<<2) + adresult - (adresult>>3) + (adresult>>4);
  /*10位结果转换为电压比例:5000/1024=4.88 近似为(4+1-1/8+1/256)=4.879*/
#endif


#ifdef AREF_11
  adresult = adresult + (adresult>>4) + (adresult>>7) + (adresult>>8);
  /*10位结果转换为电压比例:1100/1024=0.07421875 近似为(1 + 1/16 + 1/128 + 1/256)*/
#endif
 
  sum="adresult";  /*将采集的电压值转换到四位数码管显示*/
  displayArray[3]=sum/1000;
  sum="sum-displayArray"[3]*1000;
  displayArray[2]=sum/100;
  sum="sum-displayArray"[2]*100;
  displayArray[1]=sum/10;
  sum="sum-displayArray"[1]*10;
  displayArray[0]=sum;
 
  displayArray[4]=0;  /*最高两位数码管清0*/
  displayArray[5]=0;
}
/*************************************************************************/
void RelayHandler(void)  /*继电器处理模块*/
{
  static char flg="0";
 
  if(flg){
    PORTB &= 0xfd;
    flg="0";
  }else{
    PORTB |= 0x02;
    flg="1";
  }
}
/*************************************************************************/
void MotorHandler(void)  /*电机处理模块*/
{
  if(motorFlag){
    if(OCR0B >= 0x3C)  /*电机电压范围为1~2V*, 当超过2V时不再升高电压*/
    {
      OCR0B--;
    }
  }
}
/*************************************************************************/
void Delay(int num)  /*延时模块*/
{
  int i;
  for(i=0;i<num;i++){
    i="i";
  }
}
/*************************************************************************/
char ScanKeys(void)  /*键盘扫描模块*/
{
  if((PIND & 0x04) == 0x00)  /*扫描A键*/
  {
    Delay(1000);  /*延时消除抖动*/
    if((PIND & 0x04) == 0x00)
    {
      while((PIND & 0x04) == 0x00); /*没放开就等按键放开*/
      return KEY1;  /*返回A键键值*/
 }
  } 
 
  if((PINB & 0x40) == 0x00)  /*扫描B键*/
  {
    Delay(1000);  /*延时消除抖动*/
    if((PINB & 0x40) == 0x00)
    {
      while((PINB & 0x40) == 0x00); /*没放开就等按键放开*/
      return KEY2;  /*返回B键键值*/
 }
  } 
 
  if((PINB & 0x80) == 0x00)  /*扫描C键*/
  {
    Delay(1000);  /*延时消除抖动*/
    if((PINB & 0x80) == 0x00)
    {
      while((PINB & 0x80) == 0x00); /*没放开就等按键放开*/
      return KEY3;  /*返回C键键值*/
 }
  } 
 
  return KEY0;  /*无键被按则返回无按键值*/
}
/*************************************************************************/
void Key1Handler(void)  /*按键A处理模块*/
{
  static char flg="0";
 
  if(flg == 0){
    showFlag = SHOW_AD;    /*显示A/D数据*/
 flg=1;
  }else{
    showFlag = SHOW_TIME;  /*显示时间*/
 flg=0;
  }
}
/*************************************************************************/
void Key2Handler(void)  /*按键B处理模块*/
{
  static char flg="0";
 
  if(flg == 0){   /*自动播放音乐,同时继电器作配乐*/
    musicPlayFlag = 1;
 relayFlag = 1;
 flg=1;
  }else{            /*停止音乐播放,也停止继电器*/
    musicPlayFlag = 0;
 relayFlag = 0;
 musicFlag=0;
 s_tableCounter=0;
 s_musicCounter=0x01;
 flg=0;
  }
}
/*************************************************************************/
void Key3Handler(void)  /*按键C处理模块*/
{
  if(motorFlag == 0){   /*电机开始从软启动到稳定运行*/
    motorFlag = 1;
 OCR0B=0x50;     /*软启动从5V的20%=1V开始,1V=20%*5V -> 20%*0x64=0x14 -> 0x64-0x14=0x50*/
  }else{     /*电机停止运行*/
    motorFlag = 0;
 OCR0B=0x64;     /*占空比设为0%,电机停止运行*/
  }
}
/*************************************************************************/
void Key4Handler(void)  /*模拟按键D处理模块*/
{
  if(musicPlayFlag){    /*音乐播放中才起作用*/
    musicFlag="0";
 s_tableCounter=0;
 if(++s_musicCounter > MUSIC_NUM){ /*指定下一首歌曲*/
   s_musicCounter=0x01;
 }
  }
}
/*************************************************************************/
void StatusSend(void)  /*开发板运行状态反馈,共7个字节状态*/
{
  char i, status;
  for(i=0;i<6;i++){    /*前6个字节为数码管数字*/
    TxData(displayArray);
  } 
/* 第7个字节定义如下:
status: |    Bit7    |   Bit6   |   Bit5   |     Bit4     |      Bit3:0      |
          musicPlayFlag  relayFlag  motorFlag softstartFlag Playing music number */
  if(musicPlayFlag){ /*如果音乐在播放,置音乐播放标志,同时把播放音乐的序号存入Status的低四位*/
    status |= 0x80;
 status = (status & 0xf0) | (s_musicCounter & 0x0f);
  }else{
    status &= 0x70;
  }
  if(!(PINB & 0x02)){/*如果继电器在运行,置继电器运行标志*/
    status |= 0x40;
  }else{
    status &= 0xbf;
  }
  if(motorFlag){     /*置电机的软启动和稳定运行标志*/
    status |= 0x20;
  }else{
    status &= 0xdf;
  }
  if(motorFlag && OCR0B>= 0x3C){
    status |= 0x10;
  }else{
    status &= 0xef;
  }
  TxData(status);    /*发送第7状态字节*/
}
/*****************************EEPROM Functions****************************/
void EEPROM_Write(uint addr, const char* dat, int len) /*写EEPROM函数*/
{
  int i;
 
  for(i=0;i<len;i++){
    while(EECR & (1<<EEPE)); /*等待前一字节写完成*/
    EEAR = addr+i;  /*指定写入起始地址和数据*/
    EEDR = *(dat+i);
    EECR |= (1<<EEMPE); /*写1到EEMPE*/
    EECR |= (1<<EEPE);  /*写启动*/
  }
}
/*************************************************************************/
void EEPROM_Read(uint addr, char* dat, int len) /*读EEPROM函数*/
{
  int i;
 
  for(i=0;i<len;i++){
    while(EECR & (1<<EEPE)); /*等待前一字节写完*/
    EEAR = addr+i; /*指定读出起始地址*/
    EECR |= (1<<EERE); /*读启动*/
    *(dat+i)=EEDR; /*读取数据*/
  }
}
/*************************************************************************/
#ifdef INIT_EEPROM  /*如果打开初始化EEPROM编译选项则以下参加编译*/
void EEPROMInit(void) /*将音乐数据写入EEPROM*/
{
  char rcv;
  int i;
  
  EEPROM_Write(0x00, c_music2, sizeof(c_music2)); /*写入音乐数据*/
 
  for(i=0;i<sizeof(c_music2);i++){
    EEPROM_Read((char)i, &rcv, 1);
    if(rcv != c_music2){
   Print("Error!");
 }
  }
}
#endif /*INIT_EEPROM*/
/*************************End of EEPROM Functions*************************/
/*******************************TWI Functions*****************************/
void TwiWrite(char sladdr, char addr, const char* dat, int len) /*24C02写入函数*/
{
  int i;
 
  for(i=0;i<len;i++){ /*启动总线*/
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != START)  ERROR(START);
 
    TWDR = (sladdr<<1) & 0xfe; /*指定SLAVE设备*/
    TWCR = (1<<TWINT) | (1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != MT_SLA_ACK)  ERROR(MT_SLA_ACK);
 
    TWDR = addr+i; /*指定需要写入的SLAVE地址*/
    TWCR = (1<<TWINT) | (1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != MT_DATA_ACK)  ERROR(MT_DATA_ACK);
 
    TWDR = *(dat+i); /*写入数据*/
    TWCR = (1<<TWINT) | (1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != MT_DATA_ACK)  ERROR(MT_DATA_ACK);
 
    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); /*停止总线*/
 
    Delay(1000);
  }
}
/*************************************************************************/
void TwiRead(char sladdr, char addr, char* dat, int len) /*24C02读函数*/
{
  int i;
 
  for(i=0;i<len;i++){ /*启动总线*/
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != START)  ERROR(START);


    TWDR = (sladdr<<1) & 0xfe; /*指定SLAVE设备*/
    TWCR = (1<<TWINT) | (1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != MT_SLA_ACK)  ERROR(MT_SLA_ACK);


    TWDR = addr+i; /*指定需要读出的地址*/
    TWCR = (1<<TWINT) | (1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != MT_DATA_ACK)  ERROR(MT_DATA_ACK);
 
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); /*重新启动总线*/
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != START)  ERROR(START);


    TWDR = (sladdr<<1) | 0x01; /*指定SLAVE设备*/
    TWCR = (1<<TWINT) | (1<<TWEN);
    while (!(TWCR & (1<<TWINT)));
    if ((TWSR & 0xF8) != MR_SLA_ACK)  ERROR(MR_SLA_ACK);


    TWCR = (1<<TWINT) | (1<<TWEN); /*发送任意数据*/
    while (!(TWCR & (1<<TWINT))); 
    if ((TWSR & 0xF8) != MR_DATA_NACK)  ERROR(MR_DATA_NACK);
    *(dat+i) = TWDR; /*读取数据*/


    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); /*停止总线*/
  }
}
/*************************************************************************/
#ifdef INIT_24C02 /*如果打开初始化24C02编译选项则以下参加编译*/
void Twi24C02Init(void) /*将音乐数据写入24C02*/
{
  char rcv;
  int i;
 
  TwiWrite(0x50, 0x00, c_music3, sizeof(c_music3)); /*将音乐数据写入24C02*/
 
  for(i=0;i<sizeof(c_music3);i++){
    TwiRead(0x50, i, &rcv, 1);
    if(rcv != c_music3){
   Print("Error!");
 }
  }
}
#endif /*INIT_24C02*/
/**************************End of TWI Functions***************************/
/*******************Functions for AT93C46(8 bits mode)********************/
void AT93C46_EraseAll(void) /*93C46全部擦除函数*/

  AT93C46_Eren(); /*擦写使能*/
 
  CS(1);
  SPDR = 0x02; /*擦写指令前部分*/
  while(!(SPSR & (1<<SPIF)));
  SPDR = 0x40; /*擦写指令后部分*/
  while(!(SPSR & (1<<SPIF)));
  CS(0);
  Delay(1); /*拉低CS至少250ns*/
  CS(1);
  do{ /*等待擦完*/
    SPDR="0x00";
 while(!(SPSR & (1<<SPIF)));
  }while(SPDR == 0x00);
  CS(0);
 
  AT93C46_Erds(); /*擦写禁止*/
}
/*************************************************************************/
void AT93C46_Eren(void) /*93C46擦写使能函数*/
{
  CS(1);
  SPDR = 0x02; /*擦写使能指令前部分*/
  while(!(SPSR & (1<<SPIF)));
  SPDR = 0x60; /*擦写使能指令后部分*/
  while(!(SPSR & (1<<SPIF)));
  CS(0);
}
/*************************************************************************/
void AT93C46_Erds(void) /*93C46擦写禁止函数*/
{
  CS(1);
  SPDR = 0x02; /*擦写禁止指令前部分*/
  while(!(SPSR & (1<<SPIF)));
  SPDR = 0x00; /*擦写禁止指令后部分*/
  while(!(SPSR & (1<<SPIF)));
  CS(0);
}
/*************************************************************************/
void AT93C46_Erone(char addr) /*93C46擦写一个字节函数*/
{
  CS(1);
  SPDR = 0x03; /*擦写一字节指令前部分*/
  while(!(SPSR & (1<<SPIF)));
  SPDR = addr | 0x80; /*擦写一字节指令后部分*/
  while(!(SPSR & (1<<SPIF)));
  CS(0);
  Delay(1); /*拉低CS至少250ns*/
  CS(1);
  do{ /*等待擦完*/
    SPDR="0x00";
 while(!(SPSR & (1<<SPIF)));
  }while(SPDR == 0x00);
  CS(0);
}
/*************************************************************************/
void AT93C46_Read(char addr, char* dat, int len) /*93C46从指定地址读若干字节函数*/
{
  int i;
  char t1,t2;
 
  for(i=0;i<len;i++){
    CS(1);
    SPDR = 0x03; /*读指令前部分*/
    while(!(SPSR & (1<<SPIF)));
    SPDR = addr & 0x7f; /*读指令后部分*/
    while(!(SPSR & (1<<SPIF)));
    SPDR = 0x00; /*发任意数据*/
    while(!(SPSR & (1<<SPIF)));
 t1=SPDR; /*读取前部分数据*/
 SPDR = 0x00;
    while(!(SPSR & (1<<SPIF)));
 t2=SPDR; /*读取后部分数据*/
    *(dat+i)=((t1<<1) & 0xfe) | ((t2>>7) & 0x01); /*整合以上两数据,去掉Dummy bit*/
    CS(0);
  }
}
/*************************************************************************/
void AT93C46_Write(char addr, const char* dat, int len) /*93C46从指定地址读取若干字节函数*/
{
  int i;
  AT93C46_Eren(); /*擦写使能*/
 
  for(i=0;i<len;i++){
    CS(1);
    Delay(1);
    SPDR = 0x02; /*写指令前部分*/
    while(!(SPSR & (1<<SPIF)));
    SPDR = addr++ | 0x80; /*写指令后部分*/
    while(!(SPSR & (1<<SPIF)));
    SPDR = *(dat+i); /*写入数据*/
    while(!(SPSR & (1<<SPIF)));
    CS(0);
    Delay(1); /*拉低CS至少250ns*/
    CS(1);
    do{  /*等待写完成*/
      SPDR="0x00";
   while(!(SPSR & (1<<SPIF)));
   TxData(SPDR);
    }while(SPDR == 0x00);
    CS(0);
  }
 
  AT93C46_Erds(); /*擦写禁止*/
}
/*************************************************************************/
#ifdef INIT_93C46 /*如果打开初始化93C46编译选项则以下参加编译*/
void AT93C46Init(void) /*写音乐数据到93C46*/
{
  char rcv;
  int i;
 
  AT93C46_Write(0x00, c_music4, sizeof(c_music4)); /*写音乐数据到93C46*/
 
  for(i=0;i<sizeof(c_music4);i++){
    AT93C46_Read((char)i, &rcv, 1);
    if(rcv != c_music4){
   Print("Error!");
 }
  }
}
#endif /*INIT_93C46*/
/*********************End of Functions for AT93C46************************/


/******************************************************************************/
////////////////////////////////End of Program//////////////////////////////////
/******************************************************************************/

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
3
关闭 站长推荐上一条 /2 下一条