单片机C语言案例教程习题解答
单片机C语言案例教程习题解答
习题1
1.在图1-3中,若MCU的P0.0和P
2.0两引脚均为低电平,则四位数码管上有何显示。
解:由图1-3可知,P0.0引脚为低电平,将使四位数码管的a笔划为低电平,P2.0为低电平,则使Q3导通,即数码管千位管的8个发光二极管正极为高电平,从而使千位管显示其a笔划。
2.设有定义“sbit qw=P2^0;”,和赋值语句“qw=0;P0=0Xfe”,则将如何影响MCU的输
出引脚?
解:qw=0,,就是使P2.0为低电平,则使Q3导通,即数码管千位管的8个发光二极管正极为高电平,P0=0xfe,就是使P0.0为低电平,P0.1~P0.7为高电平。从而使千位管显示其a笔划。
3.画出案例6源程序的函数架构及函数调用路线图。
解:案例6源程序的函数架构及函数调用路线图如下:
4.将案例6源程序中Delay函数的for循环之式子2“i<500”分别改为“i<5000”和
“i<50000”后重新编译和下载运行,对比循环终值从500变成5000、再从5000变成50000对显示效果的影响。
解:先在数码管的千位管上显示8,其余各管无显示;再在百位管上显示0,其余各管无显示;又在十位管上显示5,其余各管无显示;再在个位管上显示1,其余各管无显示;
5.写出图1-3中,数码管在单片机学习板中的电路连接要点。
解:四位数码管的8只笔段电极从a到小数点被依次接于P0.0到P0.7上,从左至右的四只位置电极被接在受控于P2.0至P2.3的Q3至Q6的集电极回路.
6.写出图1-3中,DS1302在单片机学习板中的电路连接要点。
解: DS1302的时钟线SCLK与8051的P2.7相接,数据线DATA与P2.6相接,复位线RST 与P2.5相接.
7.写出图1-3中,AT24C02在单片机学习板中的电路连接要点。
解:AT24C02的串行时钟线SCL与8051的P3.6相接,串行数据线与P2.7所接,A T24C02的写保护脚WP接地(允许写入)。
习题2
1 设有如下定义:
int a;
crar b;
unsigned int c;
unsigned char d;
则a称为什么变量?它表示数的起止范围是什么?b哪?c哪?d哪?
解:a称为整型号变量,它表示的数的起止范围是-32768~32767;b称为字符型变量,所表示数的起止范围是-128~127;c称为无符号整型变量,所表示数的起止范围是0~65535;d 称为无符号字符型变量,所表示数的起止范围是0~225。
2 试说明语句“a+1;”与语句“a++”的区别。
解:“a+1”表示变量a与1的和,“a++”表示用变量a与1的和对变量a赋值;前者的a没有被赋值,后者的a被赋值。
3 写出if语句的一般形式、画出if语句的流程图,说明if语句的执行规则。
解:if语句的一般形式:
if(表达式)
语句
if语句的流程图
执行规则:首先对表达式进行判断,如果计算结果为“真”,那么执行“语句”,否则跳过“语句”。
4 写出if-else语句的一般形式、画出if-else语句的流程图,说明if-else语句的执行规则。
解:if?else语句的一般形式如下:
if(表达式)
语句1
else
语句2
if?else语句的流程图
其执行规则:首先计算表达式的值,如果为真,则执行语句1,否则执行语句2。
5 写出不带break的switch语句的一般形式,画出其流程图,说明其执行规则。
解:switch语句的一般形式如下:
switch (表达式)
{
case 常量表达式1: 语句1
case 常量表达式2: 语句2
case 常量表达式n: 语句n
default:语句n+1
}
其中不带break的switch结构流程图如右图。
不带break的switch语句的执行过程是:
首先计算小括号中的整型表达式的值,并以此寻找所匹配的常量表达式,匹配的常量表达式若是常量表达式x,流程就从常量表达式x进入switch结构,若没有一个能匹配的,流程就从default处进入switch结构,只要进入后,就从进入处就执行完到“}”为止的所有语句。
6写出带break的switch语句的一般形式,画出其流程图,说明其执行规则。
解:带break的switch语句的一般形式:
switch (表达式)
{
case 常量表达式1: 语句1
break;
case 常量表达式2: 语句2
break;
case 常量表达式n: 语句n
break;
default:语句n+1
}
带break的switch结构流程图如右图
带break的switch语句的执行过程是:
首先计算小括号中的整型表达式的值,并以此寻找所匹配的常量表达式,匹配的常量表达式若是常量表达式x,流程就从常量表达式x进入switch结构,若没有一个能匹配的,流程就从default处进入switch结构,进入switch结构后,若遇上break语句,流程就从该break语句上跳出switch结构;否则,就从进入处就执行完到“}”为止的所有语句,。
7 写出for语句的一般形式,画出其流程图,说明其执行规则。
解:for 语句的一般形式:
for(表达式1;表达式2;表达式3) {
语句组 }
其中,”for(表达式1;表达式2;表达式3)”可称为循环头,下面大括号所界定范围称为循环体。
for 语句的流程图如右图
它的执行规则如下:
A :先计算表达式1,再转
B ;
B :计算表达式2,若其值为真(1),则转
C ,若其值为假(0)则转E ; C :执行for 下面大括号中的语句组,执行完后转
D ;
D :计算表达式3,结束本次循环,转回B 开始下一次循环;
E :结束循环。流程转出整个for
循环结构,也就是去执行for 循环结构后面的第一条语句。 8 写出while 语句的一般形式,画出其流程图,说明其执行规则。 解:while 语句的一般形式如下:
while(表达式) {
语句组 }
其流程图如下
执行规则如下:
先计算表达式,若表达式计算不为0,就执行一次循环体语句组,然后返回再次计算表达式。如此重复,直到表达式的值计算为0时,流程转出循环结构。另外,当且仅当大括号括住的语句组只是一个语句时,大括号也可省略
9 写出do-while语句的一般形式,画出其流程图,说明其执行规则。
解:do…while语句的一般形式:
do
{
语句组
}while(表达式);
其流程图如图2-10所示。
其执行规则是:首先执行一次循环体语句,此后计算表达式的值;若表达式为1,就又返回去执行循环体语句;再计算表达式,若…;直到计算的表达式的值为0,流程就退出整个do while结构。
还要注意的是,在do-while语句中,最后的”while(表达式)”后面的那一分号’:”不可少.
10 写出一维数组定义的一般形式。
解:一维数组定义的一般形式是:
类型说明符数组名[常量表达式];
11写出二维数组定义的一般形式。
解:二维数组定义的一般形式:
类型说明符数组名[常量表达式1][常量表达式2];
12 写出无参数函数定义的一般形式。
解:无参数函数定义的一般形式为:
类型标识符函数名()
{
函数体语句
}
13 写出有两个参数的函数定义的一般形式。
解:有两个参数函数定义的一般形式如下:
类型标识符函数名(类型标识符变量名1,类型标识符变量名2)
{
函数体语句
}
14 在什么情况下函数定义时的类型说明符可以缺省?
解:当函数的返回值类型为整型或字符型时,函数定义的类型说明符可以缺省。
15 何谓局部变量?局部变量有何特点?
解:在函数内部定义的变量叫做局部变量,局部变量只能在定义它的函数内有效,因此,在不同的函数中,可以定义同名的局部变量。
16 何谓全局变量?全局变量有何特点?
解:在函数外部定义的变量叫做全局变量,全局变量在从其定义位置起,到整个程序结束处有效。在一个函数内,若有与全局变量同名的局部变量,则在该函数内,
全局变量不起作用。
习题3
1上机编程,把案例7沿顺时针方向的跑马灯,改为逆时针方向的跑马灯。
解:这只需调整Disp_led函数内部各程序段的顺序即可,即把该函数内的第一场和第四场的顺序保持不变,把第二场程序段与第六场程序段位置交换、第三场程序段与第五场程序段交换即可。
2上机编程,把案例8沿顺时针方向的巡逻灯,改为逆时针方向的巡逻灯。
解:同上题,这也只需调整Disp_led函数内部各程序段的顺序即可,即把该函数内的第一场和第七场的顺序保持不变,把第二场程序段与第十二场程序段位置交换、第三场程序段与第十一场程序段交换,第四场程序段与第十场程序段交换,第五场程序段与第九场程序段交换,第六场程序段与第八场程序段交换即可。
3上机编程,把案例9向右移动的流水灯,改为向左移动的流水灯。
解:这也只需调整Disp_led函数内部各程序段的顺序即可,即把该函数内把第一场程序段与第八场程序段位置交换、第二场程序段与第七场程序段交换,第三场程
序段与第六场程序段交换,第四场程序段与第五场程序段交换即可。
4上机编程,把案例10效果图中的第四幕改为第一幕,第三幕改为第二幕,第二幕改为第三幕,第一幕改为第四幕。
解:只修改各if语句小括号中的表达式,即把原来的“a==1”改为“a==4”,“a==2”改为“a==3”,“a==3”改为“a==2”,“a==4”改为“a==1”即可。
5 上机编程,把案例12中的倒数数显示,改为顺数数显示。
解:把主函数main修改如下:
main()
{
int n,m;
n=0;
while(1)
{
if(n==10000)
n=0;
for(m=1;m<=20;m++)
Disp_led(n);
n++;
}
}
习题4
1 何谓中断?51单片机中有哪几个中断资源?
解:让计算机正常运行程序时,因某突发事件的产生而暂停正在运行的程序,转去执行应对突发事件的相应程序,执行完该相应程序后,再返回原暂停处接
着运行原来的程序,这种应对机制称为中断。
单片机中有5个中断资源。
2 写出定义中断服务函数的一般形式。
解:中断请求服务函数的编写形式如下:
函数类型函数名(形式参数表)interrupt n [using m]
{
…
}
其中,interrupt 后面的n表示中断号,其值为0~4,后面的方括号表示其为可选项,using 后面的m表示使用的工作寄存器组号,初学者可以不选而用其
默认值。在C51中对5个中断号代表的中断源规定如下:
3 根据REG51.h头文件的有关定义,单片机中有哪两个与中断有关的寄存器,它们各自的功能是什么?
解: REG51.h头文件中所定义的IE寄存器和IP寄存器,就是两个与中断有关的寄存器,IE的功能是可设置各中断的允许与否,IP的功能是设置各中断的中断
优先级。
4 写出仅允许外中断1中断的IE赋值语句。
解:仅允许外中断1中断的IE赋值语句:
IE=0x84;
5 写出仅允许计数器1中断的IE赋值语句。
解:仅允许计数器1中断的IE赋值语句:
IE=0x88;
6 写出同时允许外中断1中断和计数器1中断的IE赋值语句。
解:同时允许外中断1中断和计数器1中断的IE赋值语句:
IE=0x8c;
7 写出让计数器1中断的优先级高于外中断1中断的优先级的IP赋值语句。
解:计数器1中断的优先级高于外中断1中断的优先级的IP赋值语句:
IP=0x08;
8 怎样才能产生一次外中断?
解:把单片机的第12脚或第13脚对地短路并断开,就能产生一次外中断。
9 怎样才能产生一次定时器中断?
解:(1)设置IE,允许一定时器中断,如
EA=1;ET0=1;//允许T0中断
(2)设置TMOD寄存器,以确定定时器工作方式,如
TMOD=0x01;//设定T0为定时器模式
(3)设定T0的计数赋初值,如
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
(4)启动定时器,如
TR0=1;
当从15536起,每微秒计数1次,50毫秒就产生一次定时器中断。
说明,当T0的C/T位为0时,每个工作周期自动计数1次,
10 怎样才能产生一次计数器中断?
解:(1)设置IE,允许一定时器中断,如
EA=1;ET0=1;//允许T0中断
(2)设置TMOD寄存器,以确定计数器工作方式,如
TMOD=0x05;//设定T0为计数器模式
(3)设定T0的计数赋初值,如
TH0=0xff;
TL0=0xf0;
(4)启动计数器,如
TR0=1;
当从0xfff0起,出现在单片机第14脚上的外部负跳变为16次时,就产生一次计数器中断。
说明,当T0的C/T位为1时,为计数器工作模式,
11如何确定计数器和定时器的初值?
解:首先用定时器所需的微秒数,或计数器所需的脉冲数作加1次数值N,再用65536与加1次数值N之差作定时器或计数器的初值。
说明,不要用加1次数值N作初值。因为不论是定时器中断还是计数器中断,本质上都是计数溢出中断,即当计数到65535(寄存器的二进制位全为
1)后再计数1次就产生中断,也就是计数到65536才产生中断。因此,从差
值计数N次后即为65536,恰好产生中断。
习题5
1.画出案例18中DS1302的三总线引脚与单片机I/O引脚间的具体连接电路。
解:由图1-3,可画出案例18中DS1302的三总线引脚与单片机I/O引脚间的具体连接电路如下:
2.写出案例18中与DS1302的三总线对接的位寻址变量的定义语句。
解:案例18中与DS1302的三总线对接的位寻址变量的定义语句如下:
sbit SCLK=P2^4;
sbit DA TA=P2^5;
sbit RST=P2^6;
3.画出基于DS1302的实用电子钟源程序的程序架构和函数调用路线图。
解:基于DS1302的实用电子钟源程序的程序架构和函数调用路线图如下:
4.图5-4所示为一直流电动机驱动电路.。设小电动机的工作电压小于5V,由三极管的知识可知,当J1、J6两端加高电平,J3、J4两端加低电平时,电动机顺时针转动;当J1、J6两端加低电平,J3、J4两端加高电平时,电动机反时针转动;当J1、J3、J4、J6均加高电平时,电动机不能转动。现将J1、J3、J4、J6分别接于P2.4、P2.5、P2.6、P2.7上。根据单片机学习板上关于S4、S5、S6的连接实际,请编程实现:1按一下S4时,电动机顺时针转动;2 按一下S5,电动动反时针转动;按下S6时,电动机停止转动。(注,对按钮的检查编程,可仿电子钟案例中对按钮的检查作类似处理)
图5-4 单片机电动机驱动电路
解:源程序如下
/* 习题5-4 */
#include
#define uchar unsigned char
sbit J1=P2^4;
sbit J3=P2^5;
sbit J4=P2^6;
sbit J6=P2^7;
sbit s4=P1^1;
sbit s5=P1^2;
sbit s6=P1^3;
main()
{
uchar i;
while(1)
{
if(s6==0)
{
for(i=0;i<100;i++)
;
if(s6==0)
J1=1,J3=1,J4=1,J6=1; /* 电机停转*/ }
if(s4==0)
{
for(i=0;i<100;i++)
;
if(s4==0)
J1=0,J3=1,J4=1,J6=0; /* 电机正转*/ }
if(s5==0)
{
for(i=0;i<100;i++)
;
if(s5==0)
J1=1,J3=0,J4=0,J6=1; /* 电机反转*/
}
}
}
习题6
1.画出案例19中AT24C02的二总线引脚与单片机I/O引脚间的具体连接电路。
解:根据图1-3,案例19中A T24C02的二总线引脚与单片机I/O引脚间的具体连接
电路如下:
2.写出案例19中与A T24C02的二总线对接的位寻址变量的定义语句。
解:案例19中与A T24C02的二总线对接的位寻址变量的定义语句如下:
sbit sda=P2^7;
sbit scl=P3^6;
3. 画出“案例19:AT24C02应用编程”源程序的程序架构和函数调用路线图。
解:案例19源程序的程序架构和函数调用路线图如下:
习题7
1.画出案例20中DS18B20的单总线引脚与单片机I/O引脚间的具体连接电路。
解:案例20中DS18B20的单总线引脚与单片机I/O引脚间的具体连接电路如下:
2.写出案例20中与DS18B20的单总线对接的位寻址变量的定义语句。
解:案例20中与DS18B20的单总线对接的位寻址变量的定义语句如下:
sbit ds=P1^0;
3. 画出“案例20:DS18B20的应用编程”源程序的程序架构和函数调用路线图。
解:案例20源程序的程序架构和函数调用路线图如下:
习题8
1.画出本项目中DS1302的三总线引脚、AT24C02的二总线引脚、DS18B20的单总线引脚与单片机I/O引脚间的具体连接电路
解:本项目中DS1302的三总线引脚、A T24C02的二总线引脚、DS18B20的单总线引脚与单片机I/O引脚间的具体连接电路如下图:
2 写出本项目中与DS1302的三总线、AT24C02的双总线、DS18B20对接的位寻址变量的定义语句,
解:本项目中与DS1302的三总线、A T24C02的双总线、DS18B20的单总线对接的位寻址变量的定义语句如下:
sbit SCLK=P2^4; /* 实时时钟的时钟线引脚*/ sbit DATA=P2^5; /* 实时时钟的数据线*/
sbit RST=P2^6; /* 实时时钟的复位线引脚*/
sbit sda=P2^7; //IO口定义
sbit scl=P3^6;
sbit ds=P1^0;
3.画出本项目源程序中主函数main的执行流程图。
解:本项目源程序中主函数main的执行流程图如下:
4.说明本项目中外中断0的中断服务函数的作用。
解:本项目中,外中断0的中断服务函数的作用,是用来设定用户调整所得的DS1302的起始走时时间
5.说明外中断1的中断服务函数的作用。
解:本项目中,外中断1的中断服务函数的作用,是用来设定需要实现时间段上控制的时间信息和时间点上控制的时间信息,也就是把这些时间信息写入
AT24C02中。
6.说明计数器0的中断服务函数的作用。
解:本项目中,计数器0的中断服务函数的作用,就是中断主函数的时间显示运作,转而显示DS18B20所测温度。
7.说明定时器1的中断服务函数的作用。
解:本项目中,定时器1的中断服务函数的作用,就是用来产生计数器T0计数所需的模拟计数脉冲。
习题9
1.画出LED汉字显示屏驱动函数LED_hz的流程图。
解:LED汉字显示屏驱动函数LED_hz的流程图如下:
2.画出LED汉字显示屏与单片机的驱动接口连接图。
解:LED汉字显示屏与单片机的驱动接口连接图如下:
3.简要说明LED_hz函数中四重循环各自的工作任务。
解:最内层的第4层循环的作用是完成一行64个字模点数据的串行移位;从外到内的第3层循环的作用是完成16行移位的依次扫描,以形成完整的一场汉字显示;
从外到内的第2层循环用来安排每场点阵文本的重复显示次数;最外层的循环是
取其循环变量去合成字模数组的列下标,从而实现汉字显示的左移功能。
4.移位时钟的特点是什么?怎样产生一个移位时钟?
解:移位时钟的特点是按列产生,以驱动一个点字模的串行移位。把对应于74HC595串行数据输入的单片机I/O引脚定义为一个位寻址变量,对这一位寻址变量先赋值0,然后再赋值1,就产生一个移位时钟。
5.锁存时钟的特点是什么?怎样产生一个锁存时钟?
解:锁存时钟的特点是按行产生,以锁存一行串入并出的64个点字模数据。把对应于74HC595锁存时钟端的单片机I/O引脚定义为一个位寻址变量,对这一位寻址变量先赋值0,然后再赋值1,就产生一个锁存时钟。
习题10
1 画出案例21源程序的程序架构和函数调用路线图.
解:案例21源程序的程序架构和函数调用路线图如下:
2 把项目1中的AT24C02取消,用片内EEPROM实现其功能,完成相应的电子钟及温度计程序设计。
解:取代的具体做法是,在第8章的源程序中,去掉与AT24C02有关的位寻址定义和函数定义,把宏晶公司IAP技术资料加入到程序中来。然后,对源程序
再作三处修改:
第一,把主函数中原对AT24C02的读操作,改为对片内EEPROM的读操作,并在前面增加一个指针变量的定义和赋值;
第二,把外中断INT1的中断服务函数中,对AT24C02的写操作,改为仅是对时间数组的赋值操作;
第三,在外中断INT0的中断服务函数中,增加对片内EEPROM的写入操作。
具体改动如下:
1 main()主函数中的增改:
(1) 增加指针变量的定义和赋值
unsigned char *p;
p=0x2000;
(2) 把原来对AT24C02的循环读操作
AT24C0x_init();
for(i=0;i<121;i++)
mmhh[i]=AT24C0x_read(i);
改为如下对片内EEPROM的循环读操作
for(i=0;i<121;i++)
mmhh[i]=byte_read(p+i);//程序开始时读取EEPROM中数据
2 把INT1中断服务函数中的如下几行,
AT24C0x_write(v,m);
v++;
AT24C0x_write(v,u);
v=v+1;
AT24C0x_write(0,ww);
ww++;
改为如下几行,
mmhh[v++]=m;
mmhh[v++]=u;
mmhh[0]=ww++;
3 在INT0中断服务函数中增加以下几行,
unsigned char *p;
p=0x2000;
u=mmhh[0]*2;
SectorErase(0x2000);//擦除扇区
for(m=0;m<=u;m++)
byte_write(p+m,mmhh[m]);//重新写入数据
修改所得的源程序如下:
源程序
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define RdCommand 0x01 //定义ISP的操作命令
#define PrgCommand 0x02
#define EraseCommand 0x03
#define Error 1
#define Ok 0
#define WaitTime 0x01 //定义CPU的等待时间
sfr ISP_DATA=0xe2; //寄存器申明
sfr ISP_ADDRH=0xe3;
sfr ISP_ADDRL=0xe4;
sfr ISP_CMD=0xe5;
sfr ISP_TRIG=0xe6;
sfr ISP_CONTR=0xe7;
sbit SCLK=P2^4; /* 实时时钟的时钟线引脚*/
sbit DATA=P2^5; /* 实时时钟的数据线*/
sbit RST=P2^6; /* 实时时钟的复位线引脚*/
sbit gw=P2^3; //个位
sbit sw=P2^2; //十位
sbit bw=P2^1; //百位
sbit qw=P2^0; //千位
sbit s3=P1^0;
sbit s4=P1^1;
sbit s5=P1^2;
sbit s6=P1^3;
sbit jw=P1^7;
sbit ds=P1^0;
sbit sda=P2^7; //IO口定义
sbit scl=P3^6;
sbit led=P1^4;
sbit SPEAK=P1^5;
uchar Utime[7]={01,48,21,8,01,05,10}; // 秒分时日月星期年uchar idata mmhh[121];
uchar zz; //定义计数值,每过1秒,sec加1
uchar xsd=255;
uchar xsdb=255;
uchar jfb=0;
uchar c1a=0;
uchar c1b=255;
uint temp;
delayx(uint z)//延时函数
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
Delay() /*延时*/
{
uchar m,n;
int max,min,time;
n=0;zz=mmhh[0]*2;
for(m=1;m<=12;m=m+4)
{
min=mmhh[m]*100+mmhh[m+1];
max=mmhh[m+2]*100+mmhh[m+3];
time=Utime[2]*100+Utime[1];
if(time>=min&&time<=max)
{led=0;break;}
else
{led=1;}
}
for(m=13;m<=zz;m=m+2)
if(mmhh[m+1]==Utime[1]&&mmhh[m]==Utime[2])
{SPEAK=0;break;}
else
{SPEAK=1;}
}
Disp_led( int m)
{
uchar code num[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
int n;
qw=1;
bw=1;
sw=1;
gw=1;
//显示千位上的数
n=m/1000; //取得千位数上的数
P0 = num[n];//把数字的笔划码赋给P0口
P0=P0|c1a;
P0=P0&c1b;
qw=0;/*开通千位(左边第一位)上的数码管显示*/
Delay();//延时
qw=1;
//显示百位上的数
n=m/100%10;//取得百位上的数
P0 = num[n];//把数字笔划码赋给P0口
P0=P0&xsdb;
bw=0;/*开通百位(左起第二位)上的数码管显示*/
Delay();//延时
bw=1;
//显示十位上的数
n=m/10%10;//取得十位上的数
P0 =num[n];//把数字笔划码赋给P0口
P0=P0&xsd;
sw=0;/*开通十位(左起第三位)上的数码管显示*/
Delay();//延时
sw=1;
//显示个位上的数
n=m%10; //取得个位上的数
P0 = num[n];//把数字笔划码赋给P0口
gw=0;/*开通个位(左起第四位)上的数码管显示*/
Delay();//延时
gw=1;
}
Wbit1302(uchar dat)
{
uchar i;
for(i=0;i<8;i++) //连续写8个二进制位数据
{
SCLK=0;
DATA=dat&0x01; //取出dat的第0位数据写入1302
SCLK=1; //上升沿写入数据
dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位}
}
Wbyte1302(uchar Cmd,uchar dat)
{
RST=0;
SCLK=0; //只有在SCLK为低电平时,才能将RST置为高电平
RST=1; //启动数据传输
Wbit1302(Cmd); //写入命令字
Wbit1302(dat); //写数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //终止数据传递
}
uchar Rbit1302()
{
uchar i,dat;
for(i=0;i<8;i++) //连续读8个二进制位数据
{
SCLK=0; //拉低SCLK,形成脉冲下降沿读出数据
dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位
if(DATA==1) //如果读出的数据是1
dat|=0x80; //dat的最高位被或上1
SCLK=1; //将SCLK置于高电平,为产生下降沿作准备}
return dat; //将读出的数据返回
}
uchar Rbyte1302(uchar Cmd)
{
uchar dat,k;
RST=0; //拉低RST
SCLK=0; //只有在SCLK为低电平时,才能将RST置为高电平RST=1; //启动数据传输
Wbit1302(Cmd); //写入命令字
dat=Rbit1302(); //读出数据
SCLK=1; //将时钟电平置于已知状态
RST=0; //终止数据传递
k=dat/16;
dat=dat%16+k*10;
return dat; //将读出的数据返回
}
Puts1302()// 把时间数组数据输出到1302
{
uchar i,j;
uchar ucAddr=0x80;
Wbyte1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/
for(i=0;i<7;i++)
{
j=Utime[i];
Wbyte1302(ucAddr,j); /* 秒分时日月星期年*/
ucAddr +=2;