2019-11-09 11:36:18 qq_40574123 阅读数 340

前言

设计一个基本实现密码锁功能的程序开发,作者实测实物有效,且在后来添加了红外功能,其再次可开发性是很好的。采用模块式编程,易懂易理解,作者大二写的,所以可以用作课程设计。

所需基础

1、C语言基础
2、有一点单片机编程语法基础
3、了解AT89C51芯片的管脚分布以及其电平驱动逻辑

工具准备

1、Keil uVision4
2、如果是刚开始学习单片机的伙伴对于89的管脚不是很熟悉的话,建议这个项目还是安装一下Protel99se,这个工具的使用阐述了,网上有很多基础教程,一看就懂。老手跳过。

代码截图

代码截图

模块使用介绍

项目由几个模块组成,如截图所示:LCD1602+24C02+MODIFYKEY+MAIN,1602用于信息的显示,是一块显示屏;24c02是一块小芯片,用于保存密码;modifykey是密码修改模块,将他单独放出也是为了避免一下不必要的错误,main函数主要是键值判断和存储密码。设计不涉及中断,当然你要去加别的模块,当然是需要中断的,不介绍了。
电路图
由于找不到原来的电路图了,只有这个带红外的了,网上找了一张,参考一下,如果代码看懂了,那你也知道哪个线在哪。键盘矩阵的话当时要求自己焊接,但是自己焊接的真的太丑了,不如买一个薄膜的又好看又好用。

必学几部分

接下来就开始讲主要的函数,主要分为:1、键值判断 2、密码修改 3、1602显示屏显示函数 4、24c02存储

键值判断

全局变量定义

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include "i2c.h"
#include "1602.h"	
#include "modifykey.h"

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;
sbit led=P2^2;
sbit Beep_P=P2^4;

u8 p[]={"  pass  "}	;
u8 l[]={"  loss  "}	;  
u8 start[]={"input   password: "} ;
u16 num=0;
u8 keybord,s=0;
u16  passkey=12345;
int adminkey=199607;

键值判断函数Getch

void Getch ( )        //取键值函数
{char a=0,b=0,c=0;
u8 X,Y,Z;
GPIO_KEY=0x0f; //先对P3 置数 行扫描
if(GPIO_KEY!=0x0f) //判断是否有键按下
        {
        delay1(1000); //延时,软件去干扰
        if(GPIO_KEY!=0x0f) //确认按键按下
                {
                X=GPIO_KEY; //保存行扫描时有键按下时状态
                GPIO_KEY=0xf0; //列扫描
                Y=GPIO_KEY;    //保存列扫描时有键按下时状态
                Z=X|Y; //取出键值
/*********************************************************************/
switch ( Z ) //判断键值(那一个键按下)
                        {
                                case 0xeb: keybord=0;num=num*10+keybord;LcdWriteData('*');delay1(1000); break; //对键值赋值
                                case 0x77: keybord=1;num=num*10+keybord;LcdWriteData('*');delay1(1000); break;
                                case 0x7b: keybord=2;num=num*10+keybord;LcdWriteData('*');delay1(1000); break;
                                case 0x7d: keybord=3;num=num*10+keybord;LcdWriteData('*');delay1(1000); break;
                                case 0xb7: keybord=4;num=num*10+keybord;LcdWriteData('*');delay1(1000); break;
                                case 0xbb: keybord=5;num=num*10+keybord;LcdWriteData('*');delay1(1000); break;
                                case 0xbd: keybord=6;num=num*10+keybord;LcdWriteData('*');delay1(1000); break;
                                case 0xd7: keybord=7;num=num*10+keybord;LcdWriteData('*');delay1(1000); break;
                                case 0xdb: keybord=8;num=num*10+keybord;LcdWriteData('*');delay1(1000); break;
                                case 0xdd: keybord=9;num=num*10+keybord;LcdWriteData('*');delay1(1000);break;
								case 0xde: num=num/10;b=0;c=num;LcdWriteCom(0x01);while(c!=0){c=c/10;b++;}for(;b>0;b--){LcdWriteData('*');delay1(1000);}b=0;c=0;break;  //除位
                                case 0x7e: if(num==passkey||num==adminkey){led=1;
								while(p[b]!='\0'){LcdWriteData(p[b]);b++;};delay1(40000);delay1(40000);b=0;delay1(40000);LcdWriteCom(0x01);
								delay1(1000);passkey=modifypassword();storageInit(passkey);delay1(10000);delay1(20000);delay1(20000);delay1(20000);led=0;}
								else {while(l[b]!='\0'){LcdWriteData(l[b]);b++;};MingJiao();delay1(40000);delay1(40000);b=0;delay1(40000);LcdWriteCom(0x01);delay1(1000);}
								num=0;LcdWriteCom(0x01);break; //密码确认
								default : num=num;break;              
                        }
		 while((a<50)&&(GPIO_KEY!=0xf0))	 //检测按键松手检测
			{
				delay1(1000);
				a++;
			}
         } 		
    }
} 		   

头文件意义

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include "i2c.h"
#include "1602.h"	
#include "modifykey.h"

为什么引入头文件,单片机中引入模块,引入函数,就一定引入头文件,因为有哪些函数,用什么格式,针对哪种单片机都是在头文件中定义的,24c02举例,I2C.H

#ifndef __I2C_H_
#define __I2C_H_

#include <reg52.h>

sbit SCL=P2^1;
sbit SDA=P2^0;

void I2cStart();
void I2cStop();
unsigned char I2cSendByte(unsigned char dat);
unsigned char I2cReadByte();
void At24c02Write(unsigned char addr,unsigned char dat);
unsigned char At24c02Read(unsigned char addr);

#endif

声明名称
引入reg52头文件,带入管脚
定义24c02芯片连接管脚,SCL时钟管脚连接2.1,SDA数据管脚连接2.0
定义相关函数
结束定义 endif

typedef 和 sbit方法

typedef用于简化变量的定义,typedef unsigned int u16; 那么 u16 a 等同于 unsigned int a
sbit 定义管脚名称
当然模块头文件也可以声明如此定义,但是不建议,避免不必要的麻烦,建议使用全名,仅仅在main函数去定义,但是这种头文件定义是可以的

//---重定义关键词---//
//#ifndef uchar
//#define uchar unsigned char
//#endif

//#ifndef uint 
//#define uint unsigned int
//#endif

键值判断case 0xeb

那么0xeb怎么来的呢,我们看到电路图,
矩阵键盘
现在我把P17置高电平,也就是置1,当我按下s14的时候,p17和p10之间导通,p10接收到来自于p17的高电平,这时候单片机可以进行判断,if p10 = 1:XXX;而现实中,我们一般将P14到P17置1,P10到P13置0,也就是P1为0x0f,oxfo是转化为2进制也就是:0000 1111;很显然了就,同样电平由于按键更改P1的值也就发生了短暂的变化。

modifykey

一个修改密码的函数为什么要单独拿出来呢,首先是逻辑,先修改临时密码变量,然后再进行判断。其次,加强可读性,最后也是最重要的,当你按键的时候,是两个操作在进行,1、在lcd上显示*表示你键入了一个值,2、在密码变量中保存这个值。同时我们知道这两个操作是没有办法同时进行的,所以分解。

LCD1602、24C02

这两个模块建议单独进行练习和学习,也是很独立的两个模块,别人已经单独给你封装好勒读懂直接用。

学习建议

淘宝买一个开发板进行学习,也就60块钱,不打广告,随便推一个吧,反正客服嗯哼大家也知道,产品无质量问题就行了。https://detail.tmall.com/item.htm?spm=a230r.1.14.15.7f3a4a62vSMiOV&id=36522460231&ns=1&abbucket=8

祝各位学习愉快,代码地址 提取码:f6ax

2016-11-16 11:40:58 sinat_28128937 阅读数 845

  首先,当一个程序有多个源文件(.c)时需要将这些.c文件都添加入工程中一起编译。在做用CVAVR的单片机实验时,CVAVR不会自动加入同目录的.C文件,我因此浪费大量时间在这个问题上。

  切入正题,.h文件内写的是函数的声明和变量的声明。.C文件里是函数的定义和变量的定义。

  一种比较方便的方法是让.h文件成为界面头文件。界面头文件的意义是只要include这个头文件就可以调用头文件爱呢里面所有申明过的函数和变量。然后,为了实现如a.h里的函数,我们在a.c这个源文件里完成对函数的定义。而在实现a.c的过程中又要include其他的头文件,这样多个.h文件就好像提供了相应的服务一样,你要用什么服务就include什么头文件。

  全局变量的声明。在不是定义全局变量的其他文件里若是要访问全局变量,则要加上extern 关键字来声明它。表现全局量一次定义,多次声明的特性。

  全局常量在声明的同时必须初始化。而且允许在不同的源程序分别定义它,使得每个源程序都能携带所要的全局常量。

  在.h文件中利用namespace来命名名空间,用来区分多个.h中出现功能不同的同名函数。以a1::f()和a2::f()来调用不同的f()函数。

  模块化。界面头文件.h的目的是简明的展现对应头文件.c所能提供的功能函数和数据服务。因此,在编程中,第一是要合理的分割程序。把能够反复利用的源程序建立在一个独立的文件里。之后将提供一个具体服务的多个文件组成一个模块。

namespace m1
{
  #include"file1.h"
  #include "file2.h"
}
并且将其命名为“module.h”这要就只要在调用该功能的.c文件里include "module.h" 并using namespace m1;

  当然在面向对象的c++中,头文件一般包含class的内部数据和函数的声明。.c文件里写实现。

2018-04-02 23:13:42 Lzinner 阅读数 1128

2018/4/2

STM32

0.说在前面的前面:

关于MCU(微控制单元(Microcontroller Unit)又称单片微型计算机,简称:单片机

1.说在前面:

时钟系统对于单片机的意义就相当于人类的心跳,时钟系统可以给予单片机一组精准的时序,让单片机可以稳定的工作,同时,可以只开启所使用的时钟,实现低功耗;

2.部分C语言的内容补充

1.#ifdef的用法(在头文件上使用)

预编译指令,用于宏定义,如果使用#ifdef,当某条件实现的时候对一组语句进行编译

#ifndefxxxxx

#define xxxxx

#endif xxxxxx

2.extern 关键字

置于变量和函数前,表示变量和函数可以定义在别的文件上,然而在另外一个文件中进行引用;

注意:可以多次定义,但是只能用一次申明

3.static关键字

具有锁数据的功能,数据不会随着程序的重复性而进行刷新;

3.时间树简介(!!!)

在stm32中有五个时间器,分别为:

3-1.HSI(high speed inter) 高速内部时钟

采用RC振荡器,频率为8mhz

3-2.HSE(high speed extern) 高速外部时钟

可以接石英或者陶瓷谐振器,或者接上外界的时钟源,频率为4mhz到16mhz

3-3.LSI(low speed inter) 低速内部时钟

采用RC振荡器,频率为40khz,可作为看门狗系统的时钟源和RTC(real time clock实时时钟)的时钟源

3-4.LSE(low speed extern)低速外部时钟

接32.768khz的石英晶体,主要作为RTC的时钟源

3-5.PLL:锁环器

实现倍频的功能(从频率*2到*16),通过控制相关寄存器实现,但是输出的频率不能大于72MHZ

4.时间树的一些基础原件

4-1:MCO

MCO是STM32的一种时间输出IO口(PA8),可以选择一个时钟信号输出(PLL的二分频,HSI HSE SYSCLK)

4-2:RTC

RTC作为实时时钟,可以提供一个准确的实时时间

4-3:USBCLK

在使用usb时,一定要让PLL作为时钟源,并且使能为48mhz或者72mhz

4-4:SYSCLK(系统时钟)

1.ABPI分频器:上面连接着一些低速外设(CAN,USB,,UART2.......)

2.ABP2分频器:上面连接着一些高速外设(UART1,Timer1,所有的普通io口(PA到PE)第二功能IO口)

5.简单介绍一下配置:(基于库函数)

1.初始化时间系统

system_stm32f10x.c中的SystemInit()函数中;

2.其他的配置在stm32f10x_rcc.c中

6.最后在说一句:

时钟树图非常重要,所有的寄存器在使用之前必须要使能相应的时钟










2017-07-19 16:26:06 qq_38374864 阅读数 22000

 C语言中没有_nop_()函数。

在51C中一般包含在#include "intrins.h" 头文件中。

该函数是在51单片机中用的延时函数,表示执行一条没有什么意义的指令,延时一个指令周期,有的指令周期是两个或两个以上的机械周期,但是_nop_();指令需要的只是一个机械周期也就是12个时钟周期(震荡周期)。

51单片机中,1个机械周期 = 12个时钟周期 = 12 * ( 1 / f)。(f 为晶振频率)。

如果只用的是12MHZ的晶振,那么 一个机械周期就是1us;也就是说:

_nop_(); 指令的延迟时间为 1us。可以较为精确得控制延迟时间。

nop指令的作用:
1)就是通过nop指令的填充(nop指令一个字节),使指令按字对齐,从而减少取指令时的内存访问次数。(一般用来内存地址偶数对齐,比如有一条指令,占3字节,这时候使用nop指令,cpu 就可以从第四个字节处读取指令了。)
2)通过nop指令产生一定的延迟,但是对于快速的CPU来说效果不明显,可以使用rep前缀,多延迟几个时钟。
3)i/o传输时,也会用一下 nop,等待缓冲区清空,总线恢复;
4)清除由上一个算术逻辑指令设置的flag位; 

2019-03-15 17:19:24 qq_28997735 阅读数 185

题目

在这里插入图片描述
这里初次使用sys.h封装系统使用

关于外部变量注意:

c/c++语言中有很多地方要用到extern,但是如果没有真正的了解它的意义,会给编程带来很大的麻烦,为了使大家少走弯路,特祥细的说明一下。
对于比较小的程序,一般只有一个c文件和一个头文件,全局变量我们通常会直接定义在c文件中,在程序之前加int i定义。如果要在头文件中定义有以下两种方法:用extern来声明:extern int i;这一句只是对变量i进行声明,在c文件的程序之前必须加上int i进行定义。extern int i=0;这一句声明和定义都做了。
对于大一点的程序,有很多c文件和头文件,这个时候全局变量就必须在头文件中声明(不需要初始化)然后在一个c文件中定义(该初始化的要初始化)。如果在头文件中定义,则编译的时候会出现重复定义的错误。如果只有头文件中声明就会出现没有定义有警告。
*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
SYMBOL: K
MODULE: 222.obj (222)
出现上述错误则是因为变量k重复定义,把你的头文件中的变量定义前加extern(只是变量声明不用初始化),再在某一个你要调用该变量的c文件的程序之前再定义(注意第一个调用的c文件要负责附带初始化该变量,其他调用的c文件就不需要初始化过程啦)

关于按键:

这里用了定时扫描独立按键,详细说明在这里: 定时扫描独立键盘

代码:

main.c

******************************************************************************
* 文件名:温度记录器
* 描  述:
* 作  者:思索与猫
* 日  期:  19/3/15 
* 备  注: 
*         
******************************************************************************
#include<stc15f2k60s2.h>
#include<sys.h>

uchar temp_range[10];    //使用数组,温度[10]
uchar index = 0;         //索引
uchar mode = 0;			 //模式
bit t_flag = 0;          //读取温度标志位

void main()
{
		CloseFucker();
		Timer0Init();
		while(1)
		{
				if(mode == 1&&t_flag == 1)      //读取温度
				{
						t_flag = 0;
						temp_range[index] = ReadTemp();       //一个一个赋值
						index++;
						if(index >= 10)          //采集到10个温度index复位,进入模式2
						{
								mode = 2;	
								light = 1;          //L1闪烁
								index = 0;														
						}
				}				
				ShowTable();              //显示数码管
				KeyDriver();              //键盘驱动
		}
}

sys.h

#ifndef __SYS_H_
#define __SYS_H_

typedef unsigned char uchar;
typedef unsigned int uint;

#include<stc15f2k60s2.h>
#include<onewire.h>
#include<ds1302.h>

//初始化
void CloseFucker();
void Timer0Init();

//显示
void ShowTable();
void Display();
void ShowLed(uchar led_dat);

//按键
void KeyScan();
void KeyDriver();
void KeyAction(uchar temp);

//外部变量
extern uchar temp_range[];
extern uchar interval[];           
extern uchar length;
extern uchar index;
extern uchar shi,fen,miao;
extern uchar mode;
extern bit t_flag;
extern bit smg_flag;
extern bit led_flag;	
extern bit light;

#endif

sys.c

#include<sys.h>
bit smg_flag;
bit led_flag;
bit light;

void CloseFucker()
{
		P2 = P2&0x1f|0xa0;
		P0 = 0xaf;
		P2 = P2&0x1f;
}

void Timer0Init()		//2ms@12.000MHz
{
		AUXR |= 0x80;		
		TMOD &= 0xF0;		
		TL0 = 0x40;		
		TH0 = 0xA2;		
		TF0 = 0;		
		TR0 = 1;		
		ET0 = 1;
		EA = 1;
}

void T0_time() interrupt 1
{
		static int count = 0, t_count = 0;
		TL0 = 0x40;		
		TH0 = 0xA2;	
		KeyScan();
		Display();
			
		if(++count >= 500)        //1S
		{
				smg_flag = ~smg_flag;
				led_flag = ~led_flag;		
				count = 0;
				t_count++;	
		}
		
		if(mode == 1&&t_count >= length)  //经过length秒,扫描一次温度
		{
				t_count = 0;
				t_flag = 1;
		}
		else if(mode != 1)
		{
				t_count = 0;
				t_flag = 0;
		}
		
		if(mode == 2&&light == 1)        //控制LED灯
		{
				if(led_flag == 1)        //闪烁
				{
						ShowLed(0xfe);
				}
				else if(led_flag == 0)
				{
						ShowLed(0xff);
				}
		}
		else if(light == 0)              //全灭
		{
				ShowLed(0xff);
		}
}

key.c

#include<sys.h>
sbit Key_In_1 = P3^0;
sbit Key_In_2 = P3^1;
sbit Key_In_3 = P3^2;
sbit Key_In_4 = P3^3;

uchar KeySta[4] = {1, 1, 1, 1};
uchar KeyCodeMap[4] = {7, 6, 5, 4};


void KeyDriver()
{
		uchar i = 0;
		static uchar keyback[4] = {1, 1, 1, 1};
		for(i=0; i<4; i++)
		{
				if(KeySta[i] != keyback[i])
				{
						if(KeySta[i] == 1)
						{
								KeyAction(KeyCodeMap[i]);
						}
						keyback[i] = KeySta[i];
				}
		}			
}

void KeyAction(uchar key_value)        //按键
{
		static uchar i = 0;
		if(mode == 0)        //模式0情况下
		{
				if(key_value == 4)      //按下S4,切换温度间隔扫描时间
				{			
						i++;
						i &= 0x03;
						length = interval[i];												
				}
				else if(key_value == 5)     //按下S5,进入模式1
				{
						mode = 1;
						index = 0;
						SetTime(23, 59, 50);      //开始计时
				}
		}
		if(mode == 2)          //模式2情况下
		{
				if(key_value == 6)      //按下s6,L1灭,显示温度
				{
						light= 0;
						index++;
						if(index >= 10)
						{
								index = 0;
						}
				}
				if(key_value == 7)    //按下S7,回到模式0
				{
						mode = 0;
						index = 0;
						i = 0;
				}
		}
}
	
void KeyScan()
{
	    uchar i = 0;
		static KeyBuf[4] = {0xff, 0xff, 0xff, 0xff};
			
		KeyBuf[0] = (KeyBuf[0]<<1)|Key_In_1;
		KeyBuf[1] = (KeyBuf[1]<<1)|Key_In_2;
		KeyBuf[2] = (KeyBuf[2]<<1)|Key_In_3;
		KeyBuf[3] = (KeyBuf[3]<<1)|Key_In_4;
		
		for(i=0; i<8; i++)
		{
				if(KeyBuf[i] == 0x00)
				{
						KeySta[i] = 0;
				}
				else if(KeyBuf[i] == 0xff)
				{
						KeySta[i] = 1;
				}
				else 
				{
						;
				}
		}	
}

display.c

#include<sys.h>

uchar code duan[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40}; //10black,11-
uchar Table[8];
uchar length = 1;
uchar interval[] = {1, 5, 30, 60};
uchar shi,fen,miao;

void Display()
{
		static uchar index = 0;
		P2 = P2&0x1f|0xe0;
		P0 = 0xff;
		P2 = P2&0x1f;
	
		P2 = P2&0x1f|0xc0;
		P0 = 1<<index;
		P2 = P2&0x1f;
	
		P2 = P2&0x1f|0xe0;
		P0 = ~duan[Table[index]];
		P2 = P2&0x1f;
		index++;
		index &= 0x07;
}

void ShowTable()
{
		if(mode == 0)        //模式0界面
		{
				Table[0] = 10;
				Table[1] = 10;
				Table[2] = 10;
				Table[3] = 10;
				Table[4] = 10;
				Table[5] = 11;
				Table[6] = length/10;
				Table[7] = length%10;
		}
		else if(mode == 1)     //模式1界面
		{
				miao = Ds1302_Single_Byte_Read(0x81);
				Ds1302_Single_Byte_Write(0x00,0x00);
				fen = Ds1302_Single_Byte_Read(0x83);
				Ds1302_Single_Byte_Write(0x00,0x00);
				shi = Ds1302_Single_Byte_Read(0x85);
				Ds1302_Single_Byte_Write(0x00,0x00);
			
				Table[0] = shi/16;
				Table[1] = shi%16;
				
				Table[3] = fen/16;
				Table[4] = fen%16;
				
				Table[6] = miao/16;
				Table[7] = miao%16;
				if(smg_flag == 1)
				{
						Table[2] = 11;
						Table[5] = 11;
				}
				else if(smg_flag == 0)
				{
						Table[2] = 10;
						Table[5] = 10;
				}
		}
		else if(mode == 2)    //模式2界面
		{
				Table[0] = 11;
				Table[1] = index/10;
				Table[2] = index%10;
				Table[3] = 10;
				Table[4] = 10;
				Table[5] = 11;
				Table[6] = temp_range[index]/10;
				Table[7] = temp_range[index]%10;
		}
}

void ShowLed(uchar led_dat)     //显示LED灯
{
		P2 = P2&0x1f|0x80;
		P0 = led_dat;
		P2 = P2&0x1f;
}

onewire.h

#ifndef _ONEWIRE_H
#define _ONEWIRE_H

#include "stc15f2k60s2.h"

#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe

sbit DQ = P1^4;

void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
unsigned char ReadTemp();                 //读取温度
#endif

onewire.c

#include "onewire.h"

void Delay_OneWire(unsigned int t)
{
		t *= 12;
		while(t--);
}

bit Init_DS18B20(void)
{
	bit initflag = 0;
	DQ = 1;
	Delay_OneWire(12);
	DQ = 0;
	Delay_OneWire(80); 
	DQ = 1;
	Delay_OneWire(10); 
	initflag = DQ;    
	Delay_OneWire(5);
  
	return initflag;
}

void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

unsigned char ReadTemp()
{
		unsigned char temp;
		unsigned char low,high;
		
		Init_DS18B20();
		Write_DS18B20(0xcc);
		Write_DS18B20(0x44);
		Delay_OneWire(200);
	
		Init_DS18B20();
		Write_DS18B20(0xcc);
		Write_DS18B20(0xbe);
		Delay_OneWire(200);
	
		low = Read_DS18B20();
		high = Read_DS18B20();
	
		temp = high<<4;
		temp |= (low&0xf0)>>4;
		
		return temp;
}

ds1302.h


#ifndef  __DS1302_H__
#define  __DS1302_H__

#include<stc15f2k60s2.h>
#include<intrins.h>
/********************************************************************/ 
sbit SCK=P1^7;		
sbit SD=P2^3;		
sbit RST=P1^3;
/********************************************************************/ 
#define RST_CLR	RST=0	
#define RST_SET	RST=1	

#define SDA_CLR	SD=0	
#define SDA_SET	SD=1	
#define SDA_R	SD	

#define SCK_CLR	SCK=0	
#define SCK_SET	SCK=1	
/********************************************************************/ 
#define ds1302_sec_addr			0x80		
#define ds1302_min_addr			0x82		
#define ds1302_hr_addr			0x84		
#define ds1302_date_addr		0x86		
#define ds1302_month_addr		0x88		
#define ds1302_day_addr			0x8A		
#define ds1302_year_addr		0x8C		

#define ds1302_control_addr		0x8E		
#define ds1302_charger_addr		0x90 		 
#define ds1302_clkburst_addr	0xBE		

extern void Write_Ds1302_Byte(unsigned char dat);

extern unsigned char Read_Ds1302_Byte(void);

extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);

extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);

void SetTime(unsigned char shi, unsigned char fen, unsigned char miao);  //设置时分秒

#endif	 

ds1302.c

#include "ds1302.h"

void Write_Ds1302_Byte(unsigned char dat) 
{
	unsigned char i;
	SCK = 0;
	for (i=0;i<8;i++) 
	{ 
		if (dat & 0x01) 	
		{
			SDA_SET;		
		}
		else 
		{
			SDA_CLR;		
		}		 
		SCK_SET;
		SCK_CLR;		
		dat = dat >> 1; 
	} 
}

unsigned char Read_Ds1302_Byte(void) 
{
	unsigned char i, dat=0;	
	for (i=0;i<8;i++)
	{	
		dat = dat >> 1;
		if (SDA_R) 	 
		{
			dat |= 0x80;
		}
		else 
		{
			dat &= 0x7F;
		}
		SCK_SET;
		SCK_CLR;
	}
	return dat;
}

void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{ 

	RST_CLR;			
	SCK_CLR;			

	RST_SET;			
	addr = addr & 0xFE;	 
	Write_Ds1302_Byte(addr);
	Write_Ds1302_Byte(dat);	
	RST_CLR;				
}

unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp;
	RST_CLR;			
	SCK_CLR;			

	RST_SET;	
	addr = addr | 0x01;	 
	Write_Ds1302_Byte(addr); 
	temp=Read_Ds1302_Byte();
	RST_CLR;	
	return temp;
}

void SetTime(unsigned char shi, unsigned char fen, unsigned char miao)
{
		Ds1302_Single_Byte_Write(0x8e,0x00);
		Ds1302_Single_Byte_Write(0x80,(miao/10)*16+miao);
		Ds1302_Single_Byte_Write(0x82,(fen/10)*16+fen);
		Ds1302_Single_Byte_Write(0x84,(shi/10)*16+shi);
		Ds1302_Single_Byte_Write(0x8e,0x80);
}

一些小知识

阅读数 16698

没有更多推荐了,返回首页