DS1302实时时钟驱动-SPI模拟通讯(上)

写的不知道好不好,有什么不对的地方还请指出,谢了。

1、SPI对于DS1302变相通讯,时钟上升沿从器件接收数据,时钟下降沿CPU发送数据。通讯均为先发送低位最后发送高位。

2、SPI标准通讯有4种模式。

3、SPI接口代码4个:启动信号、结束信号、写1字节、读1字节。

#ifndef __SPI_H__
#define __SPI_H__

#include <reg52.h>

sbit  SCLK=P1^0;//时钟
sbit  IO = P1^1;//数据
sbit  CE = P1^2;//片选、位选、使能

void STATR_SPI(void);	//1、单片机变异SPI通讯启动信号

void STOP_SPI(void);	//2、单片机结束spi通讯

void write_1_byte_SPI(unsigned char);	//3、单片机写一个字节数据,和iic一样,先发送低位数据,最后发送高位数据

unsigned char read_1_byte_SPI(void);	//4、单片机读一个字节数据,和iic一样,先接收低位数据,最后接收高位数据

#endif // !__SPI_H__
//DS1302时钟芯片的跳变均小于1us时间,51单片机最小执行代码位1us时间,故不需要注重时间来的急不急了
#include "SPI.h"
#include "intrins.h" //_nop_();

//CE = 0;	//片选脚
//SCLK = 0;//时钟
//IO = 1;	//数据

//1、单片机变异SPI通讯启动信号
void STATR_SPI(void)
{
	CE = 0;//关闭片选,停止与ds1302通讯或复位
	_nop_();
	SCLK = 0;//时钟关闭停止通讯
	_nop_();
	CE = 1;//启动ds1302开始工作
	_nop_();
}

//2、单片机结束spi通讯
void STOP_SPI(void)
{
	SCLK = 0;//拉低时钟
	_nop_();
	CE = 0;//关闭片选,停止与ds1302通讯
	_nop_();
	IO = 1;//释放数据
	_nop_();
}

//3、单片机写一个字节数据,和iic一样,先发送低位数据,最后发送高位数据
void write_1_byte_SPI(unsigned char dat)
{
	unsigned char i;
	for (i = 0;i < 8;i++)
	{
		SCLK = 0;//准备向总线上写数据
		_nop_();
		IO = dat & 0x01;//数据从最低位开始依次向高位传送到数据线上,循环传送//与运算就是乘法
		_nop_();
		SCLK = 1;//让ds1302开始读取接收数据
		dat >>= 1;//数据向右移动一次
		_nop_();
	}
	//IO = 1;//单片机释放总线  好像不需要,因为DS1302所有命令字节的最高位均为1
}

//4、单片机读一个字节数据,和iic一样,先接收低位数据,最后接收高位数据
unsigned char read_1_byte_SPI(void)
{
	unsigned char i;
	unsigned char dat=0;
	//for (i = 0x01; i != 0x80; i<<=1) //i!=0x80,那意思是只循环7次啊,i=0x80的时候要读取最高位呢,这样直接退出了个屁了
	//实际只读取7位了,高位没有读取到,对于DS1302均没有用到高位,故读一个字节没有问题,但是连续读取就出现问题了。
	for (i = 0x01; i != 0x00; i<<=1) //从低位向高位读取并储存
	{
		SCLK = 0;//开始读取DS1302发送的数据
		if (IO)
		{
			dat |= i;//或运算就是加法
		}
		SCLK = 1;//DS1302发送数据
		_nop_();
	}
	//IO = 1;//在读数据时,由于spi设备发送完数据后会自动释放总线,在这里就先注释掉,只是提醒一下用户
	return dat;//将读取的结果返回函数
}

猜你喜欢

转载自blog.csdn.net/qq_44829055/article/details/107432850