资讯详情

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

数字管和按钮绝对是必不可少的模块。

数字管,主要是消隐和小数点。

#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列也接在P当时我以为是板子又坏了。

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_SendBye(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测量一次。。

差不多就这些吧。。

标签: 温度传感器ne1617ds

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台