单片机模拟短信接收装置

产生:
单片机能不能做出一些高级有好van的东西呢?答案当然是可以,这次用单片机模拟的短信接收装置个人感觉比较不错,所以就拿出来分享了。
简介:
使用的板子是"STC89C52",用到的核心模块是LCD1602和AT24C02模块,短信的输入和发送用到串口通信,矩阵键盘用来决定短信存储的位置和一系列对短信的操作。
具体功能:
使用串口发送字符串模拟短信内容的发送,之后通过LCD1602进行短信内容的显示模拟短信的接收,通过AT24C02实现短信的储存,删除,读取条数等功能。每条短信上限为32个字节,最多储存8条短信(AT24C02储存地址有限)。收到的短信可以储存在任意已初始化后的地址,可以对短信进行储存,对任意储存短信进行删除和读取,随时可以得到已经储存短信的条数。
按键示意图:
0——1——2——3
4——5——6——7
IM——IM——IM——IM
IM——IM——W——R
SH——S——G——D
(IM=空闲键,W=储存短信条数键,R=显示短信条数键,SH=显示短信内容键,S=储存短信内容键,G=读取短信内容键,D=删除短信内容键)
按键操作时序:
烧录完成后:
串口发送->0-7按键任意按下一个->按下S键->按下G键->按下SH键
(操作完一次后可看到LCD1602上显示出短信内容,可以重复操作,但每次0-7按键值需要不一样,表示不同的地址储存不同的短信)
如果要删除短信,在进行至少一次上述操作后,先按下0-7中的一个键,再按下D键,就完成了删除。在全部操作完成后,先按下W键,再按下R键即可显示出储存的短信条数(不包含已经被删除的短信)
掉电复位后:
如果要读取短信,先按下0-7中的任意一个,接着按G键,然后按SH键即可(如果没有内容表示短信已被删除或者根本没有向该地址内写入短信)如果要查看已经储存的条数,直接按R键就好了。如果要再次保存或者删除短信,按照烧录完成后的操作进行就好了
源代码:

//模拟短信接收系统
//通过串口发送短信内容,然后通过LCD1602显示
//可以保存,删除,显示任意一条短信(上限为8条,每条32字节)
//对短信内容有掉电保护功能
//可以显示目前已储存的短信条数
//按键分布:
//0  1  2  3
//4  5  6  7
//IM IM IM IM
//IM IM W  R
//SH S  G  D
//IM=空闲键,W=保存当前条数键,R=显示短信条数键,SH=显示短信内容键
//S=短信储存键,G=短信读取键,D为短信删除键	
#include <reg52.h>
#include <intrins.h>

typedef unsigned char uchar;
typedef unsigned int uint;

sbit SDA=P2^0;
sbit SCL=P2^1;
sbit Beep=P2^3;
sbit RS=P3^5;
sbit RW=P3^6;
sbit EN=P3^4;

uchar i=0;//串口接收字符串变量
uchar x=0;//字符串数组长度
uchar a=0;//短信储存地址变量
uchar num=0;//短信条数
uchar tabel1[32];//用于接收串口传输过来的字符串
uchar tabel2[32];//用于储存从AT24C02中读取出来的字符串
uchar tabel3[8]={0x00,0x20,0x40,0x60,0x80,0xa0,0xc0,0xe0};//用于储存字符串储存的地址
uchar tabel4[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
					0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};//LCD1602显示地址
/********串口通信********/
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 LCDWrite()
{
	x=0;
	Write_cmd(0x01);
	while(x<16)
	{
		Write_cmd(tabel4[x]|0x80);
		Write_dat(tabel2[x]);
		x++;
	}
	while((x>=16)&&(x<32))
	{
		Write_cmd((tabel4[x-16]+0x40)|0x80);
		Write_dat(tabel2[x]);
		x++;
	}		
}

void LCDNum()
{
	Write_cmd(0x01);
	Write_cmd(0x00|0x80);
	Write_dat((num+'0'));
}
/********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()
{
	LCDWrite();
}

void Save_information(uchar a)
{
	x=0;
	while(x<32)
	{
		WriteAT24C02(tabel3[a]+x,tabel1[x]);
		tabel1[x]=0x20;
		x++;
	}
	num++;
	i=0;
}

void Get_information(uchar a)
{
	x=0;
	while(x<32)
	{
		tabel2[x]=ReadAT24C02(tabel3[a]+x);
		x++;
	}
}	

void Delete_information(uchar a)
{
	x=0;
	while(x<32)
	{
		WriteAT24C02(tabel3[a]+x,0X20);
		x++;
	}
	num--;
}					
/********独立键盘********/
void delay(uint z)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=114;y>0;y--);
}

void keyscan()
{
	P3=0XFF;
	if(P3==0XFE)//显示键
	{
		delay(20);
		if(P3==0XFE)
		{
			Show_information();
			Beep=0;
			while(P3==0XFE);
		}
		Beep=1;
	}
	P3=0XFF;
	if(P3==0XFD)//储存键
	{
		delay(20);
		if(P3==0XFD)
		{
			Save_information(a);
			Beep=0;
			while(P3==0XFD);
		}
		Beep=1;			
	}
	P3=0XFF;
	if(P3==0XFB)//读取键
	{
		delay(20);
		if(P3==0XFB)
		{
			Get_information(a);
			Beep=0;
			while(P3==0XFB);
		}
		Beep=1;
	}
	P3=0XFF;
	if(P3==0XF7)//删除键
	{
		delay(20);
		if(P3==0XF7)
		{
			Delete_information(a);
			Beep=0;
			while(P3==0XF7);
		}
		Beep=1;
	}
}
/********矩阵键盘********/
void keyscan1()
{
	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:a=0;Beep=0;break;
				case 0xde:a=1;Beep=0;break;
				case 0xbe:a=2;Beep=0;break;
				case 0x7e:a=3;Beep=0;break;
			}
			while(temp!=0xf0)
			{
				temp=P3&0XF0;
			}
			Beep=1;
		}
	}
	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:a=4;Beep=0;break;
				case 0xdd:a=5;Beep=0;break;
				case 0xbd:a=6;Beep=0;break;
				case 0x7d:a=7;Beep=0;break;
			}
			while(temp!=0xf0)
			{
				temp=P3&0XF0;
			}
			Beep=1;
		}
	}
	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:break;
				case 0xdb:break;
				case 0xbb:break;
				case 0x7b:break;
			}
			while(temp!=0xf0)
			{
				temp=P3&0XF0;
			}
			Beep=1;
		}
	}
	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:break;
				case 0xd7:break;
				case 0xb7:Beep=0;WriteAT24C02(0xa0,num);break;
				case 0x77:Beep=0;num=ReadAT24C02(0Xa0);LCDNum();break;
			}
			while(temp!=0xf0)
			{
				temp=P3&0XF0;
			}
			Beep=1;
		}
	}
	P3=0XFF;
}
/********main函数********/
void main()
{
	uchar i;
	UARTInit();
	Init();
	LCD1602Init();
	for(i=0;i<32;i++)
	{
		tabel1[i]=0x20;
		tabel2[i]=0x20;
	}
	while(1)
	{
		keyscan();
		keyscan1();
	}
}

P.S.
1、烧录前将keil中晶振调为11.0592MHZ,Model选DATA,本人调试过后这样显示是比较稳定的。
2、由于本人水平有限,代码可能会有一些冗余,欢迎各位大神提出意见,看到后我会尽力精简的~
3、看到这里的小可爱别忘了点个赞支持一下哈~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值