写的不知道好不好,有什么不对的地方还请指出,谢了。
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;//将读取的结果返回函数
}