IC卡读写器设计单片机课程设计报告.docx
《IC卡读写器设计单片机课程设计报告.docx》由会员分享,可在线阅读,更多相关《IC卡读写器设计单片机课程设计报告.docx(38页珍藏版)》请在冰豆网上搜索。
IC卡读写器设计单片机课程设计报告
南京工程学院
课程设计
课程名称单片机原理及应用B
课题名称IC卡读写器设计
院(系、部、中心)通信工程学院
专业通信工程
班级
姓名
学号
起止日期
设计地点微机原理与单片机实验室
指导老师岳俊生水恒华
单片机原理及应用B
摘要
IC卡在现代生活中应用非常广泛,IC卡读写器的设计方法有多种,其中,利用单片机外接芯片实现的IC卡读写器具有编程灵活,便于IC卡读写器功能的扩充,运算存储方便等优点。
本文主要介绍用单片机外接24C16EEPROM的方法,利用键盘对24C16进行模拟充值的方法。
本设计由单片机P89V51RD2芯片、24C16EEPROM和LCD液晶显示为核心,辅以必要的电路,构成了一个IC卡读写器,使用起来很方便此IC卡读写器严格按照要求设计,最终达到预期的效果,并且添加了进行挂失,修改密码,低值报警,透支报警等相关功能。
关键词IC卡读写器/单片机/C51编程
ThePrincipleandApplication
ofSingleChipMicrocomputer
ABSTRACT
ICcardiswidelyusedinmodernlife。
ThereareavarietyofICcardreaderdesignmethods,whichuseanexternalchipmicrocontrollerICcardreaderwithprogrammingflexibility,easeofexpansionICcardreaderfunction,operationandeasystorage。
Thispaperdescribesamethod24C16EEPROMexternalMCU,usingthekeyboardtosimulate24C16rechargemethods.DesignedbytheMCUchipP89V51RD2,24C16EEPROMandLCDdisplayasthecore,supplementedbythenecessarycircuitry,constituteanICcardreader,easytouse。
ThisICcardreaderinstrictaccordancewiththerequirementsofthedesign,andultimatelyachievethedesiredeffect,andaddreporttheloss,changepasswords,lowalarm,alarmandotherrelatedfunctionsoverdraft.
KeywordsICcardreader/P89V51RD2single-chipcomputer/C51programming
八、参考文献……………………………………………………………………………………………………………………28
一、课程设计目的
本课程设计是在《单片机原理及应用B》课程主要内容学习之后,通过一个单片机应用系统的设计和调试,训练学生综合运用本课程知识,独立解决工程实际问题的能力;使学生加深对单片机结构、工作原理的理解,提高学生综合应用知识的能力、分析解决问题的能力和单片机应用系统的设计技能;同时培养学生查阅科技资料和撰写科技报告的能力。
二、基本思路
通过此次课程设计掌握I2C总线的基本特点和通信协议,掌握24xx系列EEPROM的基本特点及总线控制协议,掌握单片机IO端口模拟I2C时序控制程序的编写方法。
单片机通过P1.0和P1.1分别连接24C16的SDA和SCL,编写单片机通过IO端口模拟I2C时序控制24C16读写的程序。
通过键盘对24C16EEPROM进行模拟充值,通过LED/LCD实时显示卡内实际金额。
三、实验方案
在进行头文件配置完之后,建立一个while
(1),死循环,在这个死循环中不断检测键盘输入,检测到键盘输入后,根据键盘的值,执行相应的子函数。
并通过1602LCD显示出来相应的过程。
四、实验开发环境及元器件
1、开发工具及开发环境简介
1.1单片机
单片微型计算机简称单片机,是典型的嵌入式微控制器(MicrocontrollerUnit),常用英文字母的缩写MCU表示单片机,它最早是被用在工业控制领域。
单片机由芯片内仅有CPU的专用处理器发展而来。
最早的设计理念是通过将大量外围设备和CPU集成在一个芯片中,使计算机系统更小,更容易集成进复杂的而对体积要求严格的控制设备当中。
INTEL的Z80是最早按照这种思想设计出的处理器,从此以后,单片机和专用处理器的发展便分道扬镳。
1.2Proteus
Proteus软件是LabcenterElectronics公司的一款电路设计与仿真软件,它包括ISIS、ARES等软件模块,ARES模块主要用来完成PCB的设计,而ISIS模块用来完成电路原理图的布图与仿真。
Proteus的软件仿真基于VSM技术,它与其他软件最大的不同也是最大的优势就在于它能仿真大量的单片机芯片,比如MCS-51系列、PIC系列等等,以及单片机外围电路,比如键盘、LED、LCD等等。
通过Proteus软件的使用我们能够轻易地获得一个功能齐全、实用方便的单片机实验室。
1.3KEIL
单片机开发中除必要的硬件外,同样离不开软件,我们写的汇编语言源程序要变为CPU可以执行的机器码有两种方法,一种是手工汇编,另一种是机器汇编,目前已极少使用手工汇编的方法了。
机器汇编是通过汇编软件将源程序变为机器码,用于MCS-51单片机的汇编软件有早期的A51,随着单片机开发技术的不断发展,从普遍使用汇编语言到逐渐使用高级语言开发,单片机的开发软件也在不断发展,Keil软件是目前最流行开发MCS-51系列单片机的软件,这从近年来各仿真机厂商纷纷宣布全面支持Keil即可看出。
Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(uVision)将这些部分组合在一起。
运行Keil软件需要Pentium或以上的CPU,16MB或更多RAM、20M以上空闲的硬盘空间、WIN98、NT、WIN2000、WINXP等操作系统。
掌握这一软件的使用对于使用51系列单片机的爱好者来说是十分必要的,如果你使用C语言编程,那么Keil几乎就是你的不二之选(目前在国内你只能买到该软件、而你买的仿真机也很可能只支持该软件),即使不使用C语言而仅用汇编语言编程,其方便易用的集成环境、强大的软件仿真调试工具也会令你事半功倍。
KeilC51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。
在开发大型软件时更能体现高级语言的优势
2、P89V51RD2
P89V51RD2是Philips公司生产的一款80C51微控制器,包含64KBFlash和1024字节的数据RAM。
P89V51RD2的典型特性是它的X2方式选项。
利用该特性,设计者可使应用程序以传统的80C51时钟频率(每个机器周期包含12个时钟)或X2方式(每个机器周期包含6个时钟)的时钟频率运行,选择X2方式可在相同时钟频率下获得2倍的吞吐量。
从该特性获益的另一种方法是将时钟频率减半来保持特性不变,这样可以极大地降低EMI。
Flash程序存储器支持并行和串行在系统编程(ISP),ISP允许在软件控制下对成品中的器件进行重复编程。
应用固件的产生/更新能力实现了ISP的大范围应用。
5V的工作电压,操作频率为0~40MHz。
3、24C16EEPROM
EEPROM(带电可擦写可编程只读存储器)是用户可更改的只读存储器(ROM),其可通过高于普通电压的作用来擦除和重编程(重写)。
不像EPROM芯片,EEPROM不需从计算机中取出即可修改。
在一个EEPROM中,当计算机在使用的时候可频繁地反复编程,因此EEPROM的寿命是一个很重要的设计考虑参数。
EEPROM是一种特殊形式的闪存,其应用通常是个人电脑中的电压来擦写和重编程。
4.、LCD1602
(1)简介
1602液晶也叫1602字符型液晶它是一种专门用来显示字母、数字、符号等的点阵型液晶模块它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。
每位之间有一个点距的间隔每行之间也有间隔起到了字符间距和行间距的作用,正因为如此所以他不能显示图形。
1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
(2)管脚功能
1602采用标准的16脚接口,其中:
第1脚:
VSS为电源地
第2脚:
VDD接5V电源正极
第3脚:
V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:
RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:
RW为读写信号线,高电平
(1)时进行读操作,低电平(0)时进行写操作。
第6脚:
E(或EN)端为使能(enable)端。
第7~14脚:
D0~D7为8位双向数据端。
第15~16脚:
空脚或背灯电源。
15脚背光正极,16脚背光负极。
(3)16进制ASCII码表
字符集
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:
阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
在单片机编程中还可以用字符型常量或变量赋值,如'A’。
因为CGROM储存的字符代码与我们PC中的字符代码是基本一致的,因此我们在向DDRAM写C51字符代码程序时甚至可以直接用P1=‘A’这样的方法。
PC在编译时就把'A'先转换为41H代码了。
(4)特性
3.3V或5V工作电压,对比度可调
内含复位电路
提供各种控制命令,如:
清屏、字符闪烁、光标闪烁、显示移位等多种功能
有80字节显示数据存储器DDRAM
内建有192个5X7点阵的字型的字符发生器CGROM
8个可由用户自定义的5X7的字符发生器CGRAM
五、系统分析与设计
1、系统框图
2、软件设计
(1)软件程序内容
本设计的软件程序包括主程序、充值子程序、消费子程序、挂失子程序、
修改密码程序和报警子程序等等。
另外,还设计了LCD显示子程序。
(2)软件设计流程图
主程序框图
充值子程序
消费子程序
挂失子程序
解锁子程序
修改密码子程序
(3)程设计步骤
进行头文件配置,设置相应的端口名
采用死循环,通过查询方式检测是否有键按下
根据键盘的值执行相应的子程序
在执行过程中控制LCD显示相应的内容
在子程序执行完后返回主程序
在子程序中进行相应的数值运算
挂失和修改密码的子程序将改变存储在存储器中的密码值,使之从主程序中跳出来,待重新启用成功购在回到主循环中
(4)电路连线图
六、具体程序设计及步骤
1、头文件:
at24co2.h
#ifndef__AT24C02__
#define__AT24C02__
#include"main.h"
#include
sbitSCL=P1^7;
sbitSDA=P1^6;
sbitbuz=P3^7;
voidstart_at24c02();
voidstop_at24c02();
bitwait_at24c02_ack();
voidat24c02_ack(bitck);
voidwrite_at24c02_byte(uchardat);
ucharread_at24c02_byte();
bitread_at24c02(ucharadd,uchar*buf);
bitwrite_at24c02(ucharadd,uchardat);
bitread_at24c02_buf(ucharadd,uchar*buf,ucharlength);
bitwrite_at24c02_buf(ucharadd,uchar*buf,ucharlength);
#endif
Key.h
#ifndef__KEY__
#define__KEY__
#include"main.h"
#include
#defineCANCEL15
#defineENTER14
#defineADD13
#defineSUB12
#defineLOSS11
#defineDEL10
bitkeytest(void);
uchargetkeynum(void);
#endif
Lcd1602.h
#ifndef__LCD1602__
#define__LCD1602__
#include"main.h"
#defineLINE10x80
#defineLINE20xC0
sbitRW=P1^1;
sbitRS=P1^0;
sbitBUSY=P0^7;
sbitEN=P1^2;
sbitLCMBLC=P1^3;
voidwait_lcd1602();
voidwrite_lcd1602_cmd(ucharcmd);
voidwrite_lcd1602_dat(uchardat);
voidinit_lcd1602();
voidwrite_string(ucharadd,uchar*buf);
#endif
main.h
#ifndef__MAIN__
#define__MAIN__
#defineucharunsignedchar
#defineuintunsignedint
#defineSECRET_ADD0x03
#defineLOW_ADD0x00
#defineHIGH_ADD0x01
voiddelay(uintdtime);
#endif
proce.h
#ifndef__PROCE__
#define__PROCE__
#include
#include"at24c02.h"
#include"lcd1602.h"
#include"key.h"
#include"serve.h"
voiddisplay_sum(void);
voidsub_pro(void);
voidadd_pro(void);
bitlose_pro(void);
bitchange_pro(void);
#endif
Serve.h
#ifndef__SERVE__
#define__SERVE__
//sbitbuz=P3^7;
bitadd(void);
bitsub(void);
bitlose(void);
bitunlose(void);
bitchange_first(void);
bitchange_second(void);
#endif
2、各个.C文件:
at24c02.c
#include
#include"at24c02.h"
#include
voiddelay(uintdt)
{while(dt--);}
voidstart_at24c02()
{SCL=0;_nop_();
SDA=1;_nop_();
SCL=1;_nop_();
SDA=0;_nop_();
}
voidstop_at24c02()
{SCL=0;_nop_();
SDA=0;_nop_();
SCL=1;_nop_();
SDA=1;_nop_();
}
voidat24c02_ack(bitck)
{
if(ck)
SDA=0;//发送ack
else
SDA=1;//不发送ack
SCL=1;
delay(100);
SCL=0;
delay(100);
SDA=1;
delay(100);
}
bitwait_at24c02_ack()
{
SDA=1;
delay(100);
SCL=1;
delay(100);
if(SDA)
{
SCL=0;
stop_at24c02();
return1;//没收到ack
}
else
{
SCL=0;
return0;//收到ack
}}
voidwrite_at24c02_byte(uchardat)
{
uchari;
SCL=0;
for(i=0;i<8;i++)
{
if(0x80&dat)
SDA=1;
else
SDA=0;
dat<<=1;
SCL=1;
SCL=0;
}
}
ucharread_at24c02_byte()
{
uchartemp,i;
SCL=0;
for(i=0;i<8;i++)
{
temp<<=1;
if(SDA)
temp=temp|0x01;
SCL=1;
SCL=0;
}
returntemp;
}
bitread_at24c02(ucharadd,uchar*buf)
{
start_at24c02();
write_at24c02_byte(0xA0);
if(wait_at24c02_ack())
return1;
write_at24c02_byte(add);
if(wait_at24c02_ack())
return1;
start_at24c02();
write_at24c02_byte(0xA1);
if(wait_at24c02_ack())
return1;
*buf=read_at24c02_byte();
at24c02_ack(0);
stop_at24c02();
delay(1000);
return0;
}
bitwrite_at24c02(ucharadd,uchardat)
{
start_at24c02();
write_at24c02_byte(0xA0);
if(wait_at24c02_ack())
return1;
write_at24c02_byte(add);
if(wait_at24c02_ack())
return1;
write_at24c02_byte(dat);
if(wait_at24c02_ack())
return1;
stop_at24c02();
delay(1000);
return0;
}
return0;
}
Key.c
#include
#include"key.h”
ucharkey_tab[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d,0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};
bitkeytest(void)
{uchartemp=0;
P2=0x0f;
temp=P2&0x0f;
if(temp!
=0x0f)
{
P2=0x0f;
temp=P2&0x0f;
if(temp!
=0x0f)
return1;}
return0;
}
uchargetkeynum(void)
{
ucharj=0x01;
uchari,temp=0;
i=16;
delay(2000);
if(keytest())
{for(i=0;i<4;i++)
{
P2=~j;
temp=P2&0xf0;
if(temp==0xf0)
j=j<<1;
else
break;
}
while((P2&0xf0)!
=0xf0);
temp=temp|((~j)&0x0f);
for(i=0;i<16;i++)
{if(temp==key_tab[i])
break;
}
}
returni;}
lcd1602.c
#include
#include"lcd1602.h"
voidwait_lcd1602()
{do
{RS=0;
RW=1;
EN=1;
}while(BUSY==1);
EN=0;
}
voidlcd1602_clear()
{wait_lcd1602();
EN=0;
RS=0;
RW=0;
P0=0x01;
EN=1;
delay
(1);
EN=0;
}
voidwrite_lcd1602_cmd(ucharcmd)
{wait_lcd1602();
EN=0;
RS=0;
RW=0;
P0=cmd;
EN=1;
delay(100);
EN=0;
}
voidwrite_string(ucharadd,uchar*buf)
{
write_lcd1602_cmd(add);
while(*buf!
='\0')
{write_lcd1602_dat(*buf);
buf++;
}
}
voidinit_lcd1602()
{
write_lcd1602_cmd(0x38);
write_lcd1602_cmd(0x38);
write_lcd1602_cmd(0x38);
write_lcd1602_cmd(0x0C);
write_lcd1602_cmd(0x06);
write_lcd1602_cmd(0x01);
LCMBLC=0;
}
main.c
#include
#include
#include
#include"at24c02.h"
#include"lcd1602.h"
#include"key.h"