摘 要
本文基于 8051 单片机嵌入式系统的简易超市收银机的设计,系统实现了矩
阵键盘输入,大容量EEPROM 存储,1302 实时时钟,1602 液晶显示等功能,并且
设置了掉电保护措施,完成了题目的基本要求。
本设计采用 ATS52 单片机作为主控芯片,完成了简易收银机的各项功能要
求。实现了从矩阵键盘读入商品的各种信息,并将采集到的信息存入基于传
输协议的EEPROM 外部扩展存储芯片中,并将信息实时的显示在LCD 上。程序设
计采用模块化的思想并且进行了分块调试,最终对系统进行了整版测试确定了系
统的可靠性。
关键词:ATS52 总线协议模块化
1 方案设计
1.1 方案的论证与选择
1.1.1 MCU 控制器的选用
方案一:采用 32 位的ARM2138 作为收款机的控制核心。ARM2138 具有强大
的存储能力,内嵌32K 片内静态RAM 和512K 的flash 内存,可以实现在系统可
编程(ISP),在应用可编程(IAP),并拥有2 个8 路10 位A/D 转换器,1 个D/A
转换器,转换迅速准确,引脚资源丰富,多达47 个可承受5V 电压的通用I/O
口。
方案二:采用传统的 8 位的51 系列单片机作为控制器。ATS52 单片机具
有实时调试的功能,内嵌8K flash 程序内存,256B 数据存储器,1 个全双工串
口资源等。无论是从内部构造还是编程方面51 系列单片机都相对简单,容易使
用。
综合考虑:ARM2138 功能强大,但本设计中没有涉及到大量的运算以及A/D
转换等功能,使用32 位的ARM 处理器浪费资源;ATS52 单片机的价格便宜,
使用简单方便,且可以满足系统设计要求,故选用ATS52 单片机作为系统的
控制核心。
1.1.2 键盘模块的方案选择
方案一:采用PS/2 标准键盘,PS/2 标准键盘价格低、通用、可靠,且
连接线少(理论上仅使用2 根),并且可满足多种系统的要求,更重要的是键盘
资源十分丰富,符合本设计的需要,有益于扩展应用。
方案二:采用集成 8279 驱动矩阵键盘或者面积更大的矩阵键盘,
这种键盘可以满足系统的要求,但是需要考虑按键抖动的情况,虽然软件消除抖
动会占用大量CPU 的资源,硬件消除抖动会大大增加电路的复杂程度,但考虑的
选用的ATS52 单片机学习板是自带一个矩阵键盘可以直接使用。
综合考虑,选用自带矩阵键盘作为输入设备。
1.1.3 存储模块方案选择
鉴于收款机的某些功能,本设计要求系统的存储容量足够大。仅仅凭控制器
内部的存储空间难以满足商品价目表以及购物日志等信息的存储要求,故本设计
对MCU 进行外部存储的扩展。
外接 SD 卡可以进行存储空间的扩展,而且还可以脱离系统使用读卡器读取
SD 内存储的信息。但是需要比较复杂的硬件连接电路,而EEPROM 只需要很少的
信号线(两根,一个数据线,一根时钟信号线)。相比较而言,EEPROM 采用的总
线比SD 卡采用的SDI/SPI 协议更容易实现。
本设计选用 EEPROM 对MCU 进行外部存储扩展。
1.1.4 LCD 显示模块方案选择
方案一:采用OCM4X8C 作为主液晶显示器。OCM4X8C 液晶显示模块是
点阵的汉子图型液晶显示模块,可显示汉字及图形,可与CPU 直接接口,提供两
种界面来连接微处理机:8-位并行及串行两种连接方式。而且具有多种功能:光
标显示、画面显示、画面移位、睡眠模式等。
方案二:采用型号为 SMC1602A 的点阵液晶,该液晶可以完成编号、
物品名(简单英文字母代替)、价格的显示。低功耗、高性价比,硬件电路结构
和显示程序都很简洁,符合设计的基本要求,就简易可行和成本方面考虑,选用
1602A 液晶显示器。
1.2 设计的总方案
本设计由 ATS52 作为控制核心、扩展了矩阵键盘实现数值输入、扩
展了SMC1602A 显示液晶屏实现字符显示、使用EEPROM 扩展系统存储资源。系统
的电源由USB 接口提供或者由外接稳压电源提供,同时,在系统板上设置了一片
电压为3V 的纽扣电池,当系统突然断电后,纽扣电池作维持系统运作,防止信
息丢失,实现掉电保护;EEPROM 具有掉电后信息不丢失的特性,也可以实现一定的掉电保护。
2 典型环节的设计
2.1 主控芯片ATS52 的介绍
主要性能:
与 MCS-51 单片机产品兼容、8K 字节在系统可编程Flash 存储器、 1000
次擦写周期、全静态操作:0Hz~33MHz、三级加密程序存储器、32 个可编
程I/O 口线、三个16 位定时器/计数器、八个中断源、全双工UART 串行通
道、低功耗空闲和掉电模式、掉电后中断可唤醒、看门狗定时器、双数据
指针、掉电标识符。
功能特性描述:
ATS52 是一种低功耗、高性能CMOS8 位微控制器,具有8K 在系统可
编程flash 存储器。使用Atmel 公司高密度非易失性存储器技术制造,与
工业80C51 产品指令和引脚完全兼容。片上flash 允许程序存储器在系统
可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU 和在系统
江西师范大学理电学院电子系07 级电子综合实践文稿
70
可编程flash,使得ATS52 为众多嵌入式控制应用系统提供高灵活、超有
效的解决方案。ATS52 具有以下标准功能:8K 字节flash,256 字节RAM,
32 位I/O 口线,看门狗定时器,2 个数据指针,三个16 位定时器/计数器,
一个6 向量2 级中断结构,全双工串行口,片内晶振及时钟电路。另外,
ATS52 可降至0Hz 静态逻辑操作,支持2 种软件可选择节电模式。空闲
模式下,CPU 停止工作,允许RAM、定时器/计数器、串口、中断继续工作。
掉电保护方式下,RAM 内容被保存,振荡器被冻结,单片机一切工作停止,
直到下一个。中断或硬件复位为止。8 位微控制器 8K 字节在系统可编程
flash ATS52。
P0 口:P0 口是一个8 位漏极开路的双向I/O 口。作为输出口,每位能
驱动8 个TTL 逻辑电平。对P0 端口写“1”时,引脚用作高阻抗输入。当
访问外部程序和数据存储器时,P0 口也被作为低8 位地址/数据复用。在这
种模式下,P0 不具有内部上拉电阻。
在 flash 编程时,P0 口也用来接收指令字节;在程序校验时,输出指
令字节。程序校验时,需要外部上拉电阻。
P1 口:P1 口是一个具有内部上拉电阻的8 位双向I/O 口,p1 输出缓
冲器能驱动4 个TTL 逻辑电平。对P1 端口写“1”时,内部上拉电阻把端
口拉高,此时可以作为输入口使用。作为输入使用时,被外部拉低的引脚
由于内部电阻的原因,将输出电流(IIL)。
此外,P1.0 和P1.2 分别作定时器/计数器2 的外部计数输入(P1.0/T
2)和时器/计数器2 的触发输入(P1.1/T2EX),具体如下表所示。
在 flash 编程和校验时,P1 口接收低8 位地址字节。
引脚号第二功能
P1.0 T2(定时器/计数器T2 的外部计数输入),时钟输出
P1.1 T2EX(定时器/计数器T2 的捕捉/重载触发信号和方向控制)
P1.5 MOSI(在系统编程用)
P1.6 MISO(在系统编程用)
P1.7 SCK(在系统编程用)
P2 口:P2 口是一个具有内部上拉电阻的8 位双向I/O 口,P2 输出缓
冲器能驱动4 个TTL 逻辑电平。对P2 端口写“1”时,内部上拉电阻把端
口拉高,此时可以作为输入口使用。作为输入使用时,被外部拉低的引脚
由于内部电阻的原因,将输出电流(IIL)。
在访问外部程序存储器或用 16 位地址读取外部数据存储器(例如执行
MOVX @DPTR)时,P2 口送出高八位地址。在这种应用中,P2 口使用很强的
内部上拉发送1。在使用8 位地址(如MOVX @RI)访问外部数据存储器时,
P2 口输出P2 锁存器的内容。
在 flash 编程和校验时,P2 口也接收高8 位地址字节和一些控制信号。
P3 口:P3 口是一个具有内部上拉电阻的8 位双向I/O 口,P3 输出缓
冲器能驱动4 个TTL 逻辑电平。对P3 端口写“1”时,内部上拉电阻把端
口拉高,此时可以作为输入口使用。作为输入使用时,被外部拉低的引脚
由于内部电阻的原因,将输出电流(IIL)。
P3 口亦作为ATS52 特殊功能(第二功能)使用,如下表所示。
在 flash 编程和校验时,P3 口也接收一些控制信号。
端口引脚 第二功能
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 INTO(外中断0)
P3.3 INT1(外中断1)
P3.4 TO(定时/计数器0)
P3.5 T1(定时/计数器1)
P3.6 WR(外部数据存储器写选通)
P3.7 RD(外部数据存储器读选通)
此外,P3 口还接收一些用于FLASH 闪存编程和程序校验的控制信号。
RST——复位输入。当振荡器工作时,RST 引脚出现两个机器周期以上
高电平将是单片机复位。
ALE/PROG——当访问外部程序存储器或数据存储器时,ALE(地址锁存
允许)输出脉冲用于锁存地址的低8 位字节。一般情况下,ALE 仍以时钟振
江西师范大学理电学院电子系07 级电子综合实践文稿
72
荡频率的1/6 输出固定的脉冲信号,因此它可对外输出时钟或用于定时目
的。要注意的是:每当访问外部数据存储器时将跳过一个ALE 脉冲。
对 FLASH 存储器编程期间,该引脚还用于输入编程脉冲(PROG)。
如有必要,可通过对特殊功能寄存器(SFR)区中的8EH 单元的D0 位
置位,可禁止ALE 操作。该位置位后,只有一条MOVX 和MOVC 指令才能将A
LE 激活。此外,该引脚会被微弱拉高,单片机执行外部程序时,应设置AL
E 禁止位无效。
PSEN——程序储存允许(PSEN)输出是外部程序存储器的读选通信号,
当ATC52 由外部程序存储器取指令(或数据)时,每个机器周期两次PS
EN 有效,即输出两个脉冲,在此期间,当访问外部数据存储器,将跳过两
次PSEN 信号。
EA/VPP——外部访问允许,欲使CPU 仅访问外部程序存储器(地址为0
000H-FFFFH),EA 端必须保持低电平(接地)。需注意的是:如果加密位
LB1 被编程,复位时内部会锁存EA 端状态。
如 EA 端为高电平(接Vcc 端),CPU 则执行内部程序存储器的指令。
FLASH 存储器编程时,该引脚加上+12V 的编程允许电源Vpp,当然这必
须让该器件是使用12V 编程电压Vpp
。图 2-1 ATS52 引脚图
2.2 扩展键盘的设计
矩阵键盘是单片机编程中所使用的键盘.
1.矩阵式键盘的结构与工作原理
在键盘中按键数量较多时,为了减少 I/O 口的占用,通常将按键排列
成矩阵形式,如图2-2 所示。在矩阵式键盘中,每条水平线和垂直线在交
叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1 口)
就可以构成个按键,比之直接将端口线用于键盘多出了一倍,而
且线数越多,区别越明显,比如再多加一条线就可以构成20 键的键盘,而
直接用端口线则只能多出一键(9 键)。由此可见,在需要的键数比较多时,
采用矩阵法来做键盘是合理的。
图 2-3 矩阵键盘仿真示意图
矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,下
图中,行线通过电阻接正电源,并将列线所接的单片机的I/O 口作为输出
端,而行线所接的I/O 口则作为输入。这样,当按键没有按下时,所有的
输出端都是高电平,代表无键按下。列线输出是低电平,一旦有键按下,
则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按
下了。具体的识别及编程方法如下所述。
2.矩阵式键盘的按键识别方法
确定矩阵式键盘上何键被按下介绍一种“行扫描法”。行扫描法 行
扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法,
如上图所示键盘,介绍过程如下。
1、判断键盘中有无键按下将全部行线 Y0-Y3 置低电平,然后检测列
线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合
的键位于低电平线与4 根行线相交叉的4 个按键之中。若所有列线均为高
电平,则键盘中无键按下。
2、判断闭合键所在的位置在确认有键按下后,即可进入确定具体闭
合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电
平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各
列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按
键就是闭合的按键。
下面给出一个具体的例子:
图仍如上所示。ATS52 单片机的P1 口用作键盘I/O 口,键盘的行线
接到P1 口的低4 位,键盘的列线接到P1 口的高4 位。行线P1.0-P1.3 分
别接有4 个上拉电阻到正电源+5V,并把行线P1.0-P1.3 设置为输入线,列
线P1.4-P.17 设置为输出线。4 根行线和4 根列线形成16 个相交点。
1、检测当前是否有键被按下。检测的方法是P1.4-P1.7 输出全“0”,
读取P1.0-P1.3 的状态,若P1.0-P1.3 为全“1”,则无键闭合,否则有键
闭合。
2、去除键抖动。当检测到有键按下后,延时一段时间再做下一步的
检测判断。
3、若有键被按下,应识别出是哪一个键闭合。方法是对键盘的行线
进行扫描。P1.4-P1.7 按下述4 种组合依次输出:
P1.7 1 1 1 0
P1.6 1 1 0 1
P1.5 1 0 1 1
P1.4 0 1 1 1
在每组行输出时读取P1.0-P1.3,若全为“1”,则表示为“0”这一行
没有键闭合,否则有键闭合。由此得到闭合键的行值和列值,然后可采用
计算法或查表法将闭合键的行值和列值转换成所定义的键值
4、为了保证键每闭合一次CPU 仅作一次处理,必须却除键释放时的
抖动。
键盘扫描程序:
从以上分析得到键盘扫描程序的流程图如图 2-3 所示。
图 2-3 键盘输入流程图
扫描程序如下:
unsigned char Keycan(void) // 按键扫描程序 P1.0--P1.3 为行线
P1.4--P1.7 为列线
{
unsigned char rcode, ccode;
P1 = 0xF0; // 发全0 行扫描码,列线输入
if((P1&0xF0) != 0xF0) // 若有键按下
{
delay();// 延时去抖动
if((P1&0xF0) != 0xF0)
{ rcode = 0xFE; // 逐行扫描初值
while((rcode&0x10) != 0)
{
P1 = rcode; // 输出行扫描码
if((P1&0xF0) != 0xF0) // 本行有键按下
{
ccode = (P1&0xF0)|0x0F;
do{;}while((P1&0xF0) != 0xF0); //等待键释放
return ((~rcode) + (~ccode)); // 返回键编码
}
else
rcode = (rcode<<1)|0x01; // 行扫描码左移一位
}
}
}
return 0; // 无键按下,返回值为0
}
2.3 EEPROM 外部存储器的设计
本设计使用的学习板自带型号为 ATMEL752 24C08 的EEPROM.
1、描述
24C08 是可擦除PROM ,采用1024 8-bit 的组织结构以及两线串行接口。
电压可允许低至1.8V,待机电流和工作电流分别为1uA 和1mA。24C08 具有页写
能力,每页为16 字节。24C08 具有8-pin PDIP 和8-pin SOP 两种封装形式。
(1)特点
宽范围的工作电压 1.8V~5.5V
低电压技术
—1mA 典型工作电流
—1uA 典型待机电流
存储器组织结构
—24C08,1024 8(8K bits)
2 线串行接口,完全兼容总线
时钟频率为 1MHz(5V),400kHz(1.8V,2.5V,2.7V)
施密特触发输入噪声抑制
硬件数据写保护
内部写周期(最大 5ms )
可按字节写
页写:16 字节页
可按字节,随机和序列读
自动递增地址
ESD 保护大于2.5kV
高可靠性
—擦写寿命:100 万次
—数据保持时间:100 年
无铅工艺,符合 RoHS 标准
(2) 应用领域
智能仪器仪表 工业控制 家用电器
计算机 笔记本电脑 汽车电子 通信设备
(3) 封装及结构框图
封装形式的 24C08
24C08 内部结构框图
(4) 详细操作说明
24 系统的EEPROM 支持总线传输协议。 是一种双向、两线串行通讯
接口,分别是串行数据线SDA 和串行时钟线SCL。两根线必须通过一个上拉电阻
接到电源。典型的总线配置如图2-4 所示
图 2-4 典型两线总线配置
总线上发送数据的器件被称作发送器,接受数据的器件被称作接收器。控制
信息交换的器件被称作主器件,受主器件控制的器件被称作从器件。主器件产生
串行时钟SCL,控制总线的访问状态、产生START 和STOP 条件。24C 系列在总
线中作为从器件工作。
只有当总线处于空闲状态时才可以启动数据传输。每次数据传输均开始于
START 条件,结束于STOP 条件,二者之间的数据字节数是没有的,由总线
上的主器件决定。信息以字节(8 位)为单位传输,第9 位时由接收器产生应答。
起始和停止条件
数据和时钟线都是为高则称总线处在空闲状态。当SCL 为高电平时SDA 的下
降沿(高到低)叫做起始条件(START,简写为S),SDA 的上升沿(低到高)则
叫做停止条件(STOP,简写为P)。参见下图2-5
图 2-5 起始条件和停止条件的定义
位传输
每个时钟脉冲传送一位数据。SCL 为高时SDA 必须保持稳定,因为此时SDA
的改变被认为是控制信号。位传输参见下图2-6图 2-6 位传输
应答
。
。
总线上的接收器接收到一个字节就产生一个应答,主器件必须产生一个对应
的额外的时钟脉冲,参见下图2-7。
图 2-7 I2C 总线的应答
接收器拉低 SDA 线表示应答,并在应答脉冲期间保持稳定的低电平。当主器
件作接收器时,必须发出数据传输结束的信号给发送器,即它在最后一个字节之
后的应答脉冲期间不会产生应答信号(不拉低SDA)。这种情况下,发送器必须
释放SDA 线为高以便主器件产生停止条件。
器件寻址
起始条件使能芯片读写操作后,EEPROM 都要求有8 位的器件地址信息(见
下图2-8)。
器件地址信息由“1”、“0”序列组成,前4 位如图中所示,对于所有串行
EEPROM 都是一样的。
对于 24C02/32/,随后3 位A2、A1 和A0 为器件地址位,必须与硬件输入
引脚保持一致。
对于 24C08,随后1 位A2 为器件地址位,另2 位为页地址位。A2 必须与器
件输入引脚保持一致,而 A1 和A0 是空脚图2-8 器件地址
器件操作
待机模式
EEPROM 具有低功耗待机的特点,条件为:(1)电源上电;(2)接收停止条
件及完成任务内部操作后。
存储复位
。
当协议中产生中断、掉电或系统复位后, 总线可通过以下步骤复位:
(1) 产生 9 个时钟周期。
(2) 当 SCL 为高时,SDA 也为高。
(3) 产生一个起始条件。
写操作
1. 字节写
写操作要求在接收器件地址和 ACK 应答后,接收8 位字地址。接收到这个地
址后EEPROM 应答“0”,然后是一个8 位数据。在接收8 位数据后,EEPROM 应答
“0”,接着必须由主器件发送停止条件来终止写序列。
此时 EEPROM 进入内部写周期,数据写入非易失性存储器中,在此期间
所有输入都无效。直到写周期完成,EEPROM 才会有应答(见图2-9)。
图 2-9 字节写
2. 页写
24C08 器件按16 字节/页执行页写,页写初始化与字节写相同,只是主器件
不会在第一个数据后发送停止条件,而是在EEPROM 的ACK 以后,接着发送15
个数据。EEPROM 收到每个数据后都应答“0”。最后仍需由主器件发送停止条件,
终止写序列(见图2-10)。
接收到每个数据后,字地址的低4 位内部自动加1,高位地址位不变,维持
在当前页内。当内部产生的字地址达到该页边界地址时,随后的数据将写入该页
的页首。如果超过16 个数据传送给了EEPROM ,字地址将回转到该页的首字节,
当前的字节将会被覆盖。
3.应答查询
一旦内部写周期启动,EEPROM 输入无效,此时即可启动应答查询:发送起
始条件和器件地址(读/写位为期望的操作)。只有内部写周期完成,EEPROM 才
应答“0”。之后可继续读/写操作。
应答查询流程见图 2-11。
图 2-11 应答流程查询
读操作
读操作与写操作初始化相同,只是器件地址中的读/写选择位应为“1”。有
三种不同的读操作方式:当前地址读,随机读和顺序读。
1. 当前地址读
内部地址计数器保存着上次访问时最后一个地址加 1 的值。只要芯片有电,
该地址就一直保存。当读到最后页的最后字节,地址会回转到0;当写到某页尾
的最后一个字节,地址会回转到该页的首字节。
接收器地址(读/写选择位为“1”)、EEPROM 应答ACK 后,当前地址的数据
就随时钟送出。主器件无需应答“0”,但需要发送停止条件(见图2-12)。
图 2-12 当前地址读
2. 随机读
随机读需要先写一个目标地址,一旦 EEPROM 接收器件地址和字地址并应答
了ACK,主器件就产生一个重复的起始条件。
然后,主器件发送器地址(读/写选择位为“1”),EEPROM 应答ACK,并随时
钟发送出数据。主器件无需应答“0”,但需发送停止条件(见图2-13)。
图 2-13 随机读
3. 顺序读
顺序读可以通过“当前地址读”或“随机读”启动。主器件接收到一个数据
后,应答ACK 。只要EEPROM 接收到ACK ,将自动增加字地址并继续随时钟发送
后面的数据。若达到存储器地址末尾,地址自动回转到0,仍可继续顺序读取数
据。
主器件不应答“0”,而发送停止条件,即可结束顺序读操作(见图2-14)
图 2-14 顺序读
2.3 1302 电子时钟模块
2.3.1 概述
DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/
日历31 字节静态RAM ,通过简单的串行接口与单片机进行通信实时时钟/日历
电路。提供秒分时日日期。月年的信息,每月的天数和闰年的天数可自动调整时
钟操作可通过AM/PM 指示决定采用24 或12 小时格式。DS1302 与单片机之间能
简单地采用同步串行的方式进行通信,仅需用到三个口线:1 RES 复位,2 I/O 数
据线,3 SCLK 串行时钟。时钟/RAM 的读/写数据以一个字节或多达31 个字节的
字符组方式通信。DS1302 工作时功耗很低,保持数据和时钟信息时功率小于
1mW。DS1302 是由DS1202 改进而来,增加了以下的特性。双电源管脚用于主电
源和备份电源供应Vcc1,为可编程涓流充电电源附加七个字节存储器。它广泛
应用于电话传真便携式仪器以及电池供电的仪器仪表等产品领域。
下面将主要的性能指标作一综合:
实时时钟具有能计算 2100 年之前的秒分时日日期星期月年的能力还有
闰年调整的能力;
31 8 位暂存数据存储RAM;
串行 I/O 口方式使得管脚数量最少;
宽范围工作电压 2.0 5.5V;
工作电流 2.0V 时,小于300nA;
读/写时钟或RAM 数据时有两种传送方式单字节传送和多字节传送字符
组方式;
8 脚DIP 封装或可选的8 脚SOIC 封装根据表面装配;
简单 3 线接口;
与 TTL 兼容Vcc=5V;
可选工业级温度范围-40 +85;
与 DS1202 兼容;
在 DS1202 基础上增加的特性;
对 Vcc1 有可选的涓流充电能力;
双电源管用于主电源和备份电源供应;
备份电源管脚可由电池或大容量电容输入;
附加的 7 字节暂存存储器。
2.3.2 DS1302 的基本组成和工作原理
DS1302 的引脚功能排列及描述如下:
管脚描述
X1 X2 32.768KHz 晶振管脚
GND 地
RST 复位脚
I/O 数据输入/输出引脚
SCLK 串行时钟
Vcc1,Vcc2 电源供电管脚
DS1302 串行时钟芯片8 脚DIP
DS1302S 串行时钟芯片8 脚SOIC 200mil
DS1302Z 串行时钟芯片8 脚SOIC 150mil
2.3.3 DS1302 内部寄存器
CH :时钟停止位寄存器 2 的第7 位12/24 小时标志
CH=0 振荡器工作允许 bit7=1,12 小时模式
CH=1 振荡器停止 bit7=0,24 小时模式
WP :写保护位寄存器 2 的第5 位:AM/PM 定义
WP=0 寄存器数据能够写入 AP=1 下午模式
WP=1 寄存器数据不能写入 AP=0 上午模式
TCS :涓流充电选择 DS :二极管选择位
TCS=1010 使能涓流充电 DS=01 选择一个二极管
TCS=其它禁止涓流充电 DS=10 选择两个二极管
DS=00 或11, 即使 TCS=1010, 充电功能也被禁止
微控制器的接口软件及功能应用举例
2.3.4 DS1302 与
下面首先给出基本的接口软件然后举例说明各种功能的应用
1 写保护寄存器操作
当写保护寄存器的最高位为 0 时允许数据写入寄存器写保护寄存器可以通
过命令字节8E,8F 来规定禁止写入/读出写保护位不能在多字节传送模式下写
入
Write_Enable:
MOV Command,#8Eh ;命令字节为8E
MOV ByteCnt,#1 ;单字节传送模式
MOV R0,#XmtDat ;数据地址覆给R0
MOV XmtDat,#00h ;数据内容为0 写入允许
ACALL Send_Byte ;用写入数据子程序
RET ;返回调用本子程序处
当写保护寄存器的最高位为 1 时禁止数据写入寄存器
Write_Disable:
MOV Command,#8Eh ;命令字节为8E
MOV ByteCnt,#1 ;单字节传送模式
MOV R0,#XmtDat ;数据地址覆给R0
MOV XmtDat,#80h ;数据内容为80h 禁止写入
ACALL Send_Byte ;调用写入数据子程序
RET ;返回调用本子程序处
2 时钟停止位操作
当把秒寄存器的第 7 位时钟停止位设置为0 时起动时钟开始
Osc_Enable:
MOV Command,#80h ; 命令字节为80
MOV ByteCnt,#1 ; 单字节传送模式
MOV 0,#XmtDat ; 数据地址覆给R0
MOV XmtDat,#00h ; 数据内容为0 振荡器工作允许
ACALL Send_Byte ;调用写入数据子程序
RET ;返回调用本子程序处
当把秒寄存器的第 7 位时钟停止位设置为1 时时钟振荡器停止HT1380 进
入低功耗方式
Osc_Disable:
MOV Command,#80h ;命令字节为80
MOV ByteCnt,#1 ;单字节传送模式
MOV R0,#XmtDat ;数据地址覆给R0
MOV XmtDat,#80h ;数据内容为80h 振荡器停止
ACALL Send_Byte ;调用写入数据子程序
RET ;返回调用本子程序处
3 多字节传送方式
当命令字节为BE 或BF 时DS1302 工作在多字节传送模式8 个时钟/日历寄
存器从寄存器0 地址开始连续读写从0 位开始的数据当命令字节为FE 或FF 时
DS1302 工作在多字节RAM 传送模式31 个RAM 寄存器从0 地址开始连续读写从
0 位开始的数据。
例如写入 00 年6 月21 日星期三13 时59 分59 秒程序设置如下:
Write_Multiplebyte:
MOV Command,#0BEh ;命令字节为BEh
MOV ByteCnt,#8 ;多字节写入模式此模块为8 个
MOV R0,#XmtDat ;数据地址覆给R0
MOV XmtDat,#59h ;秒单元内容为59h
MOV XmtDat+1,#59h ;分单元内容为59h
MOV XmtDat+2,#13h ;时单元内容为13h
MOV XmtDat+3,#21h ;日期单元内容为21h
MOV XmtDat+4,#06h ;月单元内容为06h
MOV XmtDat+5,#03h ;星期单元内容为03h
MOV XmtDat+6,#0 ;年单元内容为00h
MOV XmtDat+7,#0 ;写保护单元内容为00h
ACALL Send_Byte ;调用写入数据子程序
RET ;返回调用本子程序处
读出寄存器 0-7 的内容程序设置如下:
Read_Multiplebyte:
MOV Command,#0BFh ;命令字节为BFh
MOV ByteCnt,#8 ; ;多字节读出模式此模块为8 个
MOV R1,#RcvDat ;数据地址覆给R1
ACALL Receive_Byte ;调用读出数据子程序
RET ;返回调用本子程序处
4 单字节传送方式
例如写入 8 时12 小时模式程序设置如下
Write_Singlebyte:
MOV Command,#84h ; 命令字节为84h
MOV ByteCnt,#1 ; 单字节传送模式
MOV R0,#XmtDat ; 数据地址覆给R0
MOV XmtDat,#88h ; 数据内容为88h
ACALL Send_Byte ; 调用写入数据子程序
RET ; 返回调用本子程序处
2.4 液晶显示模块
现在的字符型液晶模块已经是单片机应用设计中最常用的信息显示器件。
1602 型LCD 显示模块具有体积小,功耗低,显示内容丰富等特点。1602 型LCD
可以显示2 行16 个字符,有8 位数据总线D0-D7 和RS,R/W,EN 三个控制端口,
工作电压为5V,并且具有字符对比度调节和背光功能。
2.4.1 接口信号说明
1602 型LCD 的接口信号说明如表
2.4.2 主要技术参数
1602 型LCD 的主要技术参数如下表2-2 所示
表 2-1 信号表
表 2-2 主要技术2-1 所示
参数
2.4.3 基本操作程序
读状态:输入:RS=L,RW=L, E=H 输出:D0-D7=状态字
读数据:输入:RS=H,RW=H, E=H 输出:无
写指令:输入:RS=L,RW=L,D0-D7=指令码,E=高脉冲输出:D0-D7=数据
写数据:输入:RE=H,RW=L,D0-D7=数据,E=高脉冲输出:无
2.4.4 液晶1602 的工作指令集
1、清屏
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 0 0 0 0 0 1
运行时间(250Khz):1.ms;
功能:清DDRAM 和AC 值。
2、归位
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 0 0 0 0 1 *
运行时间(250Khz):1.ms;
功能:AC=0,光标、画面回HOME 位。
3、输入方式设置
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0 0 0 0 0 0 0 1 I/D S
运行时间(250Khz):40us;
功能:设置光标、画面移动方式。
其中:I/D=1:数据读、写操作后,AC 自动增一;
I/D=0:数据读、写操作后,AC 自动减一;
S=1:数据读、写操作,画面平移;
S=0:数据读、写操作,画动,不影响DDRAM。
其中:S/C=1:画面平移一个字符位;
S/C=0:光标平移一个字符位;
R/L=1:右移;R/L=0:面不动;
功能:光标、画面移
左移。
功能:根据最近设
置的地址性质,从DDRRAM 或CGRAM 数据读出。
3 理论分析及计算
经查阅数据得知,AT24C08(EEPROM)的内部结构是按页分区的,每16 个
字节是一页,题目要求记录100 个商品价目表(PLU),每个商品包括编号、品名
(简单英文字母代替)、单价信息。可以计算得出每件商品的信息需要的存储空
间长度约为2Byte。为了方便起见,我们约定,每两种商品都是独占一页(尽管
两种种商品不会占满一页),这样无论是存货还是在销售时各条记录之间不会冲
突,我们只要按页读写就绝不会出错。因为是简易超市收银机,所以我们能达到
简单的目的就可以了。
AT24C08(EEPROM)存储芯片有1KB 空间,1KB/16Byte= 页。即存储的销
售记录与商品信息总计可达 2=128 条,此容量已足以满足我们的设计要求。
如果是更大型的超市,可以购买更大容量的EEPROM 存储芯片。
4 软件设计
4.1 主程序流程图
5 调试
5.1 液晶模块调试
硬件初次完成时,液晶只显示一行黑块,不能正常显示。首先写一个液晶测
试程序。程序如下:
/******************/
/*液晶显示数字 1 */
/******************/
#include #define uchar unsigned char #define uint unsigned int sbit en=P3^0; sbitrs=P3^2; void delay(uint z) { uintx,y; for(x=z;x>0;x--) for(y=124;y>0;y--); } void write_com(uchar com) // 写 命令函数 { rs=0; P0=com; delay(5); en=1; delay(5); en=0; } void write_data(uchar date) // 写数据 { rs=1; P0=date; delay(5); en=1; delay(5); en=0; } voidinit() { en=0; write_com(0x38); //设置显示模 式,一般固定 delay(1); write_com(0x0e); //开显示,显 示光标,光标闪烁 delay(1); write_com(0x06); //写一个字符 后地址指针加一 delay(1); write_com(0x80); //设置数据指 针,为初始位置 delay(1); } void main() { init(); write_data('1'); //显示数字 1 while(1); } 写完程序后仿真,将生成的.hex 文件下载到芯片中,可以显示。然后将.hex 文件下载到单片机中,硬件上电后仍然只显示一行黑块。因此知道液晶写数据时 出现问题,再次对照电路图检查硬件连接,发现液晶的E(6 脚),RS(4 脚)与 单片机上的P3.0, P3.2 管脚接反了,导致液晶不能正常初始化,也就不能正常 显示。 5.2 键盘调试部分 液晶能显示以后,按键按下时抖动很大,按一下键盘,会显示几个数字。 程序有去抖部分,也写了松手检测,但松手检测时没有延时程序。因此首先在松 手检测部分加上延时程序。 在松手检测处加延时程序后,发现在按下键的过程中还会存在轻微抖动情 况,然后在键盘扫描子程序处加延时子程序,否则可能读不到正确的按键情况。 修改后程序如下: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;键盘扫描 key: call ks; jnz k1; jmp key; k1: call delay; callks; jnz k2; jmp key; k2: clr tr0; clr led; MOV r2,#0feh; MOV r6,#00h; k3: MOV a,r2; MOV p2,a; MOV a,p2; jb acc.4,l1; MOV a,#0; LJMP lk; l1: jb acc.5,l2; MOV a,#4; LJMP lk; l2: jb acc.6,l3; MOV a,#8; LJMP lk; l3: jb acc.7,next_key; MOV a,#12; lk: add a,r6; MOV r6,a; k4: call ks; call delay ;加延时程序 jnz k4; 松手检测 MOV a,r6; MOV dptr,#table0; MOVc a,@a+dptr; MOV 50h,a; 查表取值存入50h,保护键值 ret; next_key: inc r6; MOV a,r2; jnb acc.7,key; rl a; MOV r2,a; jmp k3; ;;;;;;;;;;;;;;;;;;;;;;;;;; ks: MOV p2,#0f0h; MOV a,p2; call delay; 加延时程序 xrl a,#0f0h; ret; 6 总结 在做本系统中,分硬件和软件两个部分来设计。硬件是以单片机ATS52 作 为数字处理主控芯片、LCD1602 作为显示模块,还有4 4 键盘和其他辅助电路, 构成整个的硬件系统。用户可以通过键盘输入物品编号,编号正确后显示相应的 商品名称和单价,并且还附带日历时钟显示。因为本系统直接使用单片机学习板, 所以软件部分是整个控制器的重要组成部分,设计的好坏关系到系统的性能。在 控制器的软件中,采用汇编语言设计程序,编程,调试方便。 参考文献 [1]胡汉才.单片机原理及其接口技术[M],北京,清华大学出版社,62-,2009 [2]加I2C 的电子密码锁[EB],proteus 仿真论坛, http://proteus.5d6d.com/thread-1603-1-1.html , 2009.2.10 [3]刘士娟.课程设计电子密码锁设计[EB],, http://wenku.baidu.com/view/f619b3c69ec3d5bbfd0a7419.html ,2010.3 [4]华成英,童诗白.模拟电子技术基础[M],北京,高等教育出版社,28-33,2008.4 [5]1602 字符型液晶使用手册+实例[EB],电子园论坛, http://bbs.cepark.com/viewthread.php?tid=218&highlight=1602 ,2008.5 [6]戴仙金.51 单片机及其C 语言程序开发实例[M],北京,清华大学出版社, 附录1 收银机工作原理图 附录2 程序代码 时钟显示程序: #include \"reg51.h\" #define uchar unsigned char sbit RW=P2^3; sbit RS=P2^2; sbit E=P2^4; bit at=0; //sbit busy_bit=P1^7; uchar code shen[]={\"CLOCK!\ uchar word[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x20}; uchar dispbuf[8],h,m,s,counter; void delay() { uchar i; for(i=0;i<255;i++); } code /*******写命令**********/ void lcd_wmc(uchar i) { P0=i; RS=0; RW=0; E=0; delay(); E=1; } /*******写数据***********/ void lcd_wmd(uchar i) { P0=i; RS=1; RW=0; E=0; delay(); E=1; } /*******初始化液晶*******/ void lcd_init() { uchar i; lcd_wmc(0x01); lcd_wmc(0x38); 99 lcd_wmc(0x0c); lcd_wmc(0x06); lcd_wmc(0xc9); for(i=0;i<6;i++) lcd_wmd(shen[i]); lcd_wmc(0xc0); } /*******更新缓冲区子程序*******/ void newbuf() { dispbuf[0]=s%10; dispbuf[1]=s/10; dispbuf[3]=m%10; dispbuf[4]=m/10; dispbuf[6]=h%10; dispbuf[7]=h/10; } /*******显示子程序**********/ void disp(uchar dispadd) { uchar tmp; lcd_wmc(dispadd); tmp=dispbuf[7]; tmp=word[tmp]; lcd_wmd(tmp); tmp=dispbuf[6]; tmp=word[tmp]; lcd_wmd(tmp); tmp=dispbuf[5]; tmp=word[tmp]; lcd_wmd(tmp); tmp=dispbuf[4]; tmp=word[tmp]; lcd_wmd(tmp); tmp=dispbuf[3]; tmp=word[tmp]; lcd_wmd(tmp); tmp=dispbuf[2]; tmp=word[tmp]; lcd_wmd(tmp); tmp=dispbuf[1]; tmp=word[tmp]; lcd_wmd(tmp); tmp=dispbuf[0]; tmp=word[tmp]; lcd_wmd(tmp); } /*********************键盘子程序***********************/ uchar keypro(void) { uchar scanl,scanh; P1=0xf0; if((P3&0xf0)!=0xf0) { delay(); if((P1&0xf0)!=0xf0) { scanl=0xfe; while((scanl&0x10)!=0) { P1=scanl; if((P3&0xf0)!=0xf0) { scanh=(P1&0xf0)|0x0f; return (~scanh)+(~scanl); } else scanl=(scanl<<1)|0x01; } } } return 0; } /********************时间调整子程序********************/ void adjustime() { uchar k; static uchar add; k=keypro(); switch(k) { case 0x88: if(!at){add=0xc1;EA=0;lcd_wmc(0xc1);lcd_wmc(0x0f);at=1;} else {lcd_wmc(0xc0);lcd_wmc(0x0c);at=0;EA=1;} break; case 0x48: if(at) { if(add==0xc1){add=0xc7; lcd_wmc(add);} else {add=add-3;lcd_wmc(add);} } break; 101 case 0x28: if(at) { if(add==0xc7) {add=0xc1;lcd_wmc(add);} else {add=add+3;lcd_wmc(add);} } break; case 0x18: if(at) { if(add==0xc1) h++; if(h==24) h=0; if(add==0xc4) m++; if(m==60) m=0; if(add==0xc7) s++; if(s==60) s=0; newbuf(); disp(0xc0); lcd_wmc(add); } break; default: break; } if(k!=0) { while((P3&0xf0)!=0xf0) P1=0xf0; } } /*********************初始化子程序**********************/ void init() { TMOD=0x01; TH0=0x4c; TL0=0x00; EA=1; ET0=1; TR0=1; counter=0; h=12;m=0;s=0; dispbuf[2]=10; dispbuf[5]=10; } 102 /***************************主程序************************/ void shizhong(void) { init(); lcd_init(); while(1) { adjustime(); if(!at) { //闪烁 if(counter<10) { dispbuf[2]=10; dispbuf[5]=10; } else { dispbuf[2]=11; dispbuf[5]=11; } //更新显示缓冲区及调用显示程序 if(counter==0) { newbuf(); disp(0xc0); } else if(counter==10) disp(0xc0); } } } /*************************定时器0 的中断**********************/ void Time0() interrupt 1 using 2 //再次强调中断子程序执行时间越短越好 { TH0=(65536-46075)/256; TL0=(65536-46075)%256; counter++; if(counter==20) { s++; counter=0; if(s==60) { 103 m++; s=0; if(m==60) { h++; m=0; if(h==24) h=0; } } } } unsigned char Keycan(void) //按键扫描程序 P1.0--P1.3 为行线 P1.4--P1.7 为列线 { unsigned char rcode, ccode; P1 = 0xF0; // 发全0 行扫描码,列线输入 if((P1&0xF0) != 0xF0) // 若有键按下 { delay();// 延时去抖动 if((P1&0xF0) != 0xF0) { rcode = 0xFE; // 逐行扫描初值 while((rcode&0x10) != 0) { P1 = rcode; // 输出行扫描码 if((P1&0xF0) != 0xF0) // 本行有键按下 { ccode = (P1&0xF0)|0x0F; do{;}while((P1&0xF0) != 0xF0); //等待键释放 return ((~rcode) + (~ccode)); // 返回键编码 } else rcode = (rcode<<1)|0x01; // 行扫描码左移一位 } } } return 0; // 无键按下,返回值为0 } Viod main() { Keyscan(viod); While(0) { Viod shizhong(); } Shoukuan(); } 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- 69lv.com 版权所有 湘ICP备2023021910号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务