AutoLeaders控制组—51单片机学习笔记 (二)

一.模块化编程

1.简介

模块化编程在主函数里面存放逻辑与算法,而相对固定不需要改变的函数或其他代码则存放在工程目录中方便随时调用。

2.模块化编程的优点

传统方式编程:所有的函数均放在main.c里,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路。

模块化编程:把各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数的声明,其它.c文件想使用其中的代码时,只需要在主函数 #include “XXX.h” 文件即可。使用模块化编程可极大的提高代码 的可阅读性、可维护性、可移植性等。

3.模块化编程注意事项

.c文件:函数、变量的定义 。
.h文件:可被外部调用的函数、变量的声明 。(外部可见的函数)

任何自定义的变量、函数在调用前必须有定义或声明(同一个.c)。而使用到的自定义函数的.c文件必须添加到工程参与编译
使用到的.h文件必须要放在编译器可寻找到的地方(工程文件夹根 目录、安装目录、自定义)。 (一般存入工程目录中)
防止重复定义 对程序代码是否编译进行选择
防止重复包含

4.预编译

C语言的预编译以#开头,作用是在真正的编译开始之前,对代码做一些处理(预编译)。
在这里插入图片描述
#include <REGX52.H> 把REGX52.H文件的内容搬到此处
#define PI 3.14 定义PI,将PI替换为3.14
#define ABC 定义ABC
#ifndef xx_H 如果没有定义__XX_H__
#endif 与**#ifndef,#if** 匹配,组成“括号
此外还有#ifdef,#if,#else,#elif,#undef等

在头文件中 :可以套用下面代码模版进行声明:

#ifndef __ _H__
#define __ _H__



#endif

想要实现模块化编程,进行预编译则需要对所需函数建立.c 文件和头文件,下面举个例子:

void Delay(unsigned int xms)		
{  while(xms--)
	{
	unsigned char i, j;
	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
 }
}
#ifndef __Delay_H__
#define __Delay_H__

void Delay(unsigned int xms);

#endif

上述进行的是对Delay延迟函数所进行的模块化编程。

二. LCD1602调试工具

1.简介

LCD液晶屏有两行,十六列
(1). LCD1602液晶屏作为调试窗口,提供类似printf函数的功能 可实时观察单片机内部数据的变换情况,便于调试和演示。
(2) . 相比于数码管和串口 (数码管显示的内容太少并且需要不断扫描,容易闪烁。)(串口则需要使用电脑来不断打开。操作相对复杂笨重)

2.原理图

观察下列LCD1602原理图可以知道。LCD1602占据了P0口和三个P2口。与数码管(P0口)和LED灯(P2口)共用引脚。因此使用LCD时,我们无法再使用数码管和LED灯,
在这里插入图片描述

三、矩阵键盘

1.简介

当键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,矩阵键盘由此而来。采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态。如下图:16个按键只需要8个I/O口
在这里插入图片描述

2.扫描的概念

数码管扫描 (输出扫描:让数码管输出显示数据)
原理: 显示第1位一>显示第2位一>显示第3位一>… 然后快速循环这个过程,最终实现所有数码管同时显示的效果。

矩阵键盘扫描 (输入扫描:读取单片机按键状态)
原理: 读取第1行(列)一>读取第2行(列)一>读取第3行(列)一>…然后快速循环这个过程,最终实现所有按键同时检测的效果。

以上两种扫描方式的共性: 节省I/O口。
但由于P15口与蜂鸣器相接,所以我们在使用矩阵键盘是采用按列扫描的方式,避免在操作过程中蜂鸣器“嗡嗡响”。

3.矩阵键盘模块化

用matrixkey函数调出矩阵键盘中按下按键的键码

/**

  • @brief 通过先逐列再逐行扫描,来判断矩阵键盘中哪个按键被按下
  • @param 无·
  • @retval keynumber: 键盘中所对应的键码
    **/

unsigned char matrixkey()
{
  unsigned char keynumber=0;
  
	P1=0xff;
	P1_3=0;
	if(P1_7==0) {delay(20);while(P1_7==0); delay(20); keynumber=1; }
	if(P1_6==0) {delay(20);while(P1_6==0); delay(20); keynumber=5; }
	if(P1_5==0) {delay(20);while(P1_5==0); delay(20); keynumber=9; }
	if(P1_4==0) {delay(20);while(P1_4==0); delay(20); keynumber=13; }

	P1=0xff;
	P1_2=0;
	if(P1_7==0) {delay(20);while(P1_7==0); delay(20); keynumber=2; }
	if(P1_6==0) {delay(20);while(P1_6==0); delay(20); keynumber=6; }
	if(P1_5==0) {delay(20);while(P1_5==0); delay(20); keynumber=10; }
	if(P1_4==0) {delay(20);while(P1_4==0); delay(20); keynumber=14; }

	P1=0xff;
	P1_1=0;
	if(P1_7==0) {delay(20);while(P1_7==0); delay(20); keynumber=3; }
	if(P1_6==0) {delay(20);while(P1_6==0); delay(20); keynumber=7; }
	if(P1_5==0) {delay(20);while(P1_5==0); delay(20); keynumber=11; }
	if(P1_4==0) {delay(20);while(P1_4==0); delay(20); keynumber=15; }

	P1=0xff;
	P1_0=0;
	if(P1_7==0) {delay(20);while(P1_7==0); delay(20); keynumber=4; }
	if(P1_6==0) {delay(20);while(P1_6==0); delay(20); keynumber=8; }
	if(P1_5==0) {delay(20);while(P1_5==0); delay(20); keynumber=12; }
	if(P1_4==0) {delay(20);while(P1_4==0); delay(20); keynumber=16; }

return keynumber;
}

由于I/O口为弱上拉模式,单片机检测低电平,故只有当某按键两端均为0时,才算按下此按键
因此由上述代码可知,逐列扫描时先将所有P1口赋为1,再分别将每一列对应的I/O口赋为0,接下来判断该列上的四个按键中哪一个按键的另一侧/O口为0,若为0则表示此按键被按下,然后进行按键消抖,判断是否被一直按下,如果不松手程序则被卡死,松手后则进行接下来的步骤。

四、定时器

1.简介

定时器介绍:51单片机的定时器不同于独立按键和矩阵键盘等外设,它属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。
定时器作用:

(1)用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作。
(2) 替代长时间的Delay,提高CPU的运行效率和处理速度。例如边进行流水灯边按键扫描
(3)操作系统任务进行切换,

2.STC89C52定时器资源

STC89C52所拥有的定时器个数:3个 (T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源

注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的。

3.定时器框图

定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号每隔“一秒"计数单元的数值就增加一,当计数单元数值增加到“设定的闹钟提醒时间”时,计数单元就会向中断系统发出中断申请,产生“响铃提醒”,使程序跳转到中断服务函数中执行。
原理图如下:
在这里插入图片描述

4.定时器工作模式

STC89C52的T0和T1均有四种工作模式
模式0:13位定时器/计数器
模式1:16位定时器/计数器(常用)
模式2:8位自动重装模式
模式3:两个8位计数器
这四种模式中,最常用的是模式1(16位定时器),模式2(8位自动重装模式相对用到的少。模式0、1几乎不会用。
工作模式1框图:
来一个脉冲加一65535—>0

5.定时器模式一框图:

模式一框图如下:由三部分组成,其中计数系统中的TL0(低字节)和TH0(高字节)一共能存储两个字节,即从0~65535。而左边的时钟会每隔一段时间(至于时间是多少呢?下文定时器时钟会揭秘)送来一段脉冲,使计数系统进行加一,当计数系统加到65535时,再往后加一,就会溢出,此时65535重置变为0,并使TF0置一,开始中断。

在这里插入图片描述

(1.)定时器时钟

SYSclk:系统时钟,即晶振周期,本开发板上的晶振为12MHz
系统时钟如果是12T模式。12MH 会进行分频,12分频输出频率为1MHz, 一周期1微秒。即一微秒记一次数。
C/T寄存器:当给此寄存器1时则为count计数器,给0时则为Timer定时器。
我们使用定时器,故将定时器配置为12分频,C/T=0。

(2.)中断系统

中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。

当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断

实现这种功能的部件称为中断系统,请示CPU中断的请求源称为中断源。微型机的中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,要求为它服务的时候,这就存在CPU优先响应哪一个中断源请求的问题。通常根据中断源的轻重缓急排队,优先处理最紧急事件的中断请求源,即规定每一个中断源有一个优先级别。CPU总是先响应优先级别最高的中断请求。

当CPU正在处理一个中断源请求的时候(执行相应的中断服务程序) ,发生了另外一个优先级比它还高的中断源请求。如果CPU能够暂停对原来中断源的服务程序,转而去处理优先级更高的中断请求源,处理完以后,再回到原低级中断服务程序,这样的过程称为中断嵌套。这样的中断系统称为多级中断系统,没有中断嵌套功能的中断系统称为单级中断系统。

中断程序流程

在这里插入图片描述

6.中断资源

中断的资源和单片机型号是相关联的,不同的型号可能会有不同的中断资源,例如中断源个数不同,中断优先级个数不同等

STC89C52的中断资源:
中断源个数(8个):外部中断0、定时器0中断、外部中断1、定时器1中断、串口中断、外部中断2、外部中断3。
中断优先级:4个
中断号:(函数后面加上interrupt即为中断函数)
在这里插入图片描述
中断结构:下图一共5个中断源为INT0,T0,INT1,T1,(RX和TX同为串口中断)
两个中断优先级。
在这里插入图片描述

6.定时器相关寄存器

单片机通过配置寄存器来控制内部线路的连接。要使用定时器则需要将其相关寄存器配置好。
TCON 定时器控制寄存器(可位寻址)
TMOD 定时器工作模式寄存器(不可位寻址)
可位寻址:可以对寄存器每一位进行赋值。
不可位寻址:只能进行整体赋值。
在这里插入图片描述
中断寄存器:
IE(interrupt enable)即中断的使能,其中ET0、ET1等是与某个中断源对应的中断使能,EA(enable all)为中断的总使能。(各符号后面的数字1 or 0决定了它们所对应的定时器)

TF:定时器的溢出中断标志。如 T0在允许计数后,从初值开始+1计数,当最高位溢出时,由硬件置”1“TF0,向CPU请求中断,直到CPU相应中断后,TF0才清零。

C/T:决定该元件的作用,置0为定时器,置1为计数器。

GATE:门控端,决定了启动暂停是由TR0单独控制还是TR0与外部引脚共同控制。给0时TR0单独控制,给1时TR0与外部引脚共同控制。但无论怎样,只有TR0=1时才允许计数。

M1与M0:共同决定定时器的工作模式(左M1右M0)。
若要使用定时器模式1, 则M1=0,M0=1。
在这里插入图片描述

7.代码示例

Timer0_Init()此函数作用为初始化定时器,并让定时器以1毫秒进行中断。

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0x20;				//设置定时初始值
	TH0 = 0xD1;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0=1;
	EA=1;
	PT0=0;
}

void main(void)
{
	Timer0_Init();
	while(1)
	{
	
	}
}

	void Timer0Routine()       interrupt 1 
{
		TL0 = 0x20;		
		TH0 = 0xD1;			

	}

五、串口通信

1.串口简介

串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。

单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。如用串口将单片机与陀螺仪进行联系,使的陀螺仪测得的数据传输给单片机,从而丰富单片机功能。

51单片机内部自带UART (Universal Asvnchronous Receiver Transmitter,通用异先收发器) 可实现单片机的串口通信。

2.硬件电路

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

3.电平标准

电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
TTL电平:+5V表示1,0V表示0
RS232电平:-3 ~ -15V表示1,+3~+15V表示0
RS485电平:两线压差+2~ +6V表示1,-2~-6V表示0(差分信号)
流控 数据流两设备传输数据其中一台速度慢请求发送。

4.常见通信接口

在这里插入图片描述
专业术语解释
全双工:通信双方可以在同一时刻互相传输数据。
半双工:通信双方可以互相传输数据,但必须分时复用一根数据线。
单工:通信只能有一方发送到另一方,不能反向传输。

异步:通信双方各自约定通信速率。
同步:通信双方靠一根时钟线来约定通信速率。

总线:连接各个设备的数据传输线路 (类似于一条马路,把路边各住户连接起来,使住户可以相互交流)。
通信速率:可以理解为数据传输/接收的快慢,即发送端以一定的频率发送数据,接收端也以一定的频率进行接收,二者的频率可能是各自决定也可能共同约定,可能相同也可能不同(数据的发送与接收一般以比特为单位)

6.51单片机的UART

STC89C52有1个UART
STC89C52的UART有四种工作模式
模式0:同步移位寄存器
模式1:8位UART,波特率可变 (常用)
模式2:9位UART,波特率固定
模式3:9位UART,波特率可变
在这里插入图片描述

6.串口参数及时序图

波特率:串口通信的速率(发送和接收各数据位的间隔时间)。
检验位:用于数据验证。
停止位:用于数据帧间隔。
8位数据格式:每八位组成一个数据单位,传入寄存器或从寄存器中一起被取出。
9位数据格式:多了一个检验位,此位的数据代表了检验方式,如给1时为奇校验,给0时为偶校验。
在这里插入图片描述

7.串口模式图

在这里插入图片描述

SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址(图中为0x99H)。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器。

此处定时器(TH1、TL1)的作用为:控制数据传输和接收的频率,与波特率的大小相关

发送控制器/接收控制器:在中断系统中的操作,分别控制着数据的发送与接收。
移位寄存器:将从RXD接收到的数据进行划分,每次只将一个比特位的数据传到SBUF中暂存。

把数据放入SBUF中
a=SBUF == > 收到数据,RI申请中断.
SBUF=0x01 == > TI进行发送中断

8.ES EA串口相关寄存器

在这里插入图片描述
STC89C52系列单片机的串行口共有两个控制寄存器:

串行控制寄存器SCON(可位寻址):
在这里插入图片描述

SM0/FE:当PCON寄存器中的SMOD0/PCON.6位为1时,该位用于帧错误检测。当检测到一个无效停止位时,通过UART接收器设置该位。它必须由软件清零。

最常用的方式1:SM0=1 SM1=0。
SM2:允许方式2或方式3多机通信控制位。在方式2或方式3时,如SM2位为1,REN位为1,则从机处于只有接收到RB8位为1(地址)时才激活中断请求标志位RI为1,并向主机请求中断处理。被确认为寻址的从机则复位SM2位为0,从而才接收RB8为0的数据顿。在方式1时,如果SM2位为1,则只有在接收到有效的停止位时才置位中断请求标志位RI为1:在方式0时,SM2 应为0。

REN:允许/禁止串行接收控制位。由软件置位REN,即REN=1为允许串行接收状态,可启动串行接收器RxD,开始接收信息。软件复位REN,即REN=0,则禁止接收。(receive enable)

TB8:在方式2或方式3,它为要发送的第9位数据,按需要由软件置位或清0。例如,可用作数据的校验位或多机通信中表示地址帧/数据帧的标志位。

RB8:在方式2或方式3,是接收到的第9位数据。在方式1,若SM2=0,则RB8是接收到的停止位。方式0不用RB8。

由与我们用到的是方式一,故SM2、TB8、RB8均置0

TI:发送中断请求标志位。在方式0,当串行发送数据第8位结束时,由内部硬件自动置位,即TI=1,向主机请求中断,响应中断后必须用软件复位,即TI=0。在其他方式中,则在停止位开始发送时由内部硬件置位,必须用软件复位。

RI:接收中断请求标志位。在方式0,当串行接收到第8位结束时由内部硬件自动置位RI=1,向主机请求中断,响应中断后必须用软件复位,即RI=0。在其他方式中,串行接收到停止位的中间时刻由内部硬件置位,即RI=1(例外情况见SM2说明),必须由软件复位,即RI=0。

波特率选择特殊功能PCON(不可位寻址):
在这里插入图片描述

SMOD:波特率选择位。当用软件置位SMOD,即SMOD=1,则使串行通信方式1、2、3的波特率加倍:SMOD=0,则各工作方式的波特率加倍。复位时SMOD=0。

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

9. 串口初始化演示

void Uart1_Init(void)	//4800bps@12.000MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	AUXR &= 0xBF;		//定时器时钟12T模式
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	//AUXR不存在于STC89C52单片机中,因为定时器时钟只有12T模式,波特率发生器也只能用定时器1,故实际使用时应删掉这两句
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x20;		//设置定时器模式
	TL1 = 0xF9;			//设置定时初始值
	TH1 = 0xF9;			//设置定时重载值
	ET1 = 0;			//禁止定时器中断
	TR1 = 1;			//定时器1开始计时
}

六、LED点阵屏

1.简介

LED点阵屏由若千个独立的LED组成,LED以矩阵的形式排列,以灯珠亮灭来显示文字、图片、视频等。
LED点阵屏广泛应用于各种公共场合,如汽车报站器、广告屏以及公告牌等.
LED点阵屏分类按颜色:单色、双色、全彩按像素:88、1616等(大规模的LED点阵通常由很多个小点阵拼接而成)

2.点阵屏显示原理

LED点阵屏的结构类似于数码管,只不过是数码管把每一列的像素以“8”字型排列而已。
LED点阵屏与数码管一样,有共阴和共阳两种接法,不同的接法对应的电路结构不同。
LED点阵屏需要进行逐行或逐列扫描,才能使所有LED同时显示。
引脚对应关系如下图:
在这里插入图片描述
在这里插入图片描述

3.74HC595

在这里插入图片描述
(名称上面加一条横线,代表该位为低电平有效或下降沿有效)
OE(output enable) 输出使能,决定芯片能否输出,故使用时将JOE中的OE与GND连接,以读取输出数据。
QH‘:多片级联端,用于向下一片74HC595传输数据。
SRCLR:(serial clear) 串行数据清空。
RCLK:(register clock) 寄存器时钟,决定数据输出与否
SRCLK:(serial clock )串行时钟,决定上升沿移位频率
SER: 串行数据,具体数据输入端
主要通过对RCLK、SRCLK、SER这三个串口赋值来进行数据输入,而OE和SRCLR对硬件进行处理。
在这里插入图片描述
串行输入:

数据”个别地“输入,每次输入一位传输到寄存器,(通过对SE赋值,输入数据。SERCLK=1,进行上升沿移位,将数据输入寄存器中)。
并行输出:

数据”整体地“输出,八位为整体同时输出给另一端(当所有8位数据进入寄存器中,令RCLK=1进行上升沿锁存)。

上升沿移位:由串行时钟控制,时钟每到达计时点一次(SERCLK值变为1),寄存器中的数据整体下移一位。
上升沿锁存:由寄存器时钟控制,时钟每到达计时点一次(RCLK值变为1),寄存器中数据同时输出到“Q端”。

七、DS1302

1.简介

DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时且具有闺年补偿等多种功能。掉电后能继续工作
RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片

单片机的定时器与DS1302相比,会占用CPU时间、精确度也较低、且掉电后无法继续运行,故不能断电。
而DS1302时钟芯片带有一个备用电池,当单片机断电时,它内部逻辑判断会将供电源切换到备用电池上,保证时间继续运行,因此单片机下次上电时所显示时间仍然正确。

2.应用电路

在这里插入图片描述

VCC2:主电源
VCC1:备用电池
GND:电源地
SCLK:串行时钟
X1、X2:32.768KHz(更适合于该芯片,精度更高)晶振,全称为石英晶体增长器
CE:芯片使能
I/O:数据输入/输出
SCLK:串行时钟
CE、I/O、SCLK为通信引脚。

3.寄存器

在这里插入图片描述
在这里插入图片描述

第二幅图介绍的是命令字,通过对命令字赋值从而判断时钟是读出数据还是写入数据。命令字启动每一次数据传输。MSB(位7)必须是逻辑1.如果是0,则禁止对DS1302进行写入.位6在逻辑0时规定为时钟/日历数据,逻辑1是为RAM数据.位1到位5表示了输入输出的指定寄存器.LSB(位0)在逻辑0时为写操作(输出),逻辑1时为读操作(输入).命令字以LSB(位0)开始总是输入。

第一幅图:为时钟芯片中命令字与具体数据的对应关系
WP:Write Protect 写入保护,当WP为逻辑1时,无法写入数据,但可读出
CH:时钟暂停,置1时时钟停止运行,置0时正常运转
12/24:置1时小时最高到12,置0时24小时制
AM/PM:当12小时制时,此位置0显示AM,置1显示PM

4.BCD码

BCD(Binary Coded Decimal),用4位二进制数来表示1位十进制数
例:00010011表示13,1000 0101表示85,0001 1010不合法
在十六进制写法中的体现:0x13表示13,0x85表示85,0x1A不合法
BCD码转十进制:DEC=BCD/1610+BCD%16:(2位BCD)
十进制转BCD码:BCD=DEC/1016+DEC%10:(2位BCD)

5.时序定义

在这里插入图片描述

CE:即时钟使能,在写入过程中要保持高电平,写入操作结束时清零。
SCLK:给一个固定的时钟,在时钟的上升沿,I/O口中数据被写入,下降沿DS1302会将其数据输出(时钟数据被读出)。
I/O:数据输入端。

CE置1给高电平==>I/O口输入命令字的最低位(判断是写入or读出,决定数据传输模式)==>SCLK给一个固定时钟

而后若为写入操作:
第一个上升沿,RW位数据写入,SCLK置0,第二个上升沿写入次低位数据,循环往复直至写入命令字的最高位。再输入的即所要写入数据的最低位,再同样循环八次就完成了写入操作。

6.具体代码示例

#include <REGX52.H>

sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;  //模块化命名规则
//位变量逻辑判断,非0即真
 
#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[]={19,11,16,12,59,55,6,};//想要在main函数里使用数组需要在.h文件进行声明
 
 /**
  * @brief  初始化函数
  * @param  无
  * @retval 无
  */
void Ds1302_Init(void)
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}
/**
  * @brief  写入数据
  * @param  第一个是命令字地址,第二个使数据
  * @retval 无
  */
void DS1302_WriteByte(unsigned char Command,Data)
{	
	unsigned char i;
	DS1302_CE=1;//由于一开始初始化,使能段要置一
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=1;//上升沿推入数据
		DS1302_SCLK=0;//记得置0
	}
	for(i=0;i<8;i++)
	{
		DS1302_IO=Data&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	DS1302_CE=0;//使能段重新置0
}
/**
  * @brief  读出数据
  * @param  命令字
  * @retval 无
  */
unsigned char DS1302_ReadByte(unsigned char Command)
{	
	unsigned char i=0,Data=0x00;
	Command|=0x01;//由于地址重命名,因为写入地址最低位是0 把他变成1
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=0;
		DS1302_SCLK=1;//与下入不太一样
	}
		
		for(i=0;i<8;i++)
		{
			DS1302_SCLK=1;//给下降沿再读数据//去掉一个脉冲这里要多看
			DS1302_SCLK=0;
			if(DS1302_IO){Data|=(0x01<<i);}
		}
		DS1302_CE=0;
		DS1302_IO=0;//IO口要置0否则错误
		return Data;//记得返回数据
}

void main()
{
	SCK=0;
	RCK=0;

	while(1)
	{
	MetrixLED_Show(0,0x3C);
	MetrixLED_Show(1,0x42);
	MetrixLED_Show(2,0xA9);
	MetrixLED_Show(3,0x85);
	MetrixLED_Show(4,0x85);
	MetrixLED_Show(5,0xA9);
	MetrixLED_Show(6,0x42);
	MetrixLED_Show(7,0x3C);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值