单片机第三次任务

目录

一、模块化编程

1.什么是模块化编程

2.模块化编程的好处

3.如何实现模块化

二.矩阵按键

1.简述

2.硬件设计

3.矩阵按键扫描

代码设计

三.定时器

1.定时器有关知识

1.CPU时许相关内容

2.基本知识

2.定时器原理

3.定时器结构

定时器内部结构如图:

TCON控制寄存器:

TMOD模式寄存器:

TL0&&TH0

中断程序

四.串口

1.串口简介

2.硬件电路

3.单片机URAT

串口模式图

相关寄存器

4.单片机串口收发数据

1.发送数据

1.串口初始化

1.SCON的配置。

2.PCON的配置。

3. 配置定时器T1:

波特率的确定

4.禁止定时器T1中断:ET1=0;

2.代码实现

2.接收数据

 五.LED点阵屏

1.LED点阵屏原理 

2.74HC59芯片

代码设计

3.一些零碎知识

4.LED点阵屏软件设计

静态动画

动态动画

六.ds1302时钟

1.ds1302时钟芯片简介

2.ds1302使用

 1.控制寄存器

 2.日历/时钟寄存器

3.BCD码

​编辑

3.ds1302软件设置

一、模块化编程

1.什么是模块化编程

模块化编程是一种软件开发方法,它将程序拆分为独立的、相互关联的模块。在单片机编程中,模块化设计有助于提高代码的可读性、可维护性和可重用性。

2.模块化编程的好处

1.代码结构清晰2.易于维护3.提高代码重用性4.降低调试难度5.提高系统的灵活性6.更好的单元测试

3.如何实现模块化

1.创建.c文件,在文件中输入相应模块代码

2.创建.h文件,在文件中定义相关函数,如:

#ifndef__xx_H_//此处可直接使用keli的templates区域内的##define(需稍作修改)
#define__xx_H_
void .....;//注意:一定要打上分号
##endif

3.调用函数:在主函数中使用#include"xxx.h"(也可在templates中修改后直接使用)

二、使用步骤

二.矩阵按键

1.简述

  在单片机应用系统中,通过按键实现数据输入及功能控制是非常普遍的,通常在所需按键数量不多时,系统常采用独立式按键。需要按键数量比较多,为了减少I/O口的占用,通常将按键排列成矩阵.

2.硬件设计

从上图中可以看出,该电路是集成的,4*4 矩阵按键引出的 8 根控制管脚直接连接到 51 单片机的 P1 IO 口上。电路中的 P17 表示矩阵键盘第 1 行,P14 表示矩阵键盘第 1 列

该处使用的url网络请求的数据。

3.矩阵按键扫描

思路:

1、查询是否有键按下。
2、键的抖动处理。
3、查询按下键所在行和列位置,得到键值。

代码设计

#include <REGX52.H>
#include "delay.h"
unsigned char MatrixKey()
{
//法一:
	unsigned char keynum=0;
	
	P1=0xFF;
	P1_3=0;
	if(P1_7==0){delay(20);while(P1_7==0);delay(20);keynum=1;}
	if(P1_6==0){delay(20);while(P1_6==0);delay(20);keynum=5;}
	if(P1_5==0){delay(20);while(P1_5==0);delay(20);keynum=9;}
	if(P1_4==0){delay(20);while(P1_4==0);delay(20);keynum=13;}
	
	P1=0xFF;
	P1_2=0;
	if(P1_7==0){delay(20);while(P1_7==0);delay(20);keynum=2;}
	if(P1_6==0){delay(20);while(P1_6==0);delay(20);keynum=6;}
	if(P1_5==0){delay(20);while(P1_5==0);delay(20);keynum=10;}
	if(P1_4==0){delay(20);while(P1_4==0);delay(20);keynum=14;}
	
	P1=0xFF;
	P1_1=0;
	if(P1_7==0){delay(20);while(P1_7==0);delay(20);keynum=3;}
	if(P1_6==0){delay(20);while(P1_6==0);delay(20);keynum=7;}
	if(P1_5==0){delay(20);while(P1_5==0);delay(20);keynum=11;}
	if(P1_4==0){delay(20);while(P1_4==0);delay(20);keynum=15;}
	
	P1=0xFF;
	P1_0=0;
	if(P1_7==0){delay(20);while(P1_7==0);delay(20);keynum=4;}
	if(P1_6==0){delay(20);while(P1_6==0);delay(20);keynum=8;}
	if(P1_5==0){delay(20);while(P1_5==0);delay(20);keynum=12;}
	if(P1_4==0){delay(20);while(P1_4==0);delay(20);keynum=16;}
	
	return keynum;
}
法二:
void KeyDown(void)
{
    char a=0;
    GPIO_KEY=0x0f;
    if(GPIO_KEY!=0x0f)//读取按键是否按下
    {
        delay(1000);//延时 10ms 进行消抖
        if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
        {
            //测试列
            GPIO_KEY=0X0F;
            switch(GPIO_KEY)
           {
            case(0X07): KeyValue=0;break;
            case(0X0b): KeyValue=1;break;
            case(0X0d): KeyValue=2;break;
            case(0X0e): KeyValue=3;break;
            }
            //测试行
            GPIO_KEY=0XF0;
            switch(GPIO_KEY)
            {
            case(0X70): KeyValue=KeyValue;break;
            case(0Xb0): KeyValue=KeyValue+4;break;
            case(0Xd0): KeyValue=KeyValue+8;break;
            case(0Xe0): KeyValue=KeyValue+12;break;
            }
        }
      }
    return keyvalue;
   }

三.定时器

1.定时器有关知识

1.CPU时许相关内容

①振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期)。
②状态周期:2 个振荡周期为 1 个状态周期,用 S 表示。振荡周期又称 S 周期或时钟周期。
③机器周期:1 个机器周期含 6 个状态周期,12 个振荡周期。
④指令周期:完成 1 条指令所占用的全部时间,它以机器周期为单位。

2.基本知识

①51 单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器。
②定时器/计数器和单片机的 CPU 是相互独立的。 定时器/计数器工作的过程是自动完成的,不需要 CPU 的参与。
③51 单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信号 对寄存器中的数据加 1

2.定时器原理

51单片机定时器0内部有两个寄存器TH0(高位寄存器)和TL0(低位寄存器),都是一字节的,2字节最大能存65535。
每过一个指令周期(1us),寄存器的值+1,当加到溢出后发出一个溢出中断,程序可以捕获到这个中断,就可以知道此时经历了(65535+1)us。
若要定时1ms,只需设置寄存器的初值为64536,这样到溢出值65536就正好1ms。

如:对一个以12mhz为晶振的单片机,其振荡周期=1/12M(s)=1/12(us)

其机器周期(指令周期)=12*振荡周期=1us;

3.定时器结构

定时器内部结构如图:

上图中的 T0 和 T1 引脚对应的是单片机 P3.4 和 P3.5 管脚。51 单片机定时/计数器的工作由两个特殊功能寄存器控制。TMOD 是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON控制寄存器,控制 T0、 T1 的启动和停止及设置溢出标志
TCON控制寄存器:

低四位用于控制外部中断,高四位控制定时器的启动和中断申请.
TF0 = 0; //清除TF0溢出中断标志,加到1s后TF0会被置为1
TR0 = 1; //允许定时器0计时
(TF1和TR1是定时器1)
TMOD模式寄存器:

低四位用于 T0,高四位用于 T1。
gate是门控位,GATE=0 时,用于控制定时器的启动是否受外部中断源信号的影响。
GATA=1 时, INT0/1 引脚为高电平这一条件 TR0 或 TR1 为 1,定时器才可工作。
C/T :定时/计数模式选择位。C/T =0 为定时模式;C/T =1 为计数模式。
M1M0:工作方式设置位。定时/计数器有四种工作方式。

模式1工作图:

TMOD &= 0xF0;        //设置定时器模式(低4位清0,高四位不变)
TMOD |= 0x01;        //设置定时器模式(最低位置1,高四位不变)

TL0&&TH0

TL0 = 0x66;        //设置定时初值
TH0 = 0xFC;        //设置定时初值

中断程序


 

EA=1:CPU总中断允许位(0—>全部断开)
ET0=1; 中断允许
PT0=0;低优先级


定时器程序直接使用keli5自带程序即可,注意加上EA,ET0,PT0

四.串口

1.串口简介

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。
51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机的串口通信。

2.硬件电路

简单双向串口通信有两根通信线(发送端TXD和接收端RXD)。
TXD与RXD要交叉连接
当只需单向的数据传输时,可以直接一根通信线
当电平标准不一致时,需要加电平转换芯片

  • T——transmit(发送);
  • X——exchange(交换);
  • D——data(数据);
  • R——receive(接收);

3.单片机URAT

stc89c52的uart有四种工作模式:0:同步移位寄存器,1:8位uart,波特率可变,2:9位uart,波特率固定,3:9位uart,波特率可变

串口模式图

送数据的过程是:先把要传的数据写入发送缓冲区SBUF,以一定的波特率,通过发送数据源串口TXD,把数据发送出去。接收数据的过程是:数据通过RXD,以一定的波特率,写入接收缓冲区SBUF。

相关寄存器

4.单片机串口收发数据

1.发送数据

1.串口初始化

1:配置串口控制寄存器SCON为0x40(或0x50);
2:配置电源控制寄存器PCON(计算波特率);
3:配置定时器T1(串口通信只能用定时器1,只能使用8位自动重装工作模式),启动定时器T1;
4:禁止定时器T1中断;

1.SCON的配置。

SCON:用于设定串行口的工作方式,这里选择方式1(SM0=0,SM1=1)10位UART(8位数据,1位起始位,1位停止位),波特率可变。REN是允许串行接收控制位,这里是发送,所以不需要置1。SCON=0x40。

TI:发送中断标志位。在方式 0 时,当串行发送第 8 位数据结束时,或在其它方式,串行发送停止位的开始时,由内部硬件使 TI 置 1,向 CPU 发中断申请。 在中断服务程序中,必须用软件将其清 0,取消此中断申请.

RI:接收中断标志位。在方式 0 时,当串行接收第 8 位数据结束时,或在其 它方式,串行接收停止位的中间时,由内部硬件使 RI 置 1,向 CPU 发中断申请。 也必须在中断服务程序中,用软件将其清 0,取消此中断申请。

2.PCON的配置。

PCON:令SMOD=0,其他位不变。PCON&=0x7f。


SMOD:波特率选择位。

当用软件置位SMOD,即SMOD=1,则使串行通信方式1、2、3的波特率加倍;

 SMOD=0,则各工作方式的波特率不加倍。复位时SMOD=0。SMOD0:帧错误检测有效控制位。 

SMOD0=1,SCON寄存器中的SM0/FE位用于FE(帧错误检测)功能;○ 当SMOD0=0,SCON寄存器中的SM0/FE位用于SM0功能,和SM1一起指定串行口的工作方式。复位时SMOD0=0

3. 配置定时器T1:

TMOD &= 0x0F;       //TMOD高四位置0
TMOD |= 0x20;       //使用“8位自动重装”模式

波特率的确定

用8位自动重装(方式2)定时器T1的溢出率来产生波特率。

例:波特率为9600,晶振为12Mhz

溢出频率=波特率x16x2=0.3072Mhz

T1溢出一次的时间=1/溢出频率 =3.2552us

计数一次的时间=1/(12M)x12=1us,计数次数=溢出一次的时间/计数一次的时间=3.2552。

初始值就是2^8-3=253,化成16进制就是0xfd,所以初始值TH1=0xfd,重装值TL1=0xfd。

4.禁止定时器T1中断:ET1=0;
2.代码实现
#include <STC89C5xRC.H>
#include "Delay.h"

void UART_inti()//4800bps@11.0592MHz
//初始化寄存器
{
    SCON = 0x40;
    PCON = 0;

    //配置定时器1
    TMOD &= 0x0F;       //TMOD高四位置0
    TMOD |= 0x20;       //使用“8位自动重装”模式
    TL1 = 0xFA;         //设置定时初始值
    TH1 = 0xFA;         //设置定时重载值
    ET1 = 0;            //禁止定时器中断
    TR1 = 1;            //定时器1开始计时
}

void UART_SendByte(unsigned int Byte)
 //发送数据
{
    SBUF = Byte;
    //将数据写入SBUF
    while(TI == 0);
    TI = 0;//重置
}

unsigned char sec = 0;

void main()
{
    UART_inti();
    while(1)
    {
        UART_SendByte(sec);
        sec++;
        Delay(1000);
    }
}

2.接收数据

1:配置串口控制寄存器SCON为0x50;
2:配置电源控制寄存器PCON(计算波特率);
3:配置定时器T1(串口通信只能用定时器1,只能使用8位自动重装工作模式),启动定时器T1;
4:启动总中断和串口中断;

//串口初始化
void UartInit()		//4800bps@11.0592MHz
{
	PCON &= 0x7F;	
	SCON = 0x50;		//8位数据,可变波特率
	TMOD &= 0x0F;		//定时器1高四位置0
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFA;		//设定定时初值
	TH1 = 0xFA;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	//开启中断
	EA=1;	//总中断控制
	ES=1;	//串口中断
}
//串口发送一个字节数据
void UART_SendByte(unsigned char Byte){
	SBUF=Byte;
	//检测是否完成
	while(TI==0);
	TI=0;//TI复位
}
void main()
{
    UartInit();
    while(1)
    {
    }
}


//串口中断
void UART_Routine()    interrupt 4
{
	if(RI==1){
//在程序打开总中断和串口中断只需T1>=1||R1>=1就会触发中断
//串口在接受到数据后,硬件自动置R1=1
		P2=SBUF;//显示LED
		UART_SendByte(SBUF);//将数据发回电脑
		RI=0;//复位
	}
	
}


 五.LED点阵屏

1.LED点阵屏原理 

 8*8 点阵共由 64 个发光二极管组成,且每个发光二极管是放置在行线和列线 的交叉点上,当对应的某一行置 1 电平,某一列置 0 电平,则相应的二极管就亮,如要将第一个点点亮,则 1 脚接高电平 a 脚接低电平,则第一个点就亮了;点亮多个LED灯,即通过快速扫描,产生点灯效果(实则视觉延时)

2.74HC59芯片

74HC595 是一个 8 位串行输入、并行输出的位移缓存器,其中并行输出为三态输出(即高电平、低电平和高阻抗)

左侧矩形为移位寄存器,ser输出1时,当serclk达到上升沿时(即1),向下推移一个数字,当八个数字储存完毕,rclk上升沿锁位打开,八位数字同时进入右侧矩形。

代码设计


sbit RCK=P3^5;
sbit SCK=P3^6;
sbit SER=P3^4;
unsigned char a;
void 74hc59_write(unsigned char b)
{
	for(a=0;a<8;a++)
    {
        SER=b&(0x80>>a);(取出第八位值)
	    SCK=1;
        SCK=0;
    }
	RCK=1;
    RCK=0;
	

}

3.一些零碎知识

4.LED点阵屏软件设计

void LEDdz_init(()//初始化
{
    RCK=0;
    SCK=0;
}


void leddz_show(unsigned char column,data)
{

    74hc59_write(data);//段选
    P0=~(0x80>>column);//位选
	
	Delay(1);//防篡位
	P0=0xFF;//清零



}
静态动画
void main()
{
    leddz_init()

	while(1)
	{
	leddz_show(0,0x3C);
	leddz_show(1,0x42);
	leddz_show(2,0xA9);
	leddz_show(3,0x85);
	leddz_show(4,0x85);
	leddz_show(5,0xA9);
	leddz_show(6,0x42);
	leddz_show(7,0x3C);
	}
}
动态动画
unsigned char code Animation[]=
// code 代表数组中的数据放到了FLASH中,而非RAM里,好处是不会占用内存本就不多的RAM太多内存,但在后续操作中无法进行更改 
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0x08,0x08,0x08,0xFF,0x00,0x0E,0x15,
0x15,0x15,0x08,0x00,0x7E,0x01,0x02,0x00,
0x7E,0x01,0x02,0x00,0x0E,0x11,0x11,0x0E,
0x00,0x7D,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,
}
;
unsigned char i,offset,count;

void main()
{
	RCK=0;
	SCK=0;
	//单片机给电时两个时钟得到高电平值变为1,故须进行初始化清零
	while(1)
	{
		for(i=0;i<8;i++)
		{
			leddz_Show(i,Animation[i+offset]);
			//offset即偏移,每过一段时间offset加一,动画跳一帧
		}
		count++;
		if(count>10)//此处可以使用定时器做
		{
			offset++;
			count=0;
		}
		if(offset>36)
			offset=0;
	
	}
}

六.ds1302时钟

1.ds1302时钟芯片简介

主要的性能指标:

★ 实时时钟具有能计算 2100 年之前的秒、分、时、日、星期、月、年的
能力,还有闰年调整的能力;
★ 31 个 8 位暂存数据存储 RAM;
★ 串行 I/O 口方式使得管脚数量最少;
★ 宽范围工作电压 2.0~5.5V;
★ 工作在 2.0V 时,电流小于 300nA;
★ 读/写时钟或 RAM 数据时有两种传送方式单字节传送和多字节传送字符组
方式;
★ 8 脚 DIP 封装或可选的 8 脚 SOIC 封装根据表面装配;
★ 简单 3 线接口;
★ 与 TTL 兼容 Vcc=5V;
★ 可选工业级温度范围-40~+85
1,VCC2:主用电源引脚
2,X1、X2:DS1302 外部晶振引脚,通常需外接 32.768K 晶振
3,GND:电源地
4,CE:使能引脚,也是复位引脚(新版本功能变)。
5,I/O:串行数据引脚,数据输出或者输入都从这个引脚
6,SCLK:串行时钟引脚
7,VCC1:备用电源

2.ds1302使用

 1.控制寄存器

        控制寄存器用于存放 DS1302 的控制命令字,DS1302 的CE引脚回到高电平后写入的第一个字节就为控制命令。它用于对 DS1302 读写过程进行控制,格式如下:

 

 2.日历/时钟寄存器

即通过红色框中的地址,控制相关寄存器的读与写

写保护寄存器:当该寄存器最高位 WP 为 1 时,DS1302 只读不写,所以要在往 DS1302 写数据之前确保 WP 为0;

3.BCD码

时钟的寄存器中各位数据均以BCD码形式存储,在读写时间程序中需将十进制转为BCD,BCD转为十进制。

4.DS1302 的读写时序

在控制指令字输入后的下一个 SCLK 时钟的上升沿时,数据被写入 DS1302,
数据输入从低位(位 0)开始。同样,在紧跟 8 位的控制指令字后的下一个 SCLK
脉冲的下降沿读出 DS1302 的数据,读出数据时从低位 0 位到高位 7。其时序图
如下所示:

1、CE:初始化后为低电平, 在整个读写器件,要保持高电平,一次字节读写完毕之后,在进行置低电平;

2、单字节写入:在CE为高电平后,SCLK会输出周期脉冲,每一个上升沿,IO线的数据就会进入控制寄存器,当控制寄存器配置完成(为写入数据,并且地址已给),紧接着的脉冲IO线的数据就会在上升沿进入对应地址的寄存器;(上升沿读入)

3、单字节读出:在CE为高电平后,SCLK会输出周期脉冲,每一个上升沿,IO线的数据就会进入控制寄存器,当控制寄存器配置完成(为读出数据,并且地址已给),紧接着对应地址的寄存器的数据就会在下降沿进入IO线;(下降沿读出)
 

3.ds1302软件设置

#include <REGX52.H>//来自江科大视频
 
//引脚定义;
sbit  DS1302_SCLK=P3^6;
sbit  DS1302_IO=P3^4;
sbit  DS1302_CE=P3^5;
 
//对应寄存器位置定义
#define  DS1302_SECOND		0X80
#define  DS1302_MINUTE  	0X82
#define  DS1302_HOUR		0X84
#define  DS1302_DATE        0X86
#define  DS1302_MONTH		0X88
#define  DS1302_DAY         0X8A
#define  DS1302_YEAR        0X8C
#define  DS1302_WP          0X8E 
 
//定义数组,用于存放设定的时间,年月日时分秒星期
unsigned char DS1302_Time[]={23,10, 28,19,00,59,6};//顺序:年月日时分秒星期
/**
   *@breaf DS1302初始化
   *@param无
   *@retval无
   */
void  DS1302_Init()
{
	DS1302_CE=0;//将使能位置0,低电平;
	DS1302_SCLK=0;//将时钟位置0,低电平;
}
 
/**
   *@breaf DS1302单字节写入函数
   *@param command:写入控制指令的指令,包含要写入寄存器的地址;
	 *@param Data:将要写入的数据内容;
   *@retval 无
   */
void  DS1302_WriteBety(unsigned char command,Data)
{
			unsigned char i;
			DS1302_CE=1;//使能位置高电平;
			for(i=0;i<8;i++)//控制寄存器数据需要通过IO线一个一个写入控制寄存器;低位先写入
		{
				DS1302_IO=command&(0x01<<i);//相当于把第1--7位置0,只留第0位,如果第0位是0,则为0;反之则为1;
				DS1302_SCLK=1;
				DS1302_SCLK=0;
		}
		
				for(i=0;i<8;i++)//数据写入
		{
				DS1302_IO=Data&(0x01<<i);//相当于把第1--7位置0,只留第0位,如果第0位是0,则为0;反之则为1;
				DS1302_SCLK=1;
				DS1302_SCLK=0;
		}
			DS1302_CE=0;	
}
 
/**
   *@breaf  DS1302单字节读出函数
   *@param command:写入控制指令的指令,包含要读出寄存器的地址;
   *@retval Data:读出的数据;
   */
unsigned char   DS1302_ReadBety(unsigned char command)
{
	unsigned i,Data=0X00;
	    command|=0X01;//写入指令与读出指令只在最后一位相差1,故在此利用或运算消除;
			DS1302_CE=1;//使能位置高电平;
		for(i=0;i<8;i++)//控制寄存器数据需要通过IO线一个一个写入控制寄存器;低位先写入
		{
				DS1302_IO=command&(0x01<<i);//相当于把第1--7位置0,只留第0位,如果第0位是0,则为0;反之则为1;
				DS1302_SCLK=0;	
				DS1302_SCLK=1;
		}
				DS1302_IO=0;
			for(i=0;i<8;i++)//数据读出
		{
					DS1302_SCLK=1;
					DS1302_SCLK=0;			
					if(DS1302_IO)  
					{Data |=(0X01<<i);}
		}
		DS1302_CE=0;
		return Data;
}
 
 
/**
   *@breaf 向DS1302内设定时间
   *@param无
   *@retval无
   */
void DS1302_SetTime()
{
		DS1302_WriteBety(DS1302_WP,0x00);//操作 DS1302 之前,关闭写保护,不然指令无法进入控制寄存器;
		DS1302_WriteBety(DS1302_YEAR, DS1302_Time[0]/10*16+DS1302_Time[0]%10);//写入年,并将10进制转化BCD码;
		DS1302_WriteBety(DS1302_MONTH, DS1302_Time[1]/10*16+DS1302_Time[1]%10);//写入月,并将10进制转化BCD码;
		DS1302_WriteBety(DS1302_DATE, DS1302_Time[2]/10*16+DS1302_Time[2]%10);//写入日,并将10进制转化BCD码;
		DS1302_WriteBety(DS1302_HOUR, DS1302_Time[3]/10*16+DS1302_Time[3]%10);//写入时,并将10进制转化BCD码;
		DS1302_WriteBety(DS1302_MINUTE, DS1302_Time[4]/10*16+DS1302_Time[4]%10);//写入分,并将10进制转化BCD码;
		DS1302_WriteBety(DS1302_SECOND, DS1302_Time[5]/10*16+DS1302_Time[5]%10);//写入秒,并将10进制转化BCD码;
		DS1302_WriteBety(DS1302_DAY, DS1302_Time[6]/10*16+DS1302_Time[6]%10);//写入星期,并将10进制转化BCD码;
		DS1302_WriteBety( DS1302_WP,0x80);//写入结束,开启写保护;
}
 
/**
*@breaf 读取DS1302内时间
*@param无
*@retval无
*/
void DS1302_ReadTime()	
{
	unsigned char Temp;//定义变量,用于暂时存储BCD码
    Temp=DS1302_ReadBety(DS1302_YEAR);//读取年BCD码;
		DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制;
	 Temp=DS1302_ReadBety(DS1302_MONTH);//读取月BCD码;
		DS1302_Time[1]=Temp/16*10+Temp%16;//BCD码转十进制;
	 Temp=DS1302_ReadBety(DS1302_DATE);//读取日BCD码;
		DS1302_Time[2]=Temp/16*10+Temp%16;//BCD码转十进制;
	 Temp=DS1302_ReadBety(DS1302_HOUR);//读取小时BCD码;
		DS1302_Time[3]=Temp/16*10+Temp%16;//BCD码转十进制;
	 Temp=DS1302_ReadBety(DS1302_MINUTE);//读取分钟BCD码;
		DS1302_Time[4]=Temp/16*10+Temp%16;//BCD码转十进制;
	 Temp=DS1302_ReadBety(DS1302_SECOND);//读取秒BCD码;
		DS1302_Time[5]=Temp/16*10+Temp%16;//BCD码转十进制;
	 Temp=DS1302_ReadBety(DS1302_DAY);//读取星期BCD码;
		DS1302_Time[6]=Temp/16*10+Temp%16;//BCD码转十进制;
}
#include <STC89C5xRC.H>//for循环简化
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;

void DS1302_Init()
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}
void write_ds1302(unsigned char temp)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DS1302_SCLK=0;
		DS1302_IO=temp&(0x01<<i);
		DS1302_SCLK=1;

	}
}
void ds1302_writebyte(unsigned char adr,dat)
{
	DS1302_SCLK=0;
	DS1302_CE=0;
	DS1302_CE=1;
	write_ds1302(adr);
	write_ds1302(dat);
	DS1302_CE=0;
}
unsigned char ds1302_readbyte(unsigned char adr)
{
	unsigned char i,date=0x00;
	DS1302_SCLK=0;
	DS1302_CE=0;
	DS1302_CE=1;
	adr|=0x01;
	write_ds1302(adr);
	for(i=0;i<8;i++)
	{
		DS1302_SCLK=1;
		DS1302_SCLK=0;
		if(DS1302_IO){date|=(0x01<<i);}
	}
	DS1302_SCLK=0;
	DS1302_CE=0;
	DS1302_SCLK=1;
	DS1302_IO=0;
	DS1302_IO=1;
	return date;
}
void timewriter()
{
	unsigned char i;
	ds1302_writebyte(0x8e,0x00);
	for(i=0;i<3;i++)
	{
		ds1302_writebyte(timewrite[i],day[i]/10*16+day[i]%10);
	}
	ds1302_writebyte(0x8e,0x80);
}
void ds1302_timeread()
{
	unsigned char j;
	for(j=0;j<3;j++)
	{
		unsigned char b=0;
		b=ds1302_readbyte(timewrite[j]);
		day[j]=b/16*10+b%16;
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值