1、 本科课程设计 课程名称: 单片机原理与接口技术 课设项目: 电子万年历课程设计 课设地点: 专业班级: 学号 学生姓名: 同组人: 指导教师: 2012年 05月30 日 设计题目: 电子万年历 设计任务与要求: 1、显示年月日时分秒及星期信息 2、具有可
2、调整日期和时间功能 3、增加闰年计算功能 4、增加了显示温度的模块 设计方案: 由于我是在网上购买的现成的开发板来学习和使用的,故在方案的选择上也只能限于开发板设计好的电路和芯片. 系统分为主控模块、时钟电路模块、温度检测模块,按键扫描模块,LCD显示模块,电源电路、复位电路、晶振电路等模块。主控模块采用AT89C52单片机,按键模块用四个按键,用于调整时间,显示模块采用LCD1602,时钟电路模块采用DS1302时钟芯片实现对时间、日期的操作,温度模块使用18B20实现度温度的操作。 STC89C52,ATMEL的51系列单片机,价格便宜,在国内使用者非常多。支持串口下载,使用
3、非常方便,且具有很大的价格优势。缺点是仅支持串口下载,不支持在线下载,使用中会有些不方便。 1.显示模块: 方案一: 普通的共阴LED数码管,用点阵LED实现文字的显示. 方案二: LCD1602液晶显示屏. LED数码管价格适中,对于数字显示效果较好,而且使用单片机的端口也较少; LCD1602液晶显示屏,显示功能强大,可以显示大量文字、图形,显示多样性,清晰可见,价格相对LED数码管来说要昂贵些,但是基于本设计显示的东西较多,若采用LED数码管的话,所需数码管较多,而且不利于控制,因此选择LCD1602作为显示模块.故选择方案二. 2.时钟电路模块: 方案一:用单片机的定时器
4、产生1S的时基信号,然后用程序来实现时钟的时、分、秒计时,同时用程序来产生年、月、日。该方案优点是减少使用外设芯片;缺点是用单片机模拟时钟,使编程量增大,且用定时器产生时基信号,精度不高。 方案二:DS1302是一款高性能的实时时钟芯片,以计时准确、接口简单、使用方便、工作电压范围宽和低功耗等优点,得到广泛的应用,实时时钟有秒、分、时、星期、日、月和年,月小于31天时可以自动调整,并具有闰年补偿功能,而且在掉电时能够在外部纽扣电池的供电下继续工作。单片机有定时器的功能,但时间误差较大,且需要编写时钟程序. 因此采用DS1302方案二作为时钟电路。 3.温度模块: 直接采用常用的18B2
5、0. 系统框图: 液晶显示(LED)1602 单片 AT89C52 时钟芯片DS1302 温度传感器18B20 单元电路设计: 单片机中央处理系统的方案设计,选用AT89C52单片机作为中央处理器,如图所示。该单片机除了拥有MCS-51系列单片机的所有优点外,内部还具有8K的在系统可编程FLASH存储器,低功耗的空闲和掉电模式,极大的降低了电路的功耗,还包含了定时器、程序存储器、数据存储器等硬件,其硬件能符合整个控制系统的要求,不需要外接其他存储器芯片和定时器件,方便地构成一个最小系统。整个系统结构紧凑,抗干扰能力强,性价比高。 2、时钟振
6、荡电路 用主振11.0592 MHZ的晶振,使用内部晶振接法并上俩个30PF的电容,如图所示. 3、复位电路 复位电路由电阻和极性电容组成,通过高电平使单片机复位,在时钟电路开始工作后,当高电平的时间超过大约2us时,即可实现复位。此复位电路为上电复位,较为简单。若改进可以添加手动复位的功能,上电复位发生在开机加电时,由系统自动完成,手动复位通过一个按键来实现,在程序运行时,若遇到死机,死循环等情况,通过手动复位就可以实现重新启动的操作。手动按钮复位需要人为在复位输入端RST上加入高电平。一般采用的办法是在RST端和正电源Vcc之间接一个按钮和一个电阻。 4、DS1302时钟
7、电路 时钟电路主要由时钟芯片DS1302、备用电池、晶振等几部分组成,如图(6)所示。DS1302采用3线串行接口,占用引脚少,内部集成了可编程日历时钟,用户可以根据需要通过单片机的控制来自行设置,支持双电源供电,可以使用外部主电源和备用电源,备份电源能够使时钟芯片继续工作。 DS1302管脚图 DS1302时钟电路 DS1302各引脚的功能为: 8: Vcc1:备用电池端; 1: Vcc2:5V电源。当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2< Vcc1时,由Vcc1向DS1302供电;
8、 7: SCLK:串行时钟,输入; 6: I/O:数据输入输出口; 5: CE/RST:复位脚; 2、3: X1、X2 是外接晶振脚 (32.768KHZ的晶振); 4: 地(GND)。 DS1302有关日历、时间的寄存器: DS1302有关日历、时间的寄存器 1、秒寄存器(81h、80h)的位7定义为时钟暂停标志(CH)。当初始上电时该位置为1,时钟振荡器停止,DS1302处于低功耗状态;只有将秒寄器的该位置改写为0时,时钟才能开始运行。 2、小时寄存器(85h、84h)的位7用于定义DS1302是运行于12小时模式还是24小时模式。当为高时,选择12小时模
9、式。在12小时模式时,位5是 ,当为1时,表示PM。在24小时模式时,位5是第二个10小时位 3、控制寄存器(8Fh、8Eh)的位7是写保护位(WP),其它7位均置为0。在对任何的时钟和RAM的写操作之前,WP位必须为0。当WP位为1时,写保护位防止对任一寄存器的写操作。也就是说在电路上电的初始态WP是1,这时是不能改写上面任何一个时间寄存器的,只有首先将WP改写为0,才能进行其它寄存器的写操作。 DS1302读写时序 DS1302是SPI总线驱动方式。它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。DS1302的控制字如下图: DS1302的控制字图 控制字的最高有效
10、位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。 位6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据; 位5至位1(A4~A0):指示操作单元的地址; 位0(最低有效位):如为0,表示要进行写操作,为1表示进行读操作。 读数据: 读数据时在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据是从最低位到最高位。 写数据: 控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入也是从最低位(0位)开始。 5:温度传感器18B20 通过18B20进行读数据,
11、将读出来的数据进行进制转换,转换后送到 DS18B20是单总线的数字温度传感器。其与单片机的接口只需要一根数据线即可。当然连线简单意味着软件处理上可能要麻烦一点。下面来看看它的优点 看看它的靓照。外形和我们常用的三极管没有什么两样哦。 DS18B20的内部存储器分为以下几部分 ROM:存放该器件的编码。前8位为单线系列的编码(DS18B20的编码是19H)后面48位为芯片的唯一序列号。在出场的时候就已经设置好,用户无法更改。最后8位是以上56位的CRC码。 DS18B20的温度存放如上图所示。其中S位符号位。当温度值为负值时,S = 1 ,反之则S = 0 。我们把得到的温度
12、数据乘上对应的分辨率即可以得到转换后的温度值。 DS18B20的通讯协议: 在对DS18B20进行读写编程时,必须严格保证读写的时序。否则将无法读取测温结果。根据DS18B20的通讯协议,主机控制DS18B20完成温度转换必须经过3个步骤:每一次读写之前都要对DS18B20进行复位,复位成功后发送一条ROM指令,最后发送RAM指令。这样才能对DS18B20进行预定的操作。 复位要求主机将数据线下拉500us,然后释放,DS18B20收到信号后等待16~160us然后发出60~240us的存在低脉冲,主机收到此信号表示复位成功。 上图即DS18B20的复位时序图。 下面
13、是读操作的时序图 这是写操作的时序图 6.按键电路 按键电路由四个轻触开关组成。按键用来调整时间,其一端直接接到单片机的端口,另一端接地,当按下按键时,相应的端口变为低电平,通过一个与门只要这四个按键有一个按下就会在P3.2检测到一低电平就触发外部中断0进入按键调节程序中,通过与个各键相连的端口P3.4_P3.7可以判断是哪个键按下,从而作相应的操作。用软件设计扫描程序。 7.实现功能: K1按键进入设定状态 按K2,依次进入闹钟功能是否启用,闹钟时,分秒,年,月,日及时间时,分,秒的设置,直到退出设置状态 按K3,调整是否起用闹钟和调节闹钟时,分,秒,年,月,日
14、时间的时,分,秒的数字 LCD第二排中间显示小喇叭,表示启用闹钟功能,无则禁止闹钟功能(可在调整状态进行设置) 正常状态,LCD上排最前面显示自定义字符,LCD下排最前面闪动"RICHMCU" 设置状态,LCD上排最前面显示"P",下排最前面在设置闹钟时间时显示"alarm:",其它状态显示"time" 8.程序流程图: 1主程序:首先初始化定时器、LCD1602及DS1302,然后就开始查询按键,有键按下则开始调整时间和日期,若没有按下,则执行下面的时间、日期的显示,最后依次循环这些相同的操作: 18b20子程序: 复位初始化 向1820写数据,跳过rom,读数据
15、 提取百、十、个、小数点后一位 读到的数转换为整型 Ds1302子程序: 初始化 Flag=1? Dnum=? 1:小时加一 2:分加一 3:秒加一4:年加一 5:月加一 6:日加一 7:星期加一 1:小时减一 2:分减一 3:秒减一4:年减一 5:月减一 6:日减一 7:星期减一 计算要显示的数据 送到1602显示 Dnum=? 2、软件设计 软
16、件总设计:主程序首先对系统环境初始化,设置定时器T0工作模式为16位定时/计数器模式,置位总中断允许位EA,并对键盘端口置位,再对LCD1602初始化,DS1302初始化。接着扫描键盘,在键盘程序里面是对时间、日期,闹钟的调整,温度的选择,最下面是时间的显示。 例如: 闰年的计算 bit leap_year() { bit leap; if((year%4==0&&year%100!=0)||year%400==0)//闰年的条件 leap=1; else leap=0; return leap; } 仿真结果分析: 电子万年历硬件电路图及仿真
17、如图所示,系统由AT89C52单片机,按键扫描电路、显示电路、时钟电路、晶振电路、复位电路及电源指示电路。 仿真正确显示了时间,在LCD1602中正确显示了当前日期、时间,按K1按键进入设定状态,按K2,依次进入闹钟功能是否启用,闹钟时,分秒,年,月,日及时间时,分,秒的设置,直到退出设置状态,按K3,调整是否起用闹钟和调节闹钟时,分,秒,年,月,日,时间的时,分,秒的数字, 按K4,选择温度的显示.LCD第二排中间显示小喇叭,表示启用闹钟功能,无则禁止闹钟功能(可在调整状态进行设置),正常状态,LCD上排最前面显示自定义字符,LCD下排最前面闪动"TIME",设置状态,LCD上排最前面显示
18、"P",下排最前面在设置闹钟时间时显示"alarm:",其它状态显示"time"仿真正确显示了时间和日期,符合设计的要求。
增加温度的显示按下K4时出现温度的显示界面,上排显示”wendu made byFMZ”,下排显示温度.
仿真图如下所示:
参考文献:
单片机原理与接口技术(李晓林.第二版)
RZ-51V20开发板论坛
实物图:
闹钟设置
时间显示
平闰年判断,修改天数
温度显示
整体实物图
实验源程序:
#include
19、 unsigned char code digit[11]={"0123456789-"}; //定义字符数组显示数字 unsigned char code Str[]={"wendu made byFMZ"}; //说明显示的是温度 unsigned char code Error[]={" DS18B20 ERROR"}; //说明没有检测到DS18B20 unsigned char code Error1[]={" PLEASE CHECK"}; //说明没有检测到DS18B20 unsigned char code Temp[]={"wendu
20、 made byFMZ:"}; unsigned char code Cent[]={"Cent"}; //温度单位 unsigned char flag,tltemp; unsigned char code dis_week[]={"SUN,MON,TUE,WED,THU,FRI,SAT"}; unsigned char code para_month[13]={0,0,3,3,6,1,4,6,2,5,0,3,5}; //星期月参变数 unsigned char data dis_buf1[16]; //lcd上排显示缓冲区
21、unsigned char data dis_buf2[16]; //lcd下排显示缓冲区 unsigned char data year,month,date,week;//年、月、日、星期 unsigned char data armhour,armmin,armsec;//闹钟时、分、秒 unsigned char data hour,min,sec,sec100; //时、分、秒、百分之一秒 unsigned char data flag,vkey,skey;//设置状态计数标志、按键先前值、按键当前值 bit alarm; //标识是否启用闹钟,1--启用,0--关闭
22、sbit rs = P2^0; //LCD数据/命令选择端(H/L) sbit rw = P2^1; //LCD读/写选择端(H/L) sbit ep = P2^2; //LCD使能控制 sbit PRE = P3^3; //调整键(AN3) sbit SET = P3^4; //调整键(AN4) sbit SPK = P3^6; void delayms(unsigned char ms); //延时程序 bit lcd_busy(); //测试LCD忙碌状态程序 void lcd_wcmd(char cmd); //写入指令到L
23、CD程序 void lcd_wdat(char dat); //写入数据到LCD程序 void lcd_pos(char pos); //LCD数据指针位置程序 void lcd_init(); //LCD初始化设定程序 void pro_timedate(); //时间日期处理程序 void pro_display(); //显示处理程序 void pro_key(); //按键处理程序 void time_alarm(); //定时报警功能(闹钟) unsigned char scan_key(); //按键扫描程序 unsigned
24、 char week_proc(); //星期自动计算与显示函数 bit leap_year(); //判断是否为闰年 void lcd_sef_chr(); //LCD自定义字符程序 void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s); // 延时程序 void delay(unsigned char ms) { while(ms--) { unsigned char i; fo
25、r(i = 0; i< 250; i++) { _nop_(); //执行一条_nop_()指令为一个机器周期 _nop_(); _nop_(); _nop_(); } } } void delay1ms() { unsigned char i,j; for(i=0;i<4;i++) for(j=0;j<33;j++) } //n毫秒 void delaynms(unsigned char n) { unsigned char i; for(i
26、0;i 27、//当lcd_busy为1时,再次检测LCD忙碌状态,lcd-busy为0时,开始写指令
rs = 0;
rw = 0;
ep = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
//写入数据到LCD
void lcd_wdat(char dat)
{
while(lcd_busy()); rs = 1;
rw = 0 28、
ep = 0;
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
//LCD数据指针位置程序
void lcd_pos(char pos)
{
lcd_wcmd(pos|0x80); //数据指针=80+地址码(00H~27H,40H~67H)
}
void lcd_sef_chr()
{ //第一个自定义字符
lcd_wcmd(0x40); //"01 000 000" 29、 第1行地址 (D7D6为地址设定命令形式D5D4D3为字符存放位置(0--7),D2D1D0为字符行地址(0--7))
lcd_wdat(0x1f); //"XXX 11111" 第1行数据(D7D6D5为XXX,表示为任意数(一般用000),D4D3D2D1D0为字符行数据(1-点亮,0-熄灭)
lcd_wcmd(0x41); //"01 000 001" 第2行地址
lcd_wdat(0x11); //"XXX 10001" 第2行数据
lcd_wcmd(0x42); //"01 000 010" 第3行地址
lcd_wdat(0x15); //"X 30、XX 10101" 第3行数据
lcd_wcmd(0x43); //"01 000 011" 第4行地址
lcd_wdat(0x11); //"XXX 10001" 第4行数据
lcd_wcmd(0x44); //"01 000 100" 第5行地址
lcd_wdat(0x1f); //"XXX 11111" 第5行数据
lcd_wcmd(0x45); //"01 000 101" 第6行地址
lcd_wdat(0x0a); //"XXX 01010" 第6行数据
lcd_wcmd(0x46); //"01 000 110" 第7行地址
31、lcd_wdat(0x1f); //"XXX 11111" 第7行数据
lcd_wcmd(0x47); //"01 000 111" 第8行地址
lcd_wdat(0x00); //"XXX 00000" 第8行数据
//第二个自定义字符
lcd_wcmd(0x48); //"01 001 000" 第1行地址
lcd_wdat(0x01); //"XXX 00001" 第1行数据
lcd_wcmd(0x49); //"01 001 001" 第2行地址
lcd_wdat(0x1b); //"XXX 11011" 第2行数据
lcd_wcmd( 32、0x4a); //"01 001 010" 第3行地址
lcd_wdat(0x1d); //"XXX 11101" 第3行数据
lcd_wcmd(0x4b); //"01 001 011" 第4行地址
lcd_wdat(0x19); //"XXX 11001" 第4行数据
lcd_wcmd(0x4c); //"01 001 100" 第5行地址
lcd_wdat(0x1d); //"XXX 11101" 第5行数据
lcd_wcmd(0x4d); //"01 001 101" 第6行地址
lcd_wdat(0x1b); //"XXX 1101 33、1" 第6行数据
lcd_wcmd(0x4e); //"01 001 110" 第7行地址
lcd_wdat(0x01); //"XXX 00001" 第7行数据
lcd_wcmd(0x4f); //"01 001 111" 第8行地址
lcd_wdat(0x00); //"XXX 00000" 第8行数据
}
//LCD初始化设定
void lcd_init()
{
lcd_wcmd(0x38); //设置LCD为16X2显示,5X7点阵,八位数据借口
delay(1);
lcd_wcmd(0x0c); //LCD开显示及光标设置(光标不闪 34、烁,不显示"-")
delay(1);
lcd_wcmd(0x06); //LCD显示光标移动设置(光标地址指针加1,整屏显示不移动)
delay(1);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(1);
}
//闰年的计算
bit leap_year()
{
bit leap;
if((year%4==0&&year%100!=0)||year%400==0)//闰年的条件
leap=1;
else
leap=0;
return leap;
}
//星期的自动运算和处理
unsigned cha 35、r week_proc()
{ unsigned char num_leap;
unsigned char c;
num_leap=year/4-year/100+year/400;//自00年起到year所经历的闰年数
if( leap_year()&& month<=2 ) //既是闰年且是1月和2月
c=5;
else
c=6;
week=(year+para_month[month]+date+num_leap+c)%7;//计算对应的星期
return week;
}
//更新显示缓冲区
void update_disbuf(unsig 36、ned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s)
{ dis_buf1[0]=t1; //
dis_buf1[1]=0x20; //空格
dis_buf1[2]=50; //'2'
dis_buf1[3]=48; //'0'
dis_buf1[4]=year/10+48;
dis_buf1[5]=year%10+48;
dis_buf1[6]=0x2d;
dis_buf1[7]=month/ 37、10+48;
dis_buf1[8]=month%10+48;
dis_buf1[9]=0x2d; //'-'
dis_buf1[10]=date/10+48;
dis_buf1[11]=date%10+48;
dis_buf1[12]=0x20;
dis_buf1[13]=dis_week[4*week];
dis_buf1[14]=dis_week[4*week+1];
dis_buf1[15]=dis_week[4*week+2];
dis_buf2[0]=t2[0];
dis_buf2[1]=t2[1];
dis_buf2[2]=t2[ 38、2];
dis_buf2[3]=t2[3];
dis_buf2[4]=t2[4];
dis_buf2[5]=t2[5];
dis_buf2[6]=t2[6]; //空格
if (alarm)
dis_buf2[7]=0x01; //alarm=1,显示闹钟启用标致(第二个自定义字符)
else
dis_buf2[7]=0x20; //alarm=0,不显示闹钟启用标致
dis_buf2[8]=dis_h/10+48;
dis_buf2[9]=dis_h%10+48;
dis_buf2[10]=0x3a; //':'
dis_bu 39、f2[11]=dis_m/10+48;
dis_buf2[12]=dis_m%10+48;
dis_buf2[13]=0x3a;
dis_buf2[14]=dis_s/10+48;
dis_buf2[15]=dis_s%10+48;
}
//时间和日期处理程序
void pro_timedate()
{
sec++;
if(sec > 59)
{sec = 0;
min++;
if(min>59)
{min=0;
hour++;
if(hour>23)
{hour=0;
date++;
40、 if (month==1||month==3||month==5||month==7||month==8||month==10||month==12)
if (date>31) {date=1;month++;} //大月31天
if (month==4||month==6||month==9||month==11)
if (date>30) {date=1;month++;} //小月30天
if (month==2)
{if( leap_year()) {if (date> 41、29) {date=1;month++;}}
else
{if (date>28) {date=1;month++;}} }
if (month>12) {month=1;year++;}
if (year>99) year=0;
}
}
}
week_proc();
if (sec==armsec && min==armmin && hour==armhour)
{if (alarm)
TR1=1; //闹钟启用时,报警时间到,启动Timer1
}
}
/ 42、/显示处理程序
void pro_display()
{ unsigned char i;
lcd_pos(0x00);
for (i=0;i<=15;i++)
{lcd_wdat(dis_buf1[i]);}
lcd_pos(0x40);
for (i=0;i<=15;i++)
{lcd_wdat(dis_buf2[i]);}
}
//Timer0中断处理程序,秒的产生
void timer0() interrupt 1
{
TH0=0xD8;
TL0=0xF0;
sec100++;
if(sec100 >= 100) //1秒时间 ( 43、100*10ms=1000ms=1s)
{sec100 = 0;
pro_timedate();//调用时间和日期处理程序
}
if (sec&0x01)
update_disbuf(0x00," ",hour,min,sec);
else
update_disbuf(0x00,"FMZTIME",hour,min,sec);
pro_display(); //调用显示处理函数
}
//按键扫描程序
unsigned char scan_key()
{
skey=0x00; // 44、给变量vkey置初值
skey|=PRE; //读取PRE键的状态
skey=skey<<1; //将PRE键的状态存于skey的B1位
skey|=SET; //读取SET键的状态,并存于skey的B0位
return skey; //返回skey的键值(即PRE,SET的状态)
}
//外部中断INT0中断处理程序
void int0() interrupt 0
{
TR0=0; //禁止Timer0
IE=0; //禁止中断
lcd_wcmd(0x0e); 45、 //显示光标"_",整个光标不闪烁
alarm=1;
update_disbuf(0x50,"alarm:",armhour,armmin,armsec);
pro_display(); //调用显示处理程序
lcd_pos(0x47); //使光标位于第一个调整项下
flag=0;
vkey=0x03;
while(flag^0x0a)
{skey = scan_key(); //扫描按键状态
if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行 46、循环体
{ delay(10); //去按键抖动
skey = scan_key(); //转回扫描按键状态
if (skey^vkey) //若skey与vkey相同,跳出循环,相异执行循环体
{ vkey=skey; //将skey的值付给vkey
if (skey==0x01) //PRE键按下
{ flag++; //调整标志位加1
switch (flag) //将光标置于相应调整位置
{
case 1: 47、 lcd_pos(0x49);break; //
case 2: lcd_pos(0x4c);break;
case 3: lcd_pos(0x4f);break;
case 4: update_disbuf(0x50,"time: ",hour,min,sec);
pro_display();
lcd_pos(0x05);break;
case 5: lcd_pos(0x08);break;
case 6: 48、 lcd_pos(0x0b);break;
case 7: lcd_pos(0x49);break; //
case 8: lcd_pos(0x4c);break;
case 9: lcd_pos(0x4f);break;
default:break;
}
}
if (skey==0x02) //SET键按下
{ pro_key(); //转设置按键处理程序
}
49、 if (skey==0x03)
{ wendu()
}
}
}
}
lcd_wcmd(0x0c);
lcd_wcmd(0x01); //清除LCD的显示内容
IE=0x8f; //CPU开中断,INT0,INT1,开中断
TR0=1; //Timer0启动
}
// DS18B20的操作程序
sbit DQ=P3^3;
unsigned char time; //设置全局变量,专门用于严格延时
// 函数功能:将DS18B20传感器初始化,读取应答信号
//出口参数:flag
bit Ini






