/*
* 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//////////////////////////////////
/******************************************************************************/
文章评论(0条评论)
登录后参与讨论