基于51单片机的SPI总线Word格式文档下载.docx
《基于51单片机的SPI总线Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《基于51单片机的SPI总线Word格式文档下载.docx(17页珍藏版)》请在冰豆网上搜索。
reg51.h>
//包含单片机寄存器的头文件
intrins.h>
//包含_nop_()函数定义的头文件
/*********************************
以下是DS1302芯片的操作程序
**********************************/
unsignedcharcodedigit[10]={"
0123456789"
};
//定义字符数组显示数字
sbitDATA="
P1"
^1;
//位定义1302的数据输出端定义在P1.1引脚
sbitRST="
^2;
//位定义1302的复位端口定义在P1.2引脚
sbitSCLK="
^0;
//位定义1302的时钟输出端口定义在P1.0引脚
/*****************************
函数功能:
延时若干微秒
入口参数:
n
******************************/
voiddelaynus(unsignedcharn)
{
unsignedchari;
for(i=0;
i<
n;
i++)
;
}
/**********************************
向1302写一个字节数据
dat
***********************************/
voidWrite1302(unsignedchardat)
SCLK=0;
//拉低SCLK,为脉冲上升沿写入数据做好准备
delaynus
(2);
//稍微等待,使硬件做好准备
8;
i++)//连续写8个二进制位数据
{
DATA=dat&
0x01;
//取出dat的第0位数据写入1302
SCLK=1;
//上升沿写入数据
//重新拉低SCLK,形成脉冲
dat>
>
=1;
//将dat的各数据位右移1位,准备写入下一个数据位
}
/***********************************************
根据命令字,向1302写一个字节数据
Cmd,储存命令字;
dat,储存待写的数据
************************************************/
voidWriteSet1302(unsignedcharCmd,unsignedchardat)
RST=0;
//禁止数据传递
//确保写数居前SCLK被拉低
RST=1;
//启动数据传输
delaynus
(2);
Write1302(Cmd);
//写入命令字
Write1302(dat);
//写数据
SCLK=1;
//将时钟电平置于已知状态
/********************************
从1302读一个字节数据
出口参数:
*********************************/
unsignedcharRead1302(void)
unsignedchari,dat;
for(i=0;
i++)//连续读8个二进制位数据
//将dat的各数据位右移1位
if(DATA==1)//如果读出的数据是1
dat|=0x80;
//将1取出,写在dat的最高位
//将SCLK置于高电平,为下降沿读出
//稍微等待
//拉低SCLK,形成脉冲下降沿
}
returndat;
//将读出的数据返回
/**********************************************
根据命令字,从1302读取一个字节数据
Cmd出口参数:
**********************************************/
unsignedcharReadSet1302(unsignedcharCmd)
unsignedchardat;
RST=0;
//拉低RST
RST=1;
Write1302(Cmd);
dat=Read1302();
//读出数据
1302进行初始化设置
voidInit_DS1302(void)
{
WriteSet1302(0x8E,0x00);
//写入不保护指令
WriteSet1302(0x80,((0/10)<
<
4|(0%10)));
//写入秒的初始值
WriteSet1302(0x82,((0/10)<
//写入分的初始值
WriteSet1302(0x84,((12/10)<
4|(12%10)));
//写入小时的初始值
WriteSet1302(0x86,((24/10)<
4|(24%10)));
//写入日的初始值
WriteSet1302(0x88,((4/10)<
4|(4%10)));
//写入月的初始值
WriteSet1302(0x8c,((10/10)<
4|(10%10)));
//写入年的初始值
/*******************************
以下是对液晶模块的操作程序
********************************/
sbitRS="
P2"
//寄存器选择位,将RS位定义为P2.0引脚
sbitRW="
//读写选择位,将RW位定义为P2.1引脚
sbitE="
//使能信号位,将E位定义为P2.2引脚
sbitBF="
P0"
^7;
//忙碌标志位,,将BF位定义为P0.7引脚
/*******************************************************************
延时1ms
(3j+2)*i=(3×
33+2)×
10=1010(微秒),可以认为是1毫秒
********************************************************************/
voiddelay1ms()
unsignedchari,j;
10;
for(j=0;
j<
33;
j++)
延时若干毫秒
*******************************/
voiddelaynms(unsignedcharn)
delay1ms();
判断液晶模块的忙碌状态
返回值:
result。
result=1,忙碌;
result=0,不忙
***********************************************************/
bitBusyTest(void)
bitresult;
RS=0;
//根据规定,RS为低电平,RW为高电平时,可以读状态
RW=1;
E=1;
//E=1,才允许读写
_nop_();
//空操作
//空操作四个机器周期,给硬件反应时间
result=BF;
//将忙碌标志电平赋给result
E=0;
//将E恢复低电平
returnresult;
/**************************************************************
将模式设置指令或显示地址写入液晶模块
dictate
***************************************************************/
voidWriteInstruction(unsignedchardictate)
while(BusyTest()==1);
//如果忙就等待
//根据规定,RS和R/W同时为低电平时,可以写入指令
RW=0;
//E置低电平,为了让E从0到1发生正跳变,所以应先置"
0"
//空操作两个机器周期,给硬件反应时间
P0=dictate;
//将数据送入P0口,即写入指令或地址
//E置高电平
//当E由高电平跳变成低电平时,液晶模块开始执行命令
_nop_();
/*********************************************
指定字符显示的实际地址
x
************************************************/
voidWriteAddress(unsignedcharx)
WriteInstruction(x|0x80);
//显示位置的确定方法为"
80H+地址码x"
/***************************************************************
将数据(字符的标准ASCII码)写入液晶模块
y(为字符常量)
******************************************************************/
voidWriteData(unsignedchary)
RS=1;
//RS为高电平,RW为低电平时,可以写入数据
P0=y;
//将数据送入P0口,即将数据写入液晶模块
/*******************************************************
对LCD的显示模式进行初始化设置
*************************************************************/
voidLcdInitiate(void)
delaynms(15);
//首次写指令时应给LCD一段较长的反应时间
WriteInstruction(0x38);
//显示模式设置:
16×
2显示,5×
7点阵,8位数据
delaynms(5);
//给硬件一点反应时间
//连续三次,确保初始化成功
WriteInstruction(0x0c);
显示开,无光标,光标不闪烁
WriteInstruction(0x06);
//显示模式设置:
光标右移,字符不移
WriteInstruction(0x01);
//清屏幕指令,将以前的显示内容清除
以下是1302数据的显示程序
***********************************/
/************************
显示秒
*************************/
voidDisplaySecond(unsignedcharx)
//i,j分别储存秒的十位和个位
i=x/10;
//取十位
j=x%10;
//取个位
WriteAddress(0x49);
//写显示地址,将在第2行第7列开始显示
WriteData(digit[i]);
//将十位数字的字符常量写入LCD
WriteData(digit[j]);
//将个位数字的字符常量写入LCD
delaynms(50);
//延时1ms给硬件一点反应时间
显示分钟
**************************/
voidDisplayMinute(unsignedcharx)
unsignedchari,j;
//i,j分别储存分钟的十位和个位
WriteAddress(0x46);
/*************************
显示小时
***************************/
voidDisplayHour(unsignedcharx)
//i,j分别储存小时的十位和个位
//取十位
//取个位
WriteAddress(0x43);
/*********************
显示日
**********************/
voidDisplayDay(unsignedcharx)
//i,j分别储存日的十位和个位
WriteAddress(0x0d);
//写显示地址,将在第1行第14列开始显示
显示月
************************/
voidDisplayMonth(unsignedcharx)
//i,j分别储存月的十位和个位
WriteAddress(0x0a);
//写显示地址,将在第1行第11列开始显示
/**********************
显示年
***********************/
voidDisplayYear(unsignedcharx)
//i,j分别储存年的十位和个位
WriteAddress(0x07);
//写显示地址,将在第1行第8列开始显示
/***********************
主函数
voidmain(void)
unsignedcharsecond,minute,hour,day,month,year;
//分别储存秒、分、小时,日,月,年
unsignedcharReadValue;
//储存从1302读取的数据
LcdInitiate();
//将液晶初始化
WriteAddress(0);
//写Date的显示地址,将在第1行第1列开始显示
WriteData('
D'
);
//将字符常量写入LCD
a'
t'
e'
:
'
WriteData('
2'
0'
WriteAddress(0x09);
//写年月分隔符的显示地址
-'
WriteAddress(0x0c);
//写月日分隔符的显示地址
WriteAddress(0x45);
//写小时与分钟分隔符的显示地址
WriteAddress(0x48);
//写分钟与秒分隔符的显示地址
Wri