Demo entry 6352830

liu

   

Submitted by liu on Mar 26, 2017 at 15:50
Language: C. Code size: 11.2 kB.

#include <reg51.h>
#include <absacc.h>
#include <ctype.h>
#include <string.h>
#include "I2C.h"
#include "VolTab.h"

sbit BUZZER = P1^0;		//交流蜂鸣器由P1.0管脚控制
sbit CS = P1^5;
sbit DAT = P1^7;
sbit CLK = P1^6;
sbit KEY2 = P2^0;
sbit KEY3 = P2^1;

//定义音名
//L1~L7表示低音,M1~M7表示中音,H1~H7表示高音
#define L1	0xF91F	//261.63(单位:Hz,下同)
#define L2	0xF9DF	//293.66
#define L3	0xFA8A	//329.63
#define L4	0xFAD9	//349.23(低音3到低音4为半音)
#define L5	0xFB68	//392.00
#define L6	0xFBE9	//440.00
#define L7	0xFC5B	//493.88
#define M1	0xFC8F	//523.25(低音7到中音1为半音)
#define M2	0xFCEF	//587.33
#define M3	0xFD45	//659.26
#define M4	0xFD6C	//698.46(中音3到中音4为半音)
#define M5	0xFDB4	//783.99
#define M6	0xFDF4	//880.00
#define M7	0xFE2D	//987.77
#define H1	0xFE48	//1046.5(中音7到高音1为半音)
#define H2	0xFE78	//1174.7
#define H3	0xFEA3	//1318.5
#define H4	0xFEB6	//1396.9(高音3到高音4为半音)
#define H5	0xFEDA	//1568.0
#define H6	0xFEFA	//1760.0
#define H7	0xFF17	//1975.5

#define PWM_MAX 249

volatile unsigned char task = 1;
unsigned char DispBuf[8];
unsigned char s[8];

unsigned int cnt1 = 0,cnt2 = 800,cnt3 = 0;
unsigned char cnt2_temp = 0;

volatile unsigned int cnt_delay = 0;
unsigned int cnt_key = 0;
unsigned char key_flag = 0;

volatile char ReloadH;
volatile char ReloadL;
unsigned char buz_led = 0;
//播放的音乐表
code unsigned int MusicTab[] = {H1,H7,H6,H5,H4,H3,H2,M1};

bit led_con = 0;
volatile int temp = 0;
unsigned char init_temp = 50;
unsigned char temp_flag = 0;
unsigned char envir_temp;

unsigned char PwmValue;
//------------------------------------
//**********数码管显示部分************
//------------------------------------
/*
函数:DispChar()
功能:在特定位的数码管上显示字符以及小数点
*/
void DispChar(unsigned char x,unsigned char c,bit dp)
{
	code unsigned char Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
								0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
	unsigned char t;
	x &= 0x07;
	x = 7-x;

	if(c == '-')
	{	t = 0x40;}
	else
	{
		t=toint(c);
		if(t < 16)
		{	t = Tab[t];}
		else
		{	t = 0x00;}
		if(dp)
		{	t |= 0x80;}
		else
		{	t &= 0x7f;}
	}
	DispBuf[x] = t;
}
/*
函数:DispStr()
功能:从数码管的特定位开始显示字符串
*/
void DispStr(unsigned char x, unsigned char *s)
{
	unsigned char c;
	for (;;)
	{
		c = *s;
		if ( c == '\0' ) break;
		s++;
		DispChar(x,c,0);
		x++;
	}
}
/*
函数:DispDotOn()
功能:显示特定位的小数点
*/
void DispDotOn(unsigned char x)
{
	DispBuf[7-x] |= 0x80;
}
/*
函数:DispClear()
功能:清除显示
*/
void DispClear()
{
	unsigned char i;
	for(i=0;i<8;i++)
	{	DispBuf[i] = 0x00;
		s[i]='0';
	}

}
/*
函数:ByteToStr()
功能:字节型变量c转换为十进制字符串
*/
void ByteToStr(unsigned char idata *s, unsigned char c)
{
	code unsigned char Tab[] = {100,10};
	unsigned char i;
	unsigned char t;
	for ( i=0; i<2; i++ )
	{
		t = c / Tab[i];
		*s++ = '0' + t;
		c -= t * Tab[i];
	}
	*s++ = '0' + c;
	*s = '\0';
}
/*
函数:Delay()
功能:延时 t * 0.1 ms
*/
void Delay(unsigned int t)
{
	cnt_delay = t;
	while(cnt_delay);
}
//----------------------------
//********蜂鸣器部分**********
//----------------------------

//控制蜂鸣器发出相应频率的音调
void T0INTSVC() interrupt 1
{
	TR0 = 0;
	TH0 = ReloadH;
	TL0 = ReloadL;
	TR0 = 1;
	BUZZER = !BUZZER;
}
//播放一种频率的音调并点亮LED灯
void Sound(unsigned int Freq,unsigned char i)
{
//利用定时器T1发出音符的频率

	ReloadH = (unsigned char)(Freq >> 8);
	ReloadL = (unsigned char)Freq;
	TH0 = 0xFF;
	TL0 = 0xF0;
	TR0 = 1;
	P0 = ~(1<<(7-i));//控制相应位LED灯点亮
//播放音调时长
	Delay(3000);
//停止发声
	TR0 = 0;
	BUZZER = 1;
//停顿时长
	Delay(1000);
}
//----------------------------
//**********ADC部分***********
//----------------------------
/*
函数:ReadAdc()
功能:读取A/D转换结果
返回:8位ADC代码
*/
unsigned char ReadAdc()
{
	unsigned char d;
	unsigned char n;
	CS = 0;
	n = 5;
	while ( --n != 0 );
	n = 8;
	do
	{
		d <<= 1;
		if ( DAT ) d++;
		CLK = 1;
		CLK = 0;
	}while ( --n != 0 );
	CS = 1;
	return d;
}


/*
函数:AdcInit()
功能:初始化ADC接口
*/
void AdcInit()
{
	CS = 1;
	CLK = 0;
	DAT = 1;
	ReadAdc();
}

/*
函数:DispVol()
功能:将ADC值转换成电压值,并显示
参数:
	v:8位ADC结果
*/
void DispVol(unsigned char v)
{
	DispStr(0,VolTab[v]);
	DispDotOn(0);
}
//---------------------------------
//*********数字温度计部分**********
//---------------------------------
/*
函数:LM75A_GetTemp
功能:读出LM75A的温度值
返回:LM75A温度寄存器的数值(乘以0.125可得到摄氏度值)
*/
int LM75A_GetTemp()
{
	unsigned char buf[2];
	int t;
	I2C_Gets(0x90,0x00,2,buf);
	t = buf[0];
	t <<= 8;
	t += buf[1];
	t >>= 5;	//去掉无关位
	return t;
}

/*
函数:DispTemp()
功能:在数码管上显示出温度值
参数:
	t:补码,除以8以后才是真正温度值
*/
void DispTemp(int t)
{
	code unsigned char Tab[8][3] =
	{
		"00",
		"13",
		"25",
		"38",
		"50",
		"63",
		"75",
		"88"
	};
	unsigned char buf[4];
	bit p;	//符号位
	unsigned char i;	//整数部分
	unsigned char d;	//小数部分
	unsigned char x;	//临时变量
	unsigned char m;
//分离出符号
	p = 0;
	if ( t < 0 )
	{
		p = 1;
		t = -t;
	}
//分离出整数和小数部分
	i = t / 8;
	d = t % 8;
	m = i*10 + d;
	if(init_temp)
	{
		envir_temp = 10*i + d;//记录室温值
		init_temp--;
	}
	else
	{	//将温度值与室温值相比较,根据不同情况给标志赋值
		if(m-envir_temp>=10)
		{
			if(m-envir_temp<20)
			{	temp_flag = 1;}
			else if(m-envir_temp<30)
			{	temp_flag = 2;}
			else
			{	temp_flag = 3;}
		}
		else
		{	temp_flag = 0;}
	}

//整数部分转换成字符串
	ByteToStr(buf,i);
	x = 6 - strlen(buf);
//显示整数部分
	DispStr(x,buf);
//显示小数点
	DispDotOn(5);
//显示小数部分
	DispStr(6,Tab[d]);
}
//-----------------------------
/*
函数:SysInit()
功能:系统初始化
*/
void SysInit()
{
	DispClear();
	EA = 0;
	TMOD &= 0x00;
	TMOD |= 0x11;
	TH1 = 0xff;
	TL1 = 0x6a;
	TR1 = 1;
	ET1 = 1;
	EA = 1;
	I2C_Init();
	AdcInit();
}


//定时器T1中断函数
void T1INTSVC()interrupt 3
{
	code unsigned char com[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
	unsigned char i = 0;
	static unsigned char n = 0;
	static unsigned char cnt_flag=0;
	static unsigned char led_temp = 0;
	static bit LastValue2 = 1;
	static bit LastValue3 = 1;
	static bit piont2 = 1,piont3 = 1;
    bit KeyValue2 = 1,KeyValue3 = 1;
    unsigned int cnt_temp;
	bit cnt1000_flag = 0;

	TR1 = 0;
	TH1 = 0xff;
	TL1 = 0x6a;
	TR1 = 1;
//***********延时函数的实现****************
	if(cnt_delay>0)
	{	cnt_delay--;}
	else
	{	cnt_delay = 0;}
//-----------------------------------------
//***********按键扫描及任务切换************
	if(cnt_key>=1000)
	{	cnt_key = 0;
		key_flag = 1;
		cnt1000_flag = 1;
	}
	else
	{	cnt_key++;
		key_flag = 0;
	}

	if(key_flag)
	{
		KeyValue2 = KEY2;
		KeyValue3 = KEY3;
		if(LastValue2 != KeyValue2)
		{	LastValue2 = KeyValue2;}
        if(LastValue3 != KeyValue3)
		{	LastValue3 = KeyValue3;}
		KeyValue2 = LastValue2;
		KeyValue3 = LastValue3;
		if(KeyValue2==0&&piont2==1)
		{
		    task++;
			if(task == 6)
			{
				task = 1;
			//	SysInit();
			}
			piont2 = 0;
		}
		else if(KeyValue2 ==1)
		{	piont2 = 1;}
		if(KeyValue3==0&&piont3==1)
		{
		    if(task == 4)
            {
                task = 5;
            }
		    else if(task == 5)
            {
                task = 4;
            }
			piont3 = 0;
		}
		else if(KeyValue3 ==1)
		{	piont3 = 1;}
	}
//****************任务1*********************
	if(task == 1)
	{
	    P0 = 0xff;
		if(cnt1>=50000)
		{	cnt1 = 0;
			if(cnt_flag>=5)
			{	cnt_flag = 0;}
			else
			{	cnt_flag++;}
		}
		else
		{	cnt1++;}
		cnt_temp = cnt1/100;
		switch(cnt_flag)
		{
			case 0:
			case 1:
				s[0]='0';
				s[1]='0';
				s[2]=cnt_temp/100+49;
				DispChar(0,s[0],0);
				DispChar(1,s[1],0);
				DispChar(2,s[2],0);break;
			case 2:
			case 3:
				s[0]='0';
				s[1]=(500-cnt_temp)/100+48;
				s[2]=(500-cnt_temp)/10%10+48;
				DispChar(0,s[0],0);
				DispChar(1,s[1],1);
				DispChar(2,s[2],0);break;
			case 4:
			case 5:
				s[0]=cnt_temp/100+48;
				s[1]=cnt_temp/10%10+48;
				s[2]=cnt_temp%10+48;
				DispChar(0,s[0],1);
				DispChar(1,s[1],0);
				DispChar(2,s[2],0);break;
			default:
				break;
		 }
		for(i=3;i<8;i++)
		{	DispChar(i,0,0);}
	}
	else
	{
		cnt1 = 0;
		cnt_flag = 0;
	}
//----------------------------------------
//***************任务2********************
	if(task ==2)
	{
		s[3] = '-';
		s[4] = '4';
		s[7] = '8';
		if(cnt2_temp>=100)
		{
		 	cnt2_temp = 0;
			if(cnt2<=100)
			{
				cnt2 = 800;
			}
			else
			{	cnt2--;}
		}
		else
		{	cnt2_temp++;}
		s[0]=cnt2/100+48;
		s[1]=cnt2/10%10+48;
		s[2]=cnt2%10+48;

		DispChar(0,s[0],1);
		for(i=1;i<8;i++)
		{	DispChar(i,s[i],0);}
		P0 = ~(1<<(toint(s[0])-1)); //点亮相应位的LED
	}
	else
	{
		cnt2= 800;
		cnt2_temp = 0;
	}

//------------------------------------------
//***************任务4,5********************
	if(task == 4)
	{
		if(cnt1000_flag)
		{
			cnt1000_flag = 0;
			led_con = !led_con;
			cnt3++;
			if(cnt3>=50)
			{	cnt3 = 0;}
		}
        s[0] = '0';
        s[1] = '0';
		s[2] = cnt3/10+49;
		s[3] = '-';

		for(i=0;i<4;i++)
		{	DispChar(i,s[i],0);}
	}
	else
	{
        cnt3 = 0;
        temp_flag = 0;
	}
//-----------------------------------------
//*************任务6,7*******************
    if(task == 5)
    {
        led_temp++;
        if(led_temp>=PWM_MAX) led_temp=0;
        if(led_temp<PwmValue)
        {	P0 = 0x00;}
        else
        {	P0 = 0xff;}
    }
    else
    {
        led_temp = 0;
    }
//---------------------------------------
//*********数码管的动态显示**************
	if(task != 3 )
	{
		XBYTE[0x7800] = 0xff;
		XBYTE[0x7801] = ~DispBuf[n];
		XBYTE[0x7800] = ~com[n];
		n++;
		n &= 0x07;
	}
	else
	{	XBYTE[0x7800] = 0xff;}
}

void main()
{
	unsigned char i=0;
	SysInit();
	s[3] = '-';
	task = 1;
	while(1)
	{
//************播放音符***************
	    if(task == 3)
        {
            ET0 = 1;
            buz_led &= 0x07;
            for (buz_led;buz_led<8;buz_led++)
            {
				if(task != 3)
				{
					P0 = 0xff;
					break;
				}
				else
                {	Sound(MusicTab[buz_led],buz_led);}
            }
        }
        else
        {
            ET0 = 0;
            buz_led = 0;
			TR0 = 0;
			BUZZER = 1;
        }
//***********点亮温度的灯************
        if(task == 4)
        {
			temp = LM75A_GetTemp();
            DispTemp(temp);
            switch(temp_flag)
            {
                case 0:
                    P0 = 0xff;break;
                case 1:
                    P0 = 0x7f;break;
                case 2:
                    P0 = 0x3f;break;
                case 3:
                    if(led_con)
                    {	P0 = 0x00;}
                    else
                    {	P0 = 0xff;}
                default:
                    break;
            }
			Delay(10);
        }
//***********************************
        if(task == 5)
        {
			temp = LM75A_GetTemp();
            DispTemp(temp);
			PwmValue = ReadAdc();
            DispVol(PwmValue);
			DispChar(3,s[3],0);
			Delay(10);
        }
        else
        {
            CS = 1;
            CLK = 0;
            DAT = 1;
        }
//-----------------------------------
	}
}

void INT0_ISR() interrupt 0
{
    task++;
    if(task >= 6)
    {
        task = 1;
    }
}

This snippet took 0.03 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).