单片机模拟手机通讯录(含搜索联系人功能)

具体功能概括
在前边模拟过短信接收装置的基础上,添加上了搜索功能,可以通过联系人的姓的大写首字母来进行联系人电话号码的搜索。
按键类似于老式手机的按键:
7(A B C) 8(D E F) 9(G H I) 储存键
4(J K L) 5(M N O)6(P Q R)读取和显示键
1(S T U) 2(V W X) 3(Y Z) 删除键
上翻键 0 下翻键 空闲键
(括号表示按下不同的次数对应不同的数字和字母)
按键的时序是,通过串口发送过数据后,按下数字键选择储存地址,然后按储存键表示储存完成。想要删除某个信息,先确定地址,然后按下删除键即可。当储存完成后,(比如存了XXM123456789,XXM表示名字首字母大写,后边的是电话号码),通过按键选出对应的首字母“X”(可在LCD1602的右下角看到此时显示的是那个字母或数字),然后按下读取和显示键,屏幕上会显示出对应的信息。如果首字母相同的有多个人,多次按下读取键会循环显示符合要求的全部联系人信息。(代码中默认的是X,W,C开头的六个联系人,X有两个,W有三个,C有一个,可以自行修改或增添)。上翻键和下翻键可以查看联系人列表,包括已储存和未储存的(未储存的会显示空白)
源代码

#include <reg52.h>
#include <intrins.h>

typedef unsigned char uchar;
typedef unsigned int uint;

sbit SDA=P2^0;
sbit SCL=P2^1;//IIC通讯位定义
sbit RS=P3^5;
sbit RW=P3^6;
sbit EN=P3^4;//LCD1602显示位定义

uchar i=0;//串口接收字符串变量
uchar x=0;//字符串数组长度
uchar a=0;//短信储存地址变量
uchar tabel1[16];//用于接收串口传输过来的字符串
uchar tabel2[16];//用于储存从AT24C02中读取出来的字符串
uchar tabel3[10]={0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90};//用于储存字符串储存的地址
uchar tabel4[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};//LCD1602显示地址
uchar b,c,d,e,f,g,h,j,k,y,z1,z2,z3;
uchar z;
/********串口通信********/
void UARTInit()//串口的初始化
{
	TMOD|=0X20;
	TH1=0XFD;
	TL1=0XFD;
	TR1=1;
	SM0=0;
	SM1=1;
	REN=1;
	EA=1;
	ES=1;
}

void UART() interrupt 4
{
	uchar temp;
	if(RI)
	{
		temp=SBUF;
		RI=0;
		if(temp!='\0')
		{	
			tabel1[i]=temp;
			i++;
		}
	}
}
/********LCD1602********/
void Read_Busy()
{
	uchar busy;
	P0=0XFF;
	RS=0;
	RW=1;
	do
	{
		EN=1;
		busy=P0;
		EN=0;
	}while(busy&0x80);
}

void Write_cmd(uchar cmd)
{
	Read_Busy();
	RS=0;
	RW=0;
	P0=cmd;
	EN=1;
	EN=0;
	RS=1;
	RW=1;
	EN=1;
}

void Write_dat(uchar dat)
{
	Read_Busy();
	RS=1;
	RW=0;
	P0=dat;
	EN=1;
	EN=0;
	RS=1;
	RW=1;
	EN=1;
}

void LCD1602Init()										   
{
	Write_cmd(0x38);
	Write_cmd(0x0c);
	Write_cmd(0x01);
}

void LCDWrite1()
{
	Write_cmd(0x4f|0x80);
	Write_dat(y);//在右下角显示按键代表的字母
}	

void LCDWrite()//LCD1602第一行写数据
{
	x=0;
	Write_cmd(0x01);
	while(x<16)
	{
		Write_cmd(tabel4[x]|0x80);
		Write_dat(tabel2[x]);
		x++;
	}		
}
/********IIC********/
void delay_10us()
{
	_nop_();
	_nop_();
}

void delay_write(uint a)
{	
	uint b;
  	for(b=0;b<a;b++);
}

void Init()  
{
	SCL=1;
	delay_10us();
	SDA=1;
	delay_10us();
}

void Start()
{
	SDA=1;
	delay_10us();
	SCL=1;
	delay_10us();
	SDA=0;
	delay_10us();
	SCL=0;
	delay_10us();
}

void Stop()
{
	SDA=0;
	delay_10us();
	SCL=1;
	delay_10us();
	SDA=1;
	delay_10us();
}

void Writebyte(uchar a)  
{
	uchar b,temp;
   	temp=a;
   	for (b=0;b<8;b++)
   {
	   temp=temp<<1;
	   SCL=0;
	   delay_10us();
	   SDA=CY;	
	   delay_10us();
	   SCL=1;		
	   delay_10us();
   }
   SCL=0;
   delay_10us();
   SDA=1;
   delay_10us();
}

uchar Readbyte()
{
   uchar i,j,k=0;
   SCL=0;
   delay_10us(); 
   SDA=1;
   for (i=0;i<8;i++)
   {  
		delay_10us(); 
		SCL=1; 
		delay_10us();
      	if(SDA==1) 
		j=1;
      	else
		j=0;
      	k=(k<<1)|j;
	  	SCL=0;
	}
   	delay_10us();
	return k;
}

void ACK()
{
   uchar i=0;
   SCL=1;
   delay_10us();
   while((SDA==1)&&(i<255))
   	  i++;
   SCL=0;
   delay_10us();
}

uchar ReadAT24C02(uchar ADDR)
{
   uchar i;
   Start();
   Writebyte(0xa0);
   ACK();
   Writebyte(ADDR);
   ACK();
   Start();
   Writebyte(0xa1);
   ACK();
   i=Readbyte();
   Stop();
   delay_write(100);
   return i;
}

void WriteAT24C02(uchar ADDR,uchar DATA)
{
   Start();
   Writebyte(0xa0);
   ACK();
   Writebyte(ADDR);
   ACK();
   Writebyte(DATA);
   ACK();
   Stop();
   delay_write(500);
}
/********数据处理********/
void Show_information()//显示AT24C02中读取出来的信息
{
	LCDWrite();
}

void Save_information(uchar a)//将数据保存到LCD1602之中
{
	x=0;
	while(x<16)
	{
		WriteAT24C02(tabel3[a]+x,tabel1[x]);
		tabel1[x]=0x20;//顺便将储存用的数组清空
		x++;
	}
}

void Get_information(uchar a)//从储存的地址中读出数据
{
	x=0;
	Write_cmd(0x01);
	while(x<16)
	{
		tabel2[x]=ReadAT24C02(tabel3[a]+x);
		x++;
	}
}	

void Delete_information(uchar a)//删除储存的数据
{
	x=0;
	while(x<16)
	{
		WriteAT24C02(tabel3[a]+x,0X20);
		x++;
	}
}					
/********矩阵键盘********/
void delay(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=114;y>0;y--);
}

void keyscan()
{
	uchar temp;
	P3=0XFF;
	P3=0XFE;
	temp=P3&0XF0;
	if(temp!=0xf0)
	{
		delay(20);
		P3=0XFE;
		temp=0xf0&P3;
		if(temp!=0xf0)
		{
			temp=P3;
			switch(temp)
			{
				case 0xee:b++;break;
				case 0xde:c++;break;
				case 0xbe:d++;break;
				case 0x7e:Save_information(a);break;//储存键
			}
			while(temp!=0xf0)
			{
				temp=P3&0XF0;
			}
			switch(b)
			{
				case 1:a=7;y=7+'0';break;
				case 2:y='A';break;
				case 3:y='B';break;
				case 4:y='C';b=0;break;
			}
			switch(c)
			{
				case 1:a=8;y=8+'0';break;
				case 2:y='D';break;
				case 3:y='E';break;
				case 4:y='F';c=0;break;
			}
			switch(d)
			{
				case 1:a=9;y=9+'0';break;
				case 2:y='G';break;
				case 3:y='H';break;
				case 4:y='I';d=0;break;
			}
			LCDWrite1();
		}
	}
	P3=0XFF;
	P3=0XFd;
	temp=P3&0XF0;
	if(temp!=0xf0)
	{
		delay(20);
		P3=0XFd;
		temp=0xf0&P3;
		if(temp!=0xf0)
		{
			temp=P3;
			switch(temp)
			{
				case 0xed:e++;break;
				case 0xdd:f++;break;
				case 0xbd:g++;break;
				case 0x7d:z1++;z2++;z3++;break;//读取和展示键
			}			  
			while(temp!=0xf0)
			{
				temp=P3&0XF0;
			}
			switch(e)
			{
				case 1:a=4;y=4+'0';break;
				case 2:y='J';break;
				case 3:y='K';break;
				case 4:y='L';e=0;break;
			}
			switch(f)
			{
				case 1:a=5;y=5+'0';break;
				case 2:y='M';break;
				case 3:y='N';break;
				case 4:y='O';f=0;break;
			}
			switch(g)
			{
				case 1:a=6;y=6+'0';break;
				case 2:y='P';break;
				case 3:y='Q';break;
				case 4:y='R';g=0;break;
			}
			if(y=='X')
			{
				switch(z1)
				{
					case 1:Get_information(0);z2=0;z3=0;delay(3);Show_information();break;
					case 2:Get_information(1);z1=0;z2=0;z3=0;delay(3);Show_information();break;
				}
			}
			if(y=='W')
			{
				switch(z2)
				{
					case 1:Get_information(2);z1=0;z3=0;delay(3);Show_information();break;
					case 2:Get_information(3);z1=0;z3=0;delay(3);Show_information();break;
					case 3:Get_information(4);z2=0;z1=0;z3=0;delay(3);Show_information();break;
				}
			}
			if(y=='C')
			{
				switch(z3)
				{
					case 1:Get_information(5);z3=0;z1=0;z2=0;delay(3);Show_information();break;
				}
			}
			LCDWrite1();
		}
	}
	P3=0XFF;
	P3=0XFb;
	temp=P3&0XF0;
	if(temp!=0xf0)
	{
		delay(20);
		P3=0XFb;
		temp=0xf0&P3;
		if(temp!=0xf0)
		{
			temp=P3;
			switch(temp)
			{
				case 0xeb:h++;break;
				case 0xdb:j++;break;
				case 0xbb:k++;break;
				case 0x7b:Delete_information(a);break;//删除键
			}
			while(temp!=0xf0)
			{
				temp=P3&0XF0;
			}
			switch(h)
			{
				case 1:a=1;y=1+'0';break;
				case 2:y='S';break;
				case 3:y='T';break;
				case 4:y='U';h=0;break;
			}
			switch(j)
			{
				case 1:a=2;y=2+'0';break;
				case 2:y='V';break;
				case 3:y='W';break;
				case 4:y='X';j=0;break;
			}
			switch(k)
			{
				case 1:a=3;y=3+'0';break;
				case 2:y='Y';break;
				case 3:y='Z';k=0;break;
			}
			LCDWrite1();
		}
	}
	P3=0XFF;
	P3=0XF7;
	temp=P3&0XF0;
	if(temp!=0xf0)
	{
		delay(20);
		P3=0XF7;
		temp=0xf0&P3;
		if(temp!=0xf0)
		{
			temp=P3;
			switch(temp)
			{
				case 0xe7:z++;if(z==11) z=0;break;//上翻查看储存的信息
				case 0xd7:a=0;y=(0+'0');break;
				case 0xb7:z--;if(z==0) z=11;break;//下翻查看储存的信息
				case 0x77:break;
			}
			while(temp!=0xf0)
			{
				temp=P3&0XF0;
			}
			switch(z)
			{
				case 1:Get_information(0);delay(5);Show_information();break;
				case 2:Get_information(1);delay(5);Show_information();break;
				case 3:Get_information(2);delay(5);Show_information();break;
				case 4:Get_information(3);delay(5);Show_information();break;
				case 5:Get_information(4);delay(5);Show_information();break;
				case 6:Get_information(5);delay(5);Show_information();break;
				case 7:Get_information(6);delay(5);Show_information();break;
				case 8:Get_information(7);delay(5);Show_information();break;
				case 9:Get_information(8);delay(5);Show_information();break;
				case 10:Get_information(9);delay(5);Show_information();break;
			}
		}
	}
	P3=0XFF;
}

/********main函数********/
void main()
{
	uchar i;
	UARTInit();
	Init();
	LCD1602Init();//一系列的初始化函数
	for(i=0;i<16;i++)
	{
		tabel1[i]=0x20;
		tabel2[i]=0x20;
	}//手动清空AT24C02里的数据
	while(1)
	{
		keyscan();
	}
}

写在后边
实现拨打电话功能将在后边完善,代码可能会有冗余,个位大神可以进行优化。
感觉博主写的不错的小伙伴,别忘了点个赞哈~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值