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

📄 main__.c

📁 使用AVR单片机实现的万年历功能,其中使用了ds1302和1602
💻 C
📖 第 1 页 / 共 5 页
字号:

				};

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

				case 0b11010000:
					keyReturn = key6;
					break;

				case 0b10110000:
					keyReturn = key7;
					break;

				case 0b01110000:
					keyReturn = key8;
					break;

				};
			}

		}
		else
		{
			keyState = keyState0;
		}

		break;

	case keyState2:         //状态2中判断按键是否已经释放,如果已经释放则返回状态0

		keyOutput1 = 0;
		keyOutput2 = 0;

		if ((keyInput & keyMask) == keyMask)
		{
			keyState = keyState0;
		}

		break;

	};

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







#include "lcd.c"
#include "lcd.h"
#include <delay.h>
#include <string.h>

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

void LcdWriteData(unsigned char data)
{
	AVRSetLcdDataPortWriteMode;
	LCD1602SetWriteMode;
	LCD1602SetDataMode;
	LCD1602ClrEnable;
	#asm("nop")
	#asm("nop")
	LCD1602WriteDataPort = data;
	LCD1602SetEnable;
	#asm("nop")
	#asm("nop")
	LCD1602ClrEnable;
	#asm("nop")
	#asm("nop")
}

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

void LcdWriteInstruction(unsigned char data)
{
	AVRSetLcdDataPortWriteMode;
	LCD1602SetWriteMode;
	LCD1602SetInstructionMode;
	LCD1602ClrEnable;
	#asm("nop")
	#asm("nop")
	LCD1602WriteDataPort = data;
	LCD1602SetEnable;
	#asm("nop")
	#asm("nop")
	LCD1602ClrEnable;
	#asm("nop")
	#asm("nop")
}

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

unsigned char LcdReadInstruction(void)
{
	unsigned char data;
	AVRSetLcdDataPortReadMode;
	LCD1602SetReadMode;
	LCD1602SetInstructionMode;
	LCD1602ClrEnable;
	#asm("nop")
	#asm("nop")
	LCD1602SetEnable;
	#asm("nop")
	#asm("nop")
	data = LCD1602ReadDataPort;
	LCD1602ClrEnable;
	#asm("nop")
	#asm("nop")
	return data;
}

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

unsigned char LcdReadData(void)
{
	unsigned char data;
	AVRSetLcdDataPortReadMode;
	LCD1602SetReadMode;
	LCD1602SetDataMode;
	LCD1602ClrEnable;
	#asm("nop")
	#asm("nop")
	LCD1602SetEnable;
	#asm("nop")
	#asm("nop")
	data = LCD1602ReadDataPort;
	LCD1602ClrEnable;
	#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)
{
	AVRInitLcdControlPort;
	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++;
	}

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


/************************************************************
Timer1比较匹配中断处理函数
************************************************************/
interrupt [TIM1_COMPA] 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 = maxMusic1;
		break;

	case 2:
		pMusic = music2;
		maxMusic = maxMusic2;
		break;

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

	case 4:
		pMusic = music4;
		maxMusic = maxMusic4;
		break;

	case 5:
		pMusic = music5;
		maxMusic = maxMusic5;
		break;

	case 6:
		pMusic = music6;
		maxMusic = maxMusic6;
		break;

	case 7:
		pMusic = music7;
		maxMusic = maxMusic7;
		break;

	case 8:
		pMusic = music8;
		maxMusic = maxMusic8;
		break;

	case 9:
		pMusic = music9;
		maxMusic = maxMusic9;
		break;

	case 10:
		pMusic = music10;
		maxMusic = maxMusic10;
		break;

	};

	playCycle = counterChoose;     //音乐播放次数赋值
	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;
	}

	TCCR1B = 0x0A;     //开启定时器工作
}

void PlayMusic1(unsigned char counter1)
{
	pMusic = music1;
	maxMusic = maxMusic1;
	playCycle = counter1;
	OCR1A = dataOfOCR1A[pMusic[0]];
	iCompaCycle = counter[pMusic[0]] * pMusic[1];
	iMusicCycle = 1;
	TCCR1B = 0x0A;
}

void PlayMusic2(unsigned char counter2)
{
	pMusic = music2;
	maxMusic = maxMusic2;
	playCycle = counter2;
	OCR1A = dataOfOCR1A[pMusic[0]];
	iCompaCycle = counter[pMusic[0]] * pMusic[1];
	iMusicCycle = 1;
	TCCR1B = 0x0A;
}

void PlayMusic3(unsigned char counter3)
{
	pMusic = music3;
	maxMusic = maxMusic3;
	playCycle = counter3;
	OCR1A = dataOfOCR1A[pMusic[0]];
	iCompaCycle = counter[pMusic[0]] * pMusic[1];
	iMusicCycle = 1;
	TCCR1B = 0x0A;
}

void PlayMusic4(unsigned char counter4)
{

⌨️ 快捷键说明

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