比赛之前的最后一点点总结

数码管和按键肯定是必不可少的模块了。

数码管的话,主要是消隐和小数点。

#include "sys.h"

uchar code nixie[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};

void DisplayBit(uchar pos,value,bit k)
{
	P0 = 0X00;
	Select_74HC138(6);
	Select_74HC138(0);
	
	if(k)                         //显示小数点
		P0 = nixie[value] & 0x7f;
	else                            //不显示小数点
		P0 = nixie[value];
	Select_74HC138(7);
	Select_74HC138(0);
	
	P0 = _crol_(0x01,pos);
	Select_74HC138(6);
	Select_74HC138(0);
	
	Delay(1);
}

有时侯要显示任意多位数码管(其实这个也不经常用)

//显示任意长度数字
uchar w[8];
void DisplaySMG(unsigned long num) 
{
	uchar pos,len;
	unsigned long temp = 1;
	for(len = 0; len < 8; len++)
	{
		w[len] = num / temp % 10;
		temp *= 10;
		if(num < temp)
			break;
	}
	len++;
	for(pos = 0; pos < len; pos++)
		DisplayBit(pos,w[len-1-pos],0);
}

其次就是按键了

独立按键就很好写了

sbit s4 = P3^3;
sbit s5 = P3^2;
sbit s6 = P3^1;
sbit s7 = P3^0;
uchar key_val = 20;
void KeyScans()
{
	if(s4 == 0)
	{
		Delay(10);
		key_val = 4;
		while(s4 == 0)
		{
			
		}
	}
	if(s5 == 0)
	{
		Delay(10);
		key_val = 5;
		while(s5 == 0)
		{
			
		}
	}
	if(s6 == 0)
	{
		Delay(10);
		key_val = 6;
		while(s6 == 0)
		{
			
		}
	}
	if(s7 == 0)
	{
		Delay(10);
		key_val = 7;
		while(s7 == 0)
		{
			
		}
	}
}

矩阵按键

sbit h1 = P3^2;
sbit h2 = P3^3;
sbit l1 = P4^4;
sbit l2 = P4^2;
void KeyScans()
{
	h1 = 0;
	l1 = l2 = h2 = 1;
	if(l1 == 0)
	{
		Delay(10);
		key_val = 5;
		while(l1 == 0)
		{
			
		}
	}
	if(l2 == 0)
	{
		Delay(10);
		key_val = 9;
		while(l2 == 0)
		{
			
		}
	}
	h2 = 0;
	h1 = l1 = l2 = 1;
	if(l1 == 0)
	{
		Delay(10);
		key_val = 4;
		while(l1 == 0)
		{
			
		}
	}
	if(l2 == 0)
	{
		Delay(10);
		key_val = 8;
		while(l2 == 0)
		{
			
		}
	}
}

如果矩阵按键全部要用到的话,用上面那种方法就看着有点点头晕了

sbit l1 = P4^4;
sbit l2 = P4^2;
sbit l3 = P3^5;
sbit l4 = P3^4;
void KeyScans()
{
	uchar hang;
	for(hang = 0; hang < 4; hang++)
	{
		P3 = _cror_(0xf7,hang) & 0xff;
		if(l1 == 0)
		{
			Delay(10);
			key_val = hang + 4*1;
			while(l1 == 0)
			{
				
			}
		}
		if(l2 == 0)
		{
			Delay(10);
			key_val = hang + 4*2;
			while(l2 == 0)
			{
				
			}
		}
		if(l3 == 0)
		{
			Delay(10);
			key_val = hang + 4*3;
			while(l3 == 0)
			{
				
			}
		}
		if(l4 == 0)
		{
			Delay(10);
			key_val = hang + 4*4;
			while(l4 == 0)
			{
				
			}
		}
	}
}

在我看来,最头疼的还是流水灯了,因为控制不好的话它会和数码管冲突

void OperateLed(uchar who,status)
{
	static uchar temp;
	uchar zt;
	switch(status)
	{
		case 0:
			temp = temp | _crol_(0x01,who-1);
			P0 = ~temp;
			break;
		case 1:
			if(who == 0xff)
			{
				P0 = 0xff;
				temp = 0;
			}
			else
			{
				zt = (~temp) | _crol_(0x01,who-1);
				if(temp != (~zt))
					temp = ~zt;
				P0 = zt;
			}
			
			break;
		case 2:
			P0 = ~who;
			temp = who;
			break;
		default: break;
	}
	Select_74HC138(4);
	Select_74HC138(0);
}

然后就是一些外设(蜂鸣器和继电器)

下面的这种写法,给个0x10就是让继电器吸合了,但是如果想让蜂鸣器响,给个0x50,这不就把继电器给关了嘛,所以可以先定义一个变量stat = 0x00;stat = 0x10; 再stat |= 0x50,就不会了

void Operatews(uchar num,status)
{
	static uchar t;
	if(status)
	{
		t = num;
		P0 = t;
	}
	else
	{
		t = t & (~num);
		P0 = t;
	}
	Select_74HC138(5);
	Select_74HC138(0);
}

然后复习的就是NE555频率测量的模块了,记得把跳线帽接在P34和SIGNAL上,不过有一次做题,忘了把跳线帽摘下来,就影响了我的矩阵按键了,因为矩阵按键第4列也接在P34上了,当时还以为是板子又坏了。。

uint count_freq;
uchar t1 = 0;
//定时器0用作做计数
void Timer0Init()
{
	AUXR |= 0X80;  //定时器时钟12T模式
	TMOD &= 0XF0;
	TMOD |= 0X04;   //设置计数模式
	TL0 = 0XFF;
	TH0 = 0XFF;
	TF0 = 0;      //TF0 = 1;表示溢出
	TR0 = 1;
	ET0 = 1;
	EA = 1;
}

//定时器1用作定时
void Timer1Init()
{
	AUXR &= 0XBF;
	TMOD &= 0X0F;
	TL1 = 0XB0;
	TH1 = 0X3C;
	TF1 = 0;
	TR1 = 1;
	ET1 = 1;
	EA = 1;
}

void ServiceTimer0() interrupt 1
{
	count_freq++;
}

void ServiceTimer1() interrupt 3
{
	t1++;
	if(t1 == 20)
	{
		t1 = 0;
		freq = count_freq;
		count_freq = 0;
	}
}

iic 应该是我最头疼的了,但是比赛要考的话,也就只有写数据,然后读数据了,应该没啥花样,除非上次看到一套真题智能门锁,我是真的看的就不想写了,等比完赛我再看看那套题。。

IIC读和写

void Write_AT24C02(uchar addr,dat)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

uchar Read_AT24C02(uchar addr)
{
	uchar dat;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	dat = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	return dat;
}

要读入几个数据的话就写完一个之后适当延时

Write_AT24C02(0x00,dat[0]);
Delay(10);
Write_AT24C02(0x01,dat[1]);

还有最近一个看了一位我们组学长的一次写几个数进去的代码,感觉......可以借鉴

void Write_N_AT24C02(uchar *buf,uchar addr,uchar len)
{
	while(len--)
	{
		do{
			IIC_Start();
			IIC_SendByte(0xa0);
			if(!IIC_WaitAck())
				break;
			IIC_Stop();
		}while(1);
		IIC_SendByte(addr++);
		IIC_WaitAck();
		IIC_SendByte(*buf++);
		IIC_WaitAck();
		IIC_Stop();
	}
}

然后就是PCF8591了,读数据和写数据都和AT24C02差不多,改下地址就好了

我一般都不怎么喜欢写带返回值的

uchar rb2;

void ReadAIN3()
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x03);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	rb2 = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
}

DS1302刚开始学的时候感觉它挺难的,当时一直追着老师问,但是总结了,就也不怎么难了

首先是BCD和十进制的相互转换,可能还有更简洁的方法写,但是,我已经习惯这样写了。。

uchar DAT_chg_BCD(uchar dat)
{
	uchar dat1,dat2;
	dat1 = dat / 10;
	dat2 = dat % 10;
	dat2 = dat1*16 + dat2;
	return dat2;
}

uchar BCD_chg_DAT(uchar dat)
{
	uchar dat1,dat2;
	dat1 = dat / 16;
	dat2 = dat % 16;
	dat2 = dat1*10 + dat2;
	return dat2;
}

一开始肯定要往里面写一个时间进去了

void Set_DS1302()
{
	uchar i;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i = 0; i < 7; i++)
		Write_Ds1302_Byte(WriteReg[i],Time[i]);
	Write_Ds1302_Byte(0x8e,0x80);
}

然后把时间读出来

void Get_DS1302()
{
	uchar i;
	for(i = 0; i < 7; i++)
		Time[i] = Read_Ds1302_Byte(ReadReg[i]);
}

当然还要定义一下时间和读写寄存器了

uchar WriteReg[7] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
uchar ReadReg[7] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
uchar Time[7] = {55,59,23,0,0,0,0};

然后这个模块就没其他的了。。。

温度传感器DS18B20

unsigned int temp;
void Temper_Get()
{
	unsigned char lsb,msb;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	lsb = Read_DS18B20();
	msb = Read_DS18B20();
	temp = (msb << 8) | lsb;
	if((temp & 0xf8000) == 0x0000)
		temp = temp >> 4;
	
}

一位小数

temp = (msb << 8) | lsb;
	temp = temp * 0.625 + 0.5;

两位小数

temp = (msb << 8) | lsb;
temp >>= 4;
temp *= 100;
temp = temp + (lsb&0x0f) * 6.25;
if((msb >> 4) == 0x0f)
	temp |= 0x8000;

嗯~再就是超声波了

说实话,一接触超声波还是挺害怕的,但是后来发现它和温度传感器也没有啥区别。如果真的不会用它的话,就当成温度传感器用就好了。

void Delay12us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 33;
	while (--i);
}

void Send_Sonic()
{
	uchar i = 8;
	while(i--)
	{
		TX = 1;
		Delay12us();
		TX = 0;
		Delay12us();
	}
}
uint distance;
void Mea_Distance()
{
	
	uint time = 0;
	Send_Sonic();
    AUXR &= 0XBF;
    TMOD &= 0X0F;
	TL1 = 0;
	TH1 = 0;
    TF1 = 0;
	TR1 = 1;
	while((RX == 1) && (TF1 == 0));//等待超声波信号返回(RX引脚变为低电平)或等超出测量范围
	TR1 = 0;
	if(TF1 == 0)  //正常范围内
	{
		time = (TH1 << 8) | TL1;
		distance = time * 0.0172;
	}
	else
	{
		TF1 = 0;
		distance = 999;
	}
}

uchar t0 = 0;
void Timer0Init()
{
	AUXR &= 0X7F;
	TMOD &= 0XF0;
	TL0 = 0XB0;
	TH0 = 0X3C;
	TF0 = 0;
	TR0 = 1;
	ET0 = 1;
	EA = 1;
}

void ServiceTimer0() interrupt 1
{
	t0++;
	if(t0 == 20)
	{
		t0 = 0;
		FLAG_WAVE = 1;
	}
}

当然也可以减小测量的时间,这里是1s测量一次。。

差不多就这些吧。。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wu小燕呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值