重庆电力高等专科学校
计算机科学系
实 训 报 告
一、实训任务:
1、看实训要求,计划出自己实训所要用元件,在网上查找资料。
2、思考仿真原理图,然后画出来(具体I/O口暂时不确定)。
3、在网上找一些程序,然后自己改一些,进行编译。
4、编译无误之后,跟原理图相联系,完成最终的仿真图。
5、进行最后的改写,把程序和仿真原理图确定下来。
6、根据仿真图形,制作出实物图。
7、在实物制作过程中,进行电路检查和最后的调试。
二、实训要求:
要求:能显示阳历的年、月、日、星期、时、分、秒;
能显示阴历的年、月、日;
能进行日期、时间的调整。
扩展:能显示当前温度;
有闹钟功能(至少2个)
选择DS1302时钟芯片,温度传感器采用DS18B20数字温度传感器。
三、实训环境(软件、硬件):
软件:keil protues7.5
硬件:计算机2单片机的应用
四、实训意义:
在这快速发展的年代,时间对人们来说是越来越宝贵,在快节奏的生活时,人们往往忘记了时间,一旦遇到重要的事情而忘记了时间,这将会带来很大的损失。因此我们需要一个定时系统来提醒这些忙碌的人,而数字化的钟表给人们带来了极大的方便。由于单片机具有灵活性强、成本低、功耗低、保密性好等特点,所以电子日历时钟一般都以单片机为核心,外加一些外围设备来实现。
电子万年历作为电子类小设计不仅是市场上的宠儿,也是是单片机实验中一个很常用的题目。因为它的有很好的开放性和可发挥性,因此对作者的要求比较高,不仅考察了对单片机的掌握能力更加强调了对单片机扩展的应用。而且在操作的设计上要力求简洁,功能上尽量齐全,显示界面也要出色。所以,电子万年历无论作为竞赛题目还是毕业设计题目都是很有价值。
对于这个实验项目,我们还要有一些其他的基本知识掌握和意义:
(1)在学习了《数字电子技术》和《单片机原理及接口技术》课程后,为了加深对理论知识的理解,学习理论知识在实际中的运用,为了培养动手能力和解决实际问题的经验,了解专用时钟芯片DS1302,并会用DS1302芯片开发时钟模块,应用到其他系统中去。熟悉keil和protues软件调试程序和仿真.
(2)通过实验提高对单片机的认识;
(3)通过实验提高焊接、布局、电路检查能力;
(4)通过实验提高软件调试能力;
(5)进一步熟悉和掌握单片机的结构及工作原理。
(6)通过课程设计,掌握以单片机核心的电路设计的基本方法和技术。
(7)通过实际程序设计和调试,逐步掌握模块化程序设计方法和调试技术。
(8)通过完成一个包括电路设计和程序开发的完整过程,了解开发一单片机应用系统的全过程,为今后从事相应工作打下基础。
五、实训工作:
由于自己是组长,所以在实训期间要多注意一下,实训期间我的主要工作有:
1、看实训要求,计划出自己实训所要用元件,在网上查找资料,同时要求组员也做同样的工作,最后再综合起来。
2、思考仿真原理图,然后画出来(具体I/O口暂时不确定)。
3、在网上找一些程序,然后自己改一些,进行编译。
4、编译无误之后,跟原理图相联系,完成最终的仿真图。
5、进行最后的改写,把程序和仿真原理图确定下来。
6、根据仿真图形,制作出实物图,并进行电路的检查。
六、实训功能:
实训成品暂时还没有成功,所以只能够写出计划实现功能:
1、能够显示公历的年、月、日,还有时、分、秒和温度。
2、能够进行时间的调整。
七、硬件设计:
仿真电路运用的是总线类型的52单片机,单片机部分如上图。
此实训的显示部分用的是数码管,并且是共阴极数码管,其中段选接在P0口,在P0口用了一个上拉电阻,拉高P0口的电压,以使数码管正常工作。
公历的年、月、日的位选接在的是P2口,从左到右分别是P2.7。 P2.6 。P2.5 。P2.4 。P2.3 。P2.2 。P2.1。P2.0。
时间与温度的位选接在P1口上面,从左到右分别,从上到下分别是P1.7。 P1.6 。P1.5 。P1.4 。P1.3 。P1.2 。P1.1。P1.0。
上图为按键设置,最上面一个为设置,下面分别是调高与调低。
DS18B20可以程序设定9~12位的分辨率,精度为±0.5°C。可选更小的封装方式,更宽的电压适用范围。分辨率设定,及用户设定的报警温度存储在EEPROM中,掉电后依然保存。DS18B20的性能是新一代产品中最好的!性能价格比也非常出色!DS1822与DS18B20软件兼容,是DS18B20的简化版本。省略了存储用户定义报警温度、分辨率参数的EEPROM,精度降低为±2°C,适用于对性能要求不高,成本控制严格的应用,是经济型产品。 继"一线总线"的早期产品后,DS1820开辟了温度传感器技术的新概念。DS18B20和DS1822使电压、特性及封装有更多的选择,让我们可以构建适合自己的经济的测温系统。DQ接在P3.7上面。
上图为DS1302时钟部分,上图接有晶振和电容,但实物当中没有电容,所以有些功能不能够实现。
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式。此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。 DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
最后上总图:
八、程序流程:
九、源程序:
Wannianli.c
/**包含头文件**/
#include
#include "config.h"
#include "ds1302.h"
#include "ds18b20.h"
#define duanxuan P0
sbit dian=P3^3;
sbit key1=P3^0;
sbit key2=P3^1;
sbit key3=P3^2; //#include "key.h"
#define uint unsigned int
#define uchar unsigned char
#define seg_time 2
char ReadValue,nian,yue,ri,shi,fen,miao,xingqi,key1n;
uint temperature;
uchar count,count1;
bit mode_flag;
bit set_mode=0;
char set_shi=0,set_fen=0;
uchar
codeSeg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴极数码管显示0到9
uchar time=10;
void keyscan();
void delay_ms(uint z)
{uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--); }
void flash()
{ReadValue = ReadSet1302(0x81); //从秒寄存器读数据
miao=change(ReadValue); //数据转化
ReadValue = ReadSet1302(0x83); //从分寄存器读数据
fen=change(ReadValue) ; //数据转化
ReadValue = ReadSet1302(0x85); //从时寄存器读数据
shi=change(ReadValue); //数据转化
ReadValue = ReadSet1302(0x87); //从日寄存器读数据
ri=change(ReadValue); //数据转化
ReadValue = ReadSet1302(0x89); //从月寄存器读数据
yue=change(ReadValue); //数据转化
ReadValue = ReadSet1302(0x8d); //从年寄存器读数据
nian=change(ReadValue); //数据转化
temperature=ReadTemperature();
nian1;
duanxuan=Seg[2];
delay_ms(seg_time);
nian2;
duanxuan=Seg[0];
delay_ms(seg_time);
nian3;
duanxuan=Seg[nian/10];
delay_ms(seg_time);
nian4;
duanxuan=Seg[nian%10];
delay_ms(seg_time);
yue1;
duanxuan=Seg[yue/10];
delay_ms(seg_time);
yue2;
duanxuan=Seg[yue%10];
delay_ms(seg_time);
ri1;
duanxuan=Seg[ri/10];
delay_ms(seg_time);
ri2;
duanxuan=Seg[ri%10];
delay_ms(seg_time);
shi1;
duanxuan=Seg[shi/10];
delay_ms(seg_time);
shi2;
duanxuan=Seg[shi%10];
delay_ms(seg_time);
fen1;
duanxuan=Seg[fen/10];
delay_ms(seg_time);
fen2;
duanxuan=Seg[fen%10];
delay_ms(seg_time);
miao1;
duanxuan=Seg[miao/10];
delay_ms(seg_time);
miao2;
duanxuan=Seg[miao%10];
delay_ms(seg_time);
wendu1;
duanxuan=Seg[temperature%1000/100];
delay_ms(seg_time);
wendu2;
duanxuan=Seg[temperature%100/10];
delay_ms(seg_time);
}
unsigned char WeekDay20(unsigned char y,unsigned char m,unsigned char d)
{unsigned char week, day;
week = day >> 5;//月星期数
day &= 0x1f;//月天数
if ((m < 3) && (y & 0x03)){//平年
if (m == 2) day--; //平年月天数
week++; //平年月表+1 }
y = y + (y >> 2);//年+年/4
week = (week + y + d + 2) % 7;//(星期=年+年/4+月表+2日)%7
return (week << 5) | day;//返回星期和月天数
}
void flash_set()
{temperature=ReadTemperature();
shi1;
duanxuan=Seg[set_shi/10];
delay_ms(seg_time);
shi2;
duanxuan=Seg[set_shi%10];
delay_ms(seg_time);
fen1;
duanxuan=Seg[set_fen/10];
delay_ms(seg_time);
fen2;
duanxuan=Seg[set_fen%10];
delay_ms(seg_time);
wendu1;
duanxuan=Seg[temperature%1000/100];
delay_ms(seg_time);
wendu2;
duanxuan=Seg[temperature%100/10];
delay_ms(seg_time);}
void INT_Init()
{// IP=0x05; //外部中断0和外部中断1设置为高优先级// IT0=1; //外部中断0为下降沿触发
//IT1=1; //外部中断1为下降沿触发
// EX0=1; //开外部中断0
//EX1=1; //开外部中断1
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
TR0=1;
EA=1;}
void ALL_Init()
{INT_Init();
P0=0xff;
P1=0xff;
P2=0xff;
mode_flag=0;}
/**函数功能:主程序 入口参数: 出口参数:***/
void main(void)
{ALL_Init();
while(1)
{if(set_mode==0)
{flash();}
else
{flash_set();}
keyscan();}}
void keyscan()
{/*key1n: 1:调整闹钟分钟 2:调整闹钟小时 3:调整分钟
4:调整小时 5:退出 */
if(key1==0)//---------------key1为功能键(设置键)
{delay_ms(5);//延时,用于消抖动
if(key1==0)//延时后再次确认按键按下
{while(!key1);
key1n++;
if(key1n==6)
key1n=1;//设置按键共有秒、分、时、返回,4个功能循环
if(key1n<3)
{set_mode=1;}
if(key1n>2)
{set_mode=0;}}}/*-------加键key2----- */
if(key1n!=0&&(key1n!=5))//当key1按下一下。再按一下键才有效(按键次数不等于零)
{if(key2==0) //上调键
{ delay_ms(5);
if(key2==0)
{while(!key2);
switch(key1n)
{case 1:
set_fen++;
if(set_fen==60)
set_fen=0;
break;
case 2:
set_shi++;
if(set_shi==24)
set_shi=0;
break;
case 3:
fen++;
if(fen==60)
fen=0;
WriteSet1302(0x82,((fen/10)<<4|(fen%10)));
break;
case 4:
shi++;
if(shi==24)
shi=0;
WriteSet1302(0x84,((shi/10)<<4|(shi%10)));
break;}}}} /*--------加键key2------- */
if(key1n!=0&&(key1n!=5))//当key1按下以下。再按以下键才有效(按键次数不等于零)
{if(key3==0) //上调键
{delay_ms(5);
if(key3==0)
{while(!key3);
switch(key1n)
{case 1:
set_fen--;
if(set_fen<0)
set_fen=59;
break;
case 2:
set_shi--;
if(set_shi<0)
set_shi=23;
break;
case 3:
fen--;
if(fen<0)
fen=59;
WriteSet1302(0x82,((fen/10)<<4|(fen%10)));
break;
case 4:
shi--;
if(shi<0)
shi=23;
WriteSet1302(0x84,((shi/10)<<4|(shi%10)));
break; }}}}}
config.h
#define nian1 P2=0x7f;P1=0xff
#define nian2 P2=0xbf;P1=0xff
#define nian3 P2=0xdf;P1=0xff
#define nian4 P2=0xef;P1=0xff
#define yue1 P2=0xf7;P1=0xff
#define yue2 P2=0xfb;P1=0xff
#define ri1 P2=0xfd;P1=0xff
#define ri2 P2=0xfe;P1=0xff
#define shi1 P1=0x7f;P2=0xff
#define shi2 P1=0xbf;P2=0xff
#define fen1 P1=0xdf;P2=0xff
#define fen2 P1=0xef;P2=0xff
#define miao1 P1=0xf7;P2=0xff
#define miao2 P1=0xfb;P2=0xff
#define wendu1 P1=0xfd;P2=0xff
#define wendu2 P1=0xfe;P2=0xff
Reg52.h
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99; /* 8052 Extensions */
sfr T2CON = 0xC8;
sfr RCAP2L = 0xCA;
sfr RCAP2H = 0xCB;
sfr TL2 = 0xCC;
sfr TH2 = 0xCD; /* BIT Registers */ /* PSW */
sbit CY = PSW^7;
sbit AC = PSW^6;
sbit F0 = PSW^5;
sbit RS1 = PSW^4;
sbit RS0 = PSW^3;
sbit OV = PSW^2;
sbit P = PSW^0; //8052 only /* TCON */
sbit TF1 = TCON^7;
sbit TR1 = TCON^6;
sbit TF0 = TCON^5;
sbit TR0 = TCON^4;
sbit IE1 = TCON^3;
sbit IT1 = TCON^2;
sbit IE0 = TCON^1;
sbit IT0 = TCON^0; /* IE */
sbit EA = IE^7;
sbit ET2 = IE^5; //8052 only
sbit ES = IE^4;
sbit ET1 = IE^3;
sbit EX1 = IE^2;
sbit ET0 = IE^1;
sbit EX0 = IE^0; /* IP */
sbit PT2 = IP^5;
sbit PS = IP^4;
sbit PT1 = IP^3;
sbit PX1 = IP^2;
sbit PT0 = IP^1;
sbit PX0 = IP^0; /* P3 */
sbit RD = P3^7;
sbit WR = P3^6;
sbit T1 = P3^5;
sbit T0 = P3^4;
sbit INT1 = P3^3;
sbit INT0 = P3^2;
sbit TXD = P3^1;
sbit RXD = P3^0; /* SCON */
sbit SM0 = SCON^7;
sbit SM1 = SCON^6;
sbit SM2 = SCON^5;
sbit REN = SCON^4;
sbit TB8 = SCON^3;
sbit RB8 = SCON^2;
sbit TI = SCON^1;
sbit RI = SCON^0; /* P1 */
sbit T2EX = P1^1; // 8052 only
sbit T2 = P1^0; // 8052 only /* T2CON */
sbit TF2 = T2CON^7;
sbit EXF2 = T2CON^6;
sbit RCLK = T2CON^5;
sbit TCLK = T2CON^4;
sbit EXEN2 = T2CON^3;
sbit TR2 = T2CON^2;
sbit C_T2 = T2CON^1;
sbit CP_RL2 = T2CON^0;
#endif
Ds1302.h
#ifndef uint
#define uint unsigned int
#endif
#ifndef uchar
#define uchar unsigned char
#endif
sbit DATA=P3^6; //位定义1302芯片的接口,数据输出
sbit RST =P3^4; //位定义1302芯片的接口,复位端口
sbit SCLK=P3^5; //位定义1302芯片的接口,时钟输出端口
/**函数功能:延时若干微秒*****/
void delaynus(uchar n)
{ uchar i;
for(i=0;i
void Write1302(uchar dat)
{uchar i;
SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备//
delaynus(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续写8个二进制位数据
{DATA=dat&0x01; //取出dat的第0位数据写入1302// delaynus(2); //稍微等待,使硬件做好准备
SCLK=1; //上升沿写入数据//
delaynus(2); //稍微等待,使硬件做好准备
SCLK=0; //重新拉低SCLK,形成脉冲
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位
}}
/**函数功能:根据命令字,向1302写一个字节数据入口参数:Cmd,储存命令字;dat,储存待写的数据*****/
void WriteSet1302(uchar Cmd,uchar dat)
{
RST=0; //禁止数据传递
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输//
delaynus(2); //稍微等待,使硬件做好准备
Write1302(Cmd); //写入命令字
Write1302(dat); //写数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
}
/****
函数功能:从1302读一个字节数据入口参数:x****/
uchar Read1302(void)
{ uchar i,dat;
// delaynus(2); //稍微等待,使硬件做好准备
for(i=0;i<8;i++) //连续读8个二进制位数据
{dat>>=1;//将dat的各数据位右移1位,因为先读出的是字节的最低位
if(DATA==1) //如果读出的数据是1
dat|=0x80; //将1取出,写在dat的最高位
SCLK=1; //将SCLK置于高电平,为下降沿读出// delaynus(2); //稍微等待
SCLK=0; //拉低SCLK,形成脉冲下降沿//
delaynus(2); //稍微等待 }
return dat; //将读出的数据返回}
/**函数功能:根据命令字,从1302读取一个字节数据入口参数:Cmd***/
uchar ReadSet1302(uchar Cmd)
{uchar dat;
RST=0; //拉低RST
SCLK=0; //确保写数居前SCLK被拉低
RST=1; //启动数据传输
Write1302(Cmd); //写入命令字
dat=Read1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //禁止数据传递
return dat; //将读出的数据返回
}/*函数功能: 1302进行初始化设置***/
void DS1302_Init(void)
{ WriteSet1302(0x8E,0x00);//根据写状态寄存器命令字,写入不保护指令
WriteSet1302(0x8a,7);
/* WriteSet1302(0x80,((58/10)<<4|(58%10)));//根据写秒寄存器命令字,写入秒的初始值
WriteSet1302(0x82,((59/10)<<4|(59%10))); //根据写分寄存器命令字,写入分的初始值
WriteSet1302(0x84,((20/10)<<4|(2%10))); //根据写小时寄存器命令字,写入小时的初始值
WriteSet1302(0x86,((10/10)<<4|(6%10))); //根据写日寄存器命令字,写入日的初始值
WriteSet1302(0x88,((10/10)<<4|(10%10))); //根据写月寄存器命令字,写入月的初始值
WriteSet1302(0x8c,((10/10)<<4|(10%10))); //根据写小时寄存器命令字,写入小时的初始值*/
}
uchar change(uchar temp)
{return (((temp&0x70)>>4)*10 + (temp&0x0F));
}
Ds18b20.h
#ifndef uint
#define uint unsigned int
#endif
#ifndef uchar
#define uchar unsigned char
#endif
sbit DATA_ = P3^7; //DS18B20接入口
void delay1(uint num)
{while(num--) ;}
void Init_DS18B20() //传感器初始化
{uchar x=0;
DATA_ = 1; //DQ复位
delay1(10); //稍做延时
DATA_ = 0; //单片机将DQ拉低
delay1(80); //精确延时 大于 480us //450
DATA_ = 1; //拉高总线
delay1(20);
x=DATA_; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败// delay1(30);}
uchar ReadOneChar()
{uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{DATA_ = 0; // 给脉冲信号
dat>>=1;
DATA_ = 1; // 给脉冲信号
if(DATA_)
dat|=0x80;
delay1(8);}
return dat;} //写一个字节
void WriteOneChar(unsigned char dat)
{uchar i=0;
for (i=8; i>0; i--)
{DATA_ = 0;
DATA_ = dat&0x01;
delay1(10);
DATA_ = 1;
dat>>=1;}
delay1(8);} //读取温度
int ReadTemperature()
{uchar a=0;
uchar b=0;
int t=0;
float tt=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20(); WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar();//低位
b=ReadOneChar();//高位
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
t= tt*10+0.5;
return t;}
十、元件介绍:
ds1302
DS1302是SPI总线驱动方式。它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。
要想与DS1302通信,首先要先了解DS1302的控制字。DS1302的控制字如图
控制字(即地址及命令字节)
控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。
位6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;
位5至位1(A4~A0):指示操作单元的地址;
位0(最低有效位):如为0,表示要进行写操作,为1表示进行读操作。
控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。
ds18b20
DS18B20内部结构主要由四部分组成:64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
(1)DQ为数字信号输入/输出端;
(2)GND为电源地;
(3)VDD为外接供电电源输入端(在寄生电源接线方式时接地)。
DS18B20温度传感器的内部存储器包括一个高速暂存RAM和一个非易失性的可电擦除的EEPRAM,后者存放高温度和低温度触发器TH、TL和结构寄存器。
低五位一直都是"1",TM是测试模式位,用于设置DS18B20在工作模式还是在测试模式。在DS18B20出厂时该位被设置为0,用户不要去改动。R1和R0用来设置分辨率,如下表所示:(DS18B20出厂时被设置为12位)
AT89C52
AT89C52为40 脚双列直插封装的8 位通用微处理器,采用工业标准的C51内核,在内部功能及管脚排布上与通用的8xc52 相同,其主要用于会聚调整时的功能控制。功能包括对会聚主IC 内部寄存器、数据RAM及外部接口等功能部件的初始化,会聚调整控制,会聚测试图控制,红外遥控信号IR的接收解码及与主板CPU通信等。主要管脚有:32个双向I/O口 · 256x8bit内部RAM ,XTAL1(19 脚)和XTAL2(18 脚)为振荡器输入输出端口,外接12MHz 晶振。RST/Vpd(9 脚)为复位输入端口,外接电阻电容组成的复位电路。VCC(40 脚)和VSS(20 脚)为供电端口,分别接+5V电源的正负端。P0~P3 为可编程通用I/O 脚,其功能用途由软件定义,在本设计中,P0 端口(32~39 脚)被定义为N1 功能控制端口,分别与N1的相应功能管脚相连接,13 脚定义为IR输入端,10 脚和11脚定义为I2C总线控制端口,分别连接N1的SDAS(18脚)和SCLS(19脚)端口,12 脚、27 脚及28 脚定义为握手信号功能端口,连接主板CPU 的相应功能端,用于当前制式的检测及会聚调整状态进入的控制功能。
P0 口
P0 口是一组8 位漏极开路型双向I/O 口, 也即地址/数据总线复用口。作为输出口用时,每位能吸收电流的
方式驱动8 个TTL逻辑门电路,对端口P0 写“1”时,可作为高阻抗输入端用。
在访问外部数据存储器或程序存储器时,这组口线分时转换地址(低8 位)和数据总线复用,在访问期间激活内部上拉电阻。
在Flash 编程时,P0 口接收指令字节,而在程序校验时,输出指令字节,校验时,要求外接上拉电阻。
P1 口
P1 是一个带内部上拉电阻的8 位双向I/O 口, P1 的输出缓冲级可驱动(吸收或输出电流)4 个TTL 逻辑
门电路。对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口。作输入口使用时,因为内部存在上拉
电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。
与AT89C51 不同之处是,P1.0 和P1.1 还可分别作为定时/计数器2 的外部计数输入(P1.0/T2)和输入(P1.1/T2EX),
参见表1。
Flash 编程和程序校验期间,P1 接收低8 位地址。
表.P1.0和P1.1的第二功能
P2 口
P2 是一个带有内部上拉电阻的8 位双向I/O 口,P2 的输出缓冲级可驱动(吸收或输出电流)4 个TTL 逻辑
门电路。对端口P2 写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口,作输入口使用时,因为内部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流(IIL)。
在访问外部程序存储器或16 位地址的外部数据存储器(例如执行MOVX @DPTR 指令)时,P2 口送出高8 位地址数据。在访问8 位地址的外部数据存储器(如执行MOVX @RI 指令)时,P2 口输出P2 锁存器的内容。
Flash 编程或校验时,P2亦接收高位地址和一些控制信号。
P3 口
P3 口是一组带有内部上拉电阻的8 位双向I/O 口。P3 口输出缓冲级可驱动(吸收或输出电流)4 个TTL 逻
辑门电路。对P3 口写入“1”时,它们被内部上拉电阻拉高并可作为输入端口。此时,被外部拉低的P3 口将用上拉电阻输出电流(IIL)。
P3 口除了作为一般的I/O 口线外,更重要的用途是它的第二功能
P3 口还接收一些用于Flash 闪速存储器编程和程序校验的控制信号。
十一、实训总结:
在整个设计过程中,充分发挥了个人的主观能动性,自主学习,学到了许多没学到的知识。完成情况实在不好,并没有达到预期的目的。在最初的设计中,通过查阅资料学习,完成了最初的设想。在电路焊接时虽然没什么大问题,但从中也知道了焊接在整个作品中的重要性,电路工程量大,不能心急,一个个慢慢来不能急于求成,反而达到事半功倍的效果。在焊接电路的过程中,遇到了很多的困难,最主要的是犯了一个小错误,但是又很难发现,那就是在焊接电源降压部分时就出现了短路,找了很久都没有发现错误,最后经过排查,才知道是开关处的电源指示灯导通了,导致了短路。这导致没有起到降压的作用。经过多次的反复测试与分析,可以对电路的原理及功能更加熟悉,同时提高了设计能力与及对电路的分析能力。
对电路的设计、布局要先有一个好的构思,才显得电路板美观、大方。程序编写中,由于思路不清晰,开始时遇到了很多的问题,最后通过在网上查找,终于找到了相似的程序,但是想要改还是很麻烦,因为程序太多了,最后静下心来才得以解决部分。但是任然在软件的编程方面得到更到的提高,对编程能力得到加强.同时对所学的知识得到很大的提高与巩固。
在此次设计中,知道了做凡事要有一颗平常的心,不要想着走捷径,一步一脚印,也练就了我的耐心。此次设计过程中学到了很多很多东西,这是最重要的。总之,制作电子万年历使我的实践能力得到了全方位的提升。