⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.i

📁 使用AVR单片机实现的万年历功能,其中使用了ds1302和1602
💻 I
📖 第 1 页 / 共 5 页
字号:
/************************************************
函数unsigned char FindKeyValue (void)用于查找键值
************************************************/
unsigned char FindKeyValue (void)
{
	unsigned keyReturn;    //返回的键值,并初始化为无键值
	keyReturn = 0;			

	switch (keyState)
	{
	case 0:
		PORTD.7				 = 1;			//第二行置高电平
		PORTD.6				 = 0;			//第一行置低电平,扫描第一行

		keyValue = PINB       				 & keyMask;	//读取键值

		if(keyValue != keyMask)			//如果有键按下,则进入状态1
		{
			keyState = 1;
		}
		else							//否则第一行置高电平,第二行置低电平,扫描第二行
		{
			PORTD.6				 = 1;
			PORTD.7				 = 0;
			keyValue = PINB       				 & keyMask;   //读取键值

			if(keyValue != keyMask)			//如果有键按下,则进入状态1
			{
				keyState = 1;
			}
			else							//否则第二行也置高电平
			{
				PORTD.7				 = 1;
			}

		}

		break;
		
	case 1:

		if (keyValue == (PINB       				 & keyMask))	//如果读取的按键值和上次一样,则进入状态2,并判断按键,否则进入状态0
		{
			keyState = 2;

			if (PORTD.6				)
			{
				switch(keyValue)
				{
				case 0b11100000:
					keyReturn = 1;
					break;

				case 0b11010000:
					keyReturn = 2;
					break;

				case 0b10110000:
					keyReturn = 3;
					break;

				case 0b01110000:
					keyReturn = 4;
					break;

				};

			}
			else
			{
				switch(keyValue)
				{
				case 0b11100000:
					keyReturn = 5;
					break;

				case 0b11010000:
					keyReturn = 6;
					break;

				case 0b10110000:
					keyReturn = 7;
					break;

				case 0b01110000:
					keyReturn = 8;
					break;

				};
			}

		}
		else
		{
			keyState = 0;
		}

		break;

	case 2:         //状态2中判断按键是否已经释放,如果已经释放则返回状态0
		
		PORTD.6				 = 0;
		PORTD.7				 = 0;

		if ((PINB       				 & keyMask) == keyMask)
		{
			keyState = 0;
		}

		break;
		
	};
	
	return keyReturn;//返回读取的键值
}








   

         



// CodeVisionAVR C Compiler
// (C) 1998-2000 Pavel Haiduc, HP InfoTech S.R.L.


#pragma used+

void delay_us(unsigned int n);
void delay_ms(unsigned int n);

#pragma used-

// CodeVisionAVR C Compiler
// (C) 1998-2007 Pavel Haiduc, HP InfoTech S.R.L.

// Prototypes for string functions



#pragma used+

char *strcat(char *str1,char *str2);
char *strcatf(char *str1,char flash *str2);
char *strchr(char *str,char c);
signed char strcmp(char *str1,char *str2);
signed char strcmpf(char *str1,char flash *str2);
char *strcpy(char *dest,char *src);
char *strcpyf(char *dest,char flash *src);
unsigned int strlenf(char flash *str);
char *strncat(char *str1,char *str2,unsigned char n);
char *strncatf(char *str1,char flash *str2,unsigned char n);
signed char strncmp(char *str1,char *str2,unsigned char n);
signed char strncmpf(char *str1,char flash *str2,unsigned char n);
char *strncpy(char *dest,char *src,unsigned char n);
char *strncpyf(char *dest,char flash *src,unsigned char n);
char *strpbrk(char *str,char *set);
char *strpbrkf(char *str,char flash *set);
char *strrchr(char *str,char c);
char *strrpbrk(char *str,char *set);
char *strrpbrkf(char *str,char flash *set);
char *strstr(char *str1,char *str2);
char *strstrf(char *str1,char flash *str2);
char *strtok(char *str1,char flash *str2);
 
unsigned int strlen(char *str);
void *memccpy(void *dest,void *src,char c,unsigned n);
void *memchr(void *buf,unsigned char c,unsigned n);
signed char memcmp(void *buf1,void *buf2,unsigned n);
signed char memcmpf(void *buf1,void flash *buf2,unsigned n);
void *memcpy(void *dest,void *src,unsigned n);
void *memcpyf(void *dest,void flash *src,unsigned n);
void *memmove(void *dest,void *src,unsigned n);
void *memset(void *buf,unsigned char c,unsigned n);
unsigned int strcspn(char *str,char *set);
unsigned int strcspnf(char *str,char flash *set);
int strpos(char *str,char c);
int strrpos(char *str,char c);
unsigned int strspn(char *str,char *set);
unsigned int strspnf(char *str,char flash *set);

#pragma used-
#pragma library string.lib



//函数void LcdWriteData(unsigned char data)用于向LCD写入一个数据

void LcdWriteData(unsigned char data)
{
	DDRA = 0xFF	;  
	PORTB.1 = 0				;
	PORTB.2 = 1				;
	PORTB.0 = 0				;
	#asm("nop")
	#asm("nop")
	PORTA				 = data;
	PORTB.0 = 1				;
	#asm("nop")
	#asm("nop")
	PORTB.0 = 0				;
	#asm("nop")
	#asm("nop")
}

//函数void LcdWriteInstruction(unsigned char data)用于向LCD写入一个指令

void LcdWriteInstruction(unsigned char data)
{
	DDRA = 0xFF	;
	PORTB.1 = 0				;
	PORTB.2 = 0		;
	PORTB.0 = 0				;
	#asm("nop")
	#asm("nop")
	PORTA				 = data;
	PORTB.0 = 1				;
	#asm("nop")
	#asm("nop")
	PORTB.0 = 0				;
	#asm("nop")
	#asm("nop")
}

//函数unsigned char LcdReadInstruction(void)用于从液晶读取指令

unsigned char LcdReadInstruction(void)
{
	unsigned char data;
	DDRA = 0x00	;
	PORTB.1 = 1				;
	PORTB.2 = 0		;
	PORTB.0 = 0				;
	#asm("nop")
	#asm("nop")
	PORTB.0 = 1				;
	#asm("nop")
	#asm("nop")
	data = PINA				;
	PORTB.0 = 0				;
	#asm("nop")
	#asm("nop")
	return data;
}

//函数unsigned char LcdReadData(void)用于从液晶读取一个字节的数据

unsigned char LcdReadData(void)
{
	unsigned char data;
	DDRA = 0x00	;
	PORTB.1 = 1				;
	PORTB.2 = 1				;
	PORTB.0 = 0				;
	#asm("nop")
	#asm("nop")
	PORTB.0 = 1				;
	#asm("nop")
	#asm("nop")
	data = PINA				;
	PORTB.0 = 0				;
	#asm("nop")
	#asm("nop")
	return data;
}

//函数void LcdCheckBusy(void)用于跳过液晶的忙状态

void LcdCheckBusy(void)
{
	
	while (0x80 == (LcdReadInstruction() & 0x80))
	{
	}

}

//函数void LcdClear(void)用于液晶清屏

void LcdClear(void)
{
	LcdCheckBusy();
	LcdWriteInstruction(0x01);
}

//函数void LcdInit(void)用于初始化液晶

void LcdInit(void)
{
	DDRB |= 0x07		;
	delay_ms(15);
	LcdWriteInstruction(0x38);  //LCD内部要求,初始化的时候连续三次设置显示模式
	delay_ms(5);
	LcdWriteInstruction(0x38);
	delay_ms(5);
	LcdWriteInstruction(0x38);
	LcdCheckBusy();
	LcdWriteInstruction(0x38);	//8位数据接口
	LcdCheckBusy();
	LcdWriteInstruction(0x08);	//关显示
	LcdCheckBusy();
	LcdWriteInstruction(0x01);	//清屏
	LcdCheckBusy();
	LcdWriteInstruction(0x06);	//读或者写一个字符后地址指针加1
	LcdCheckBusy();
	LcdWriteInstruction(0x0C);	//开显示,不显示光标
}

//函数void LcdSetXY(unsigned char x, unsigned char y)用于指定液晶数据写入的地址

void LcdSetXY(unsigned char x, unsigned char y)
{
	unsigned char addr;
	addr = 0x80 + x * 0x40 + y;	//计算地址
	LcdCheckBusy();
	LcdWriteInstruction(addr);
}

//函数void LcdPutOneChar(unsigned char c)用于向液晶输入一个显示数据

void LcdPutOneChar(unsigned char c)
{
	LcdCheckBusy();
	LcdWriteData(c);
}

//函数void LcdPutFlashString(unsigned char flash *str)用于向液晶输入位于Flash中的一个字符串

void LcdPutFlashString(unsigned char flash *str)
{
	unsigned char i;
	i = 0;

	while (str[i] != '\0')
	{
		LcdCheckBusy();
		LcdWriteData(str[i]);
		i++;
	}

}

//函数void LcdPutRamString(unsigned char *str)用于向液晶输入位于Ram中的一个字符串

void LcdPutRamString(unsigned char *str)
{
	unsigned char i;
	i = 0;

	while (str[i] != '\0')
	{
		LcdCheckBusy();
		LcdWriteData(str[i]);
		i++;
	}

}
						
    
	



    
     



/************************************************************
播放音乐使能TIME1之前必须完成以下工作
初始化*pMusic指针,使其指向某一首音乐
初始化maxMusic,使其等于*pMusic指针指向的音乐的数据的个数
初始化音乐播放的次数playCycle
初始化OCR1A,使其对应于第一个音符
初始化第一个音符比较匹配的次数iCompaCycle
初时话iMusicCycle为1
************************************************************/
/************************************************************
播放音乐使能TIME1之前必须完成以下工作
初始化*pMusic指针,使其指向某一首音乐
初始化maxMusic,使其等于*pMusic指针指向的音乐的数据的个数
初始化音乐播放的次数playCycle
初始化OCR1A,使其对应于第一个音符
初始化第一个音符比较匹配的次数iCompaCycle
初时话iMusicCycle为1
************************************************************/


/************************************************************
Timer1比较匹配中断处理函数
************************************************************/
interrupt [7] void Timer1CompaIsr(void)
interrupt [7] void Timer1CompaIsr(void)
interrupt [7] void Timer1CompaIsr(void)
{
	
	if (--iCompaCycle == 0)                   //比较匹配次数是否到了
	{
		if(iMusicCycle < maxMusic)           // 判断最后一个音符是否已经被播放
		{     
			OCR1A = dataOfOCR1A[pMusic[++iMusicCycle]];        //装入下一个音符的数据
			iCompaCycle = counter[pMusic[iMusicCycle]];        
			iCompaCycle = iCompaCycle * pMusic[++iMusicCycle];
																
			if(OCR1A == 2500)						// IF语句判断OCR1A中是否是装入了空音符的数据,如果是的话就把PD5释放
			{
				TCCR1A = 0x00;
			}
			else if (TCCR1A == 0x00)     //非空音符时,如果PD5引脚已经释放,则与OCR1连接
			{
				TCCR1A = 0x40;
			}

		}
		else if(--playCycle != 0)                              //判断播放次数是否已经为0
		{
			OCR1A = dataOfOCR1A[pMusic[0]];                    //重新装入第一个音符的数据
			iCompaCycle = counter[pMusic[0]] * pMusic[1];
			iMusicCycle = 1;
			 
            if(OCR1A == 2500)		// IF语句判断OCR1A中是否是装入了空音符的数据,如果是的话就把PD5释放
			{
				TCCR1A = 0x00;
			}
			else if (TCCR1A == 0x00)	//非空音符时,如果PD5引脚已经释放,则与OCR1连接
			{
				TCCR1A = 0x40;
			}

		}
		else
		{
			TCCR1B = 0x08;    //播放结束,关闭TIME1的时钟
		}

	}
}
/************************************************************
函数MusicInit用于初始化音乐播放
************************************************************/
void MusicInit(void)
{
	DDRD.5 = 1;            //设置PD5为输出引脚
   	PORTD.5 = 0;			//
    	TCCR1A = 0x40;		//比较匹配时触发PD5引脚
    	TCCR1B = 0x08;		//CTC模式,先不启动定时器
	TIMSK |= 0x10;			//开放定时器1的比较匹配功能
}
/************************************************************
函数void PlayMusic(unsigned char musicChoose, unsigned char counterChoose)
中musicChoose为选择播放的音乐,counterChoose为播放次数
************************************************************/
void PlayMusic(unsigned char musicChoose, unsigned char counterChoose)
{
	//switch语句把选择的音乐序号对应的音乐数据付给pMusic指针
	switch (musicChoose)
	{
	case 1:
		pMusic = music1;
		maxMusic = 273	;
		break;
	
	case 2:
		pMusic = music2;
		maxMusic = 223	;
		break;

	case 3:
		pMusic = music3;
		maxMusic = 137   ;
		break;

	case 4:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -