市内电话计费实训报告设计.docx
《市内电话计费实训报告设计.docx》由会员分享,可在线阅读,更多相关《市内电话计费实训报告设计.docx(26页珍藏版)》请在冰点文库上搜索。
![市内电话计费实训报告设计.docx](https://file1.bingdoc.com/fileroot1/2023-6/21/624b0f41-6a2e-40b5-91fe-980782780058/624b0f41-6a2e-40b5-91fe-9807827800581.gif)
市内电话计费实训报告设计
江西科技师范大学
通信与电子学院
《单片机应用技术》实训报告
实训题目:
市内电话计费电路的设计
小组成员:
陈红英20122621
刘玉婷20122622
兰小玲20122623
班级:
12电子信息工程职教本科1班
指导老师:
尤国平
一、实训设计任务、要求
设计任务:
设计一个家庭用监测电话费开支的电话计费系统。
要求:
①通信检测功能。
检测本电话打出的有效电话次数及时间。
②每次通话以3min为计时单位,不满3min以3min计算。
③计费装置可以设置计费标准并可显示每次通话的单价(3min为
单位),可显示一个月的总费用,最多不超过999.99元。
④每日0时至7时半价计费。
2、实训计划和人员安排
1、实训计划:
5月28号——5月29号收集资料,整理大概框图思路
6月1号——6月2号绘制硬件电路图
6月3号——6月4号编写软件程序
6月5号——6月6号购买元器件,焊接硬件电路
6月7号——6月9号调试电路,完成硬件部分
6月10号——6月11号撰写实训报告
6月12号——6月13号制作PPT,录制视频
2、人员安排:
刘玉婷:
硬件设计及PPT制作
陈红英:
实训报告制作及软件设计
兰小玲:
视屏录制及元件采购
3、实训选题分析(主要完成对选题的功能分析,注重原理阐述;如何细化功能模块,软、硬件电路设计的设计思路)
1、选题分析
本课题主要是实现设计一个家庭用监测电话费开支的电话计费系统。
整个系统由单片机控制,通过时钟计数芯片DS1302实现对打出有效电话次数和时间的统计。
可通过按键对计费标准进行调整。
通过LCD1602显示单价,一个月的总费用,最多不超过999.99元。
2、硬件设计思路
本电路采用89C52单片机作为控制核心,它具有在线编程功能,低功耗,能在3V超低压工作;计数电路由DS1302提供,它是一种高性能、低功耗、带RAM的实时时钟电路;显示电路我们可以选择LCD1602来实现。
LCD1602具有显示效果优秀,显示内容多,编程简单等特点。
具体框架结构图如下:
四、方案设计(最少要提出两种不同的方案,并比较两种方案在设计、实现细节方面的差异和优劣,确定实训最终选定方案)
方案一:
采用AT89C51芯片作为硬件核心,内部具有4KBROM存储空间,能于3V的超低电压工作,而且与MCS-51系列单片机完全兼容,但是运用于电路设计中时不具备ISP在线编程技术。
显示部分采用LED数码管动态扫描,LED数码管价格适中,对于显示数字最合适,而且采用动态扫描法与单片机相连接时,占用的单片机口线少,但所需要的数码管数量太多,焊接困难极易出错,所以不采用LED数码管作为显示。
采用单片机定时计数器提供秒信号,使用程序实现对总价的计算,调节部分使用按键开关进行调节,实现对单价的调节与设定。
方案二:
采用STC89C52芯片,它能以3V的超低电压工作,同时也与MCS-51系列单片机完全兼容,该芯片内部存储器为8KBROM存储空间,同时具有89C51的功能,且具有在线编程可擦除技术,当在对电路进行调试时,由于程序的错误修改或程序的新增功能需要烧入程序时,不需要对芯片进行多次插拔,所以不会对芯片造成损坏.采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量文字,图形,显示多样,清晰可见。
采用DS1302时钟芯片实现时钟,DS1302芯片是一种高性能的时钟芯片,可自动精准的进行计数,8位的RAM作为数据暂存区,工作电压2.5V-5.5V范围内,2.5V时耗电小于300mA。
调节部分使用按键开关进行调节,实现对单价调节与设定。
最后,我们采用方案二STC89C52单片机,实时时钟芯片DS1302,显示使用LCD1602液晶显示屏,并设置了3个按键,k0为单价加,k1为单价减,SW1闭合为电话打通。
5、方案实现(根据选定的方案,给出每一功能模块具体的实现细节,所选用的具体芯片介绍,得到的硬件电路和相应的函数模块)
①、主控模块
采用AT89C52芯片,它能以3V的超低电压工作,同时也与MCS-51系列单片机完全兼容,该芯片内部存储器为8KBROM存储空间,同时具有89C51的功能,且具有在线编程可擦除技术。
②、计数模块
P3口有两个作用,一个接上DS1302的AD0-AD7(双向地址/数据复用总线),控制着DS1302的8位并行数据的地址和数据的传输,P2接上液晶的DB0-DB7(数据总线)控制着向液晶发送8位并行数据。
P3.5接上DS1302的单数据线,发送并接受数据,地址的操作。
③、单价调节模块
P1.0、P1.1和P1.7作为独立按键口。
k0、k1轻触开关为话费单价的加减,SW1自锁开关闭合时为电话打通并开始计费,断开时则表示没有电话播出。
④、液晶显示模块
液晶显示模块如上图所示,字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,本实验采用16列*2行的字符型LCD1602带背光的液晶显示屏。
P3.0口为液晶的数据/命令选择端,1为数据,2为命令,P3.1口控制液晶读/写选择端,高电平为读命令,低电平为写操作,P3.2口控制液晶使能信号。
工作原理如下:
(1)时钟芯片DS1302的工作原理:
DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置“0”,接着把RST端置“1”,最后才给予SCLK脉冲;读/写时序如下图4所示。
图5为DS1302的控制字,此控制字的位7必须置1,若为0则不能把对DS1302进行读写数据。
对于位6,若对程序进行读/写时RAM=1,对时间进行读/写时,CK=0。
位1至位5指操作单元的地址。
位0是读/写操作位,进行读操作时,该位为1;该位为0则表示进行的是写操作。
控制字节总是从最低位开始输入/输出的。
表6为DS1302的日历、时间寄存器内容:
“CH”是时钟暂停标志位,当该位为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位为0时,时钟开始运行。
“WP”是写保护位,在任何的对时钟和RAM的写操作之前,WP必须为0。
当“WP”为1时,写保护位防止对任一寄存器的写操作。
(2)DS1302的控制字节
DS1302的控制字如表1所示。
控制字节的高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出
表1DS1302的控制字格式
RAMRD
1A4A3A2A1A0
/CK/WR
(3)数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
如图5所示:
图5DS1302读/写时序图
六、仿真电路图
七、程序设计过程(介绍程序设计的算法思想、并介绍主要模块的功能及实现,用自顶向下的设计思路完成程序功能的分解)
1、基于DS1302的市内电话计费系统设计系统主程序。
设计该系统的主程序包含了液晶模块初始化、DS1302时钟控制模块初始化、定时器T0初始化、时钟程序和中断程序。
2、液晶模块初始化程序首先产生一个让LCD复位的低电平脉冲,复位后再使能LCD。
初始化中主要设置LCD模式、偏置电压、显示模式和清屏。
3、.DS1302时钟控制模块初始化程D1302时钟模块的初始化主要是往DS1302中写数据定时器T0初始化程序定时器T0的初始化主要设置定时器的操作模式、启动方式。
设置定时器的值及采用中断方式。
设置完成后,启动定时器工作。
4、时钟程序和中断程序钟程序主要包含了按键控制程序和液晶显示程序。
液晶显示主要显示两行,电话未拨打电话时:
第一行显电话拨打次数和总时间,第二行显示总电话费用和单价。
电话拨打成功时:
第一行计时,第二行显示总电话费用的初始值和单价。
8、实训程序
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#definefalse0
#definetrue1
#definelcddata1
#defineinstruction0
#defineread1
#definewrite0
#defineWRITE_SECOND0x80
#defineWRITE_MINUTE0x82
#defineWRITE_HOUR0x84
#defineREAD_SECOND0x81
#defineREAD_MINUTE0x83
#defineREAD_HOUR0x85
#defineWRITE_PROTECT0x8E//位寻址寄存器定义
sbitACC_7=ACC^7;//管脚定义
sbitSCLK=P3^5;//DS1302时钟信号
sbitDIO=P3^6;//DS1302数据信号
sbitCE=P3^7;//DS1302片选
sbitL_DI=P3^0;
sbitL_RW=P3^1;
sbitL_EN=P3^2;
sbitKeyUp=P1^0;
sbitKeyDown=P1^1;
sbitRing=P1^7;
voidSend_TextV(unsignedcharRow,unsignedcharColumn,unsignedcharcode*po,unsignedcharno);
voidSend_NumberV(unsignedcharRow,unsignedcharColumn,unsignedlongnumber,unsignedcharno,unsignedcharpoint);
voidinit_LCD(void);
voidclear_LCD(void);
voidSend_Data(bitDI,bitRW,unsignedcharLData);
unsignedcharReceive_Data(bitDI,bitRW);
ucharhour=0;minute=0;second=0;
uintCishu;//次数统计
unsignedlongTotalTime;//总时间
unsignedlongMoney;//总费用
uintPrice;//单价
voidInitial(void);
unsignedcharRead1302(unsignedcharaddr);
unsignedlongtemplast,tempnow,temptime,MoneyNow;
voidmain()
{
Initial();
init_LCD();//初始化显示屏
Cishu=0;
TotalTime=0;
Money=0;
Price=10;//单位为分
Send_TextV(0,0,"N:
0T:
0",16);//显示总次数以及总时间通信检测功能,检测本电话打出的有效电话次数及时间。
Send_TextV(1,0,"M:
0.00P:
0.10",16);//显示总费用以及单价
while
(1)
{
if(KeyUp==0)
{Price++;
if(Price>999.99)//单位分
{Price=999.99;//显示一个月的总费用,最多不超过999.99元。
}
Send_NumberV(1,11,Price,3,2);
while(!
KeyUp);
}
if(KeyDown==0)
{Price--;
if(Price<1)//单位分
{Price=1;
}
Send_NumberV(1,11,Price,3,2);
while(!
KeyDown);
}
if(Ring==0)
{clear_LCD();
MoneyNow=0;
Send_TextV(0,0,":
:
",11);
Send_TextV(1,0,"M:
P:
",11);
Send_NumberV(1,11,Price,3,2);
Send_NumberV(1,2,MoneyNow,5,2);
second=Read1302(READ_SECOND);
minute=Read1302(READ_MINUTE);
hour=Read1302(READ_HOUR);
templast=hour*3600+60*minute+second;
while
(1)
{second=Read1302(READ_SECOND);
minute=Read1302(READ_MINUTE);
hour=Read1302(READ_HOUR);
tempnow=hour*3600+60*minute+second;
temptime=(tempnow-templast);
Send_NumberV(0,6,temptime%60,2,0);
Send_NumberV(0,3,temptime/60%60,2,0);
Send_NumberV(0,0,temptime/3600,2,0);
if((hour>=0)&&(hour<7))//每日0时至7时半价计费
MoneyNow=((temptime/180)+1)*(Price/2);
else
MoneyNow=((temptime/180)+1)*(Price);
Send_NumberV(1,2,MoneyNow,5,2);
if(Ring==1)
{Cishu++;
Money=Money+MoneyNow;
TotalTime=TotalTime+temptime/180*3+3;
//每次通话以3min为计时单位,不满3min以3min计算。
Send_TextV(0,0,"N:
0T:
",16);
//显示总次数以及总时间
Send_TextV(1,0,"M:
0.00P:
",16);
//显示总费用以及单价
Send_NumberV(0,2,Cishu,6,0);
Send_NumberV(0,11,TotalTime,5,0);
Send_NumberV(1,2,Money,5,2);
Send_NumberV(1,11,Price,3,2);
break;
}
}
}
}
}
voidWrite1302(unsignedcharaddr,dat)
{
unsignedchari,temp;
CE=0;//CE引脚为低,数据传送
SCLK=0;//清零时钟总线
CE=1;//CE引脚为高,逻辑控制
//发送地址
for(i=8;i>0;i--)//循环8次移位
{
SCLK=0;
temp=addr;
DIO=(bit)(temp&0x01);//每次传输低字
addr>>=1;//右移一位
SCLK=1;
}
//发送数据
for(i=8;i>0;i--)
{
SCLK=0;
temp=dat;
DIO=(bit)(temp&0x01);
dat>>=1;
SCLK=1;
}
CE=0;
}
//数据读取子程序
unsignedcharRead1302(unsignedcharaddr)
{
unsignedchari,temp,dat1,dat2;
CE=0;
SCLK=0;
CE=1;
//发送地址
for(i=8;i>0;i--)//循环8次移位
{
SCLK=0;
temp=addr;
DIO=(bit)(temp&0x01);//每次传输低字
addr>>=1;//右
SCLK=1;
}
//读取数据
for(i=8;i>0;i--)
{
ACC_7=DIO;
SCLK=1;
ACC>>=1;
SCLK=0;
}
CE=0;
dat1=ACC;
dat2=dat1/16;//数据进制转换
dat1=dat1%16;//十六进制转十
dat1=dat1+dat2*10;
return(dat1);
}
//初始化DS1302
voidInitial(void)
{
Write1302(WRITE_PROTECT,0X00);//禁止写保
Write1302(WRITE_SECOND,0x00);//秒位初始
Write1302(WRITE_MINUTE,0x00);//分钟初始化
Write1302(WRITE_HOUR,0x08);//小时初始化
Write1302(WRITE_PROTECT,0x80);//写保护初始化
}
voidDelayms(uintxms)//延时程序
{
uinti,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);//程序延时相当于1ms
}
voidclear_LCD(void)//显示屏清屏程序
{
_nop_();
Send_Data(instruction,write,0x01);//ClearDisplay
Delayms(3);
}
voidinit_LCD(void)//初始化显示屏程序
{_nop_();
Send_Data(instruction,write,0x01);//ClearDisplay
Delayms(15);
_nop_();
Send_Data(instruction,write,0x3c);//FunctionSet
Delayms(15);
_nop_();
Send_Data(instruction,write,0x0c);//DisplayON/OFFControl
_nop_();
_nop_();
clear_LCD();
return;
}
unsignedcharReceive_Data(bitDI,bitRW)//从显示屏读指令或数据程序
{
unsignedcharLData;
L_DI=DI;
L_RW=RW;
_nop_();
P2=0xff;
P2=0xff;
_nop_();_nop_();_nop_();_nop_();
L_EN=0;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
L_EN=1;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
LData=P2;
L_EN=0;
LData=P2;
_nop_();
L_DI=1;
L_RW=1;
P2=0xff;
_nop_();
returnLData;
}
voidSend_Data(bitDI,//向显示屏发送指令或数据程序
bitRW,//DI表示发送指令或数据选择,rw选择读或写
unsignedcharLData)//需写入的数据或指令
{
unsignedcharBF;
_nop_();
BF=Receive_Data(instruction,read);
Delayms
(2);
BF=0x80;
_nop_();
while((BF&0x80)==0x00)
{_nop_();_nop_();_nop_();_nop_();_nop_();
BF=Receive_Data(instruction,read);
_nop_();_nop_();_nop_();_nop_();_nop_();
}
_nop_();_nop_();_nop_();_nop_();
L_DI=DI;
L_RW=RW;
_nop_();
P2=0xff;
_nop_();_nop_();_nop_();_nop_();
L_EN=0;
P2=LData;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
L_EN=1;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
L_EN=0;
_nop_();_nop_();_nop_();_nop_();
P2=0xff;
_nop_();
L_DI=1;
L_RW=1;
P2=0xff;
_nop_();
return;
}
voidSend_NumberV(unsignedcharRow,
//向显示屏发送显示数字程序
unsignedcharColumn,
//ROW表示行,column表示列
unsignedlongnumber,
//number表示要显示的数字
Unsignedcharno,
//no数字的位数
unsignedcharpoint
//小数点的位置
)
{//列Column0~15;行Row0~3
unsignedcharaddress,temp,Digital,i,Clear;
unsignedlongMo