可以。
下面是一个利用ds1302在1602液晶上显示数字钟的论文,希望对你有用。
/
文件名 : 时钟DS1302LCDc
/
#include<reg52h>
#include<intrinsh>
#define uchar unsigned char
#define uint unsigned int
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
sbit P3_2 = P3^2;
sbit P3_5 = P3^4;
sbit T_CLK = P1^6; /实时时钟时钟线引脚 /
sbit T_IO = P3^5; /实时时钟数据线引脚 /
sbit T_RST = P1^7; /实时时钟复位线引脚 /
//这三个引脚参考资料
sbit E=P2^7; //1602使能引脚
sbit RW=P2^6; //1602读写引脚
sbit RS=P2^5; //1602数据/命令选择引脚
/
名称 : delay()
功能 : 延时,延时时间大概为140US。
输入 : 无
输出 : 无
/
void delay()
{
int i,j;
for(i=0; i<=10; i++)
for(j=0; j<=2; j++)
;
}
/
名称 : enable(uchar del)
功能 : 1602命令函数
输入 : 输入的命令值
输出 : 无
/
void enable(uchar del)
{
P0 = del;
RS = 0;
RW = 0;
E = 0;
delay();
E = 1;
delay();
}
/
名称 : write(uchar del)
功能 : 1602写数据函数
输入 : 需要写入1602的数据
输出 : 无
/
void write(uchar del)
{
P0 = del;
RS = 1;
RW = 0;
E = 0;
delay();
E = 1;
delay();
}
/
名称 : L1602_init()
功能 : 1602初始化,请参考1602的资料
输入 : 无
输出 : 无
/
void L1602_init(void)
{
enable(0x01);
enable(0x38);
enable(0x0c);
enable(0x06);
enable(0xd0);
}
/
名称 : L1602_char(uchar hang,uchar lie,char sign)
功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
L1602_char(1,5,'b')
输入 : 行,列,需要输入1602的数据
输出 : 无
/
void L1602_char(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
write(sign);
}
/
名称 : L1602_string(uchar hang,uchar lie,uchar p)
功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
L1602_string(1,5,"ab cd ef;")
输入 : 行,列,需要输入1602的数据
输出 : 无
/
void L1602_string(uchar hang,uchar lie,uchar p)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
enable(a);
while(1)
{
if(p == '\0') break;
write(p);
p++;
}
}
/
名称 : v_RTInputByte()
功能 : 往DS1302写入1Byte数据
输入 : ucDa 写入的数据
输出 : 无
/
void v_RTInputByte(uchar ucDa)
{
uchar i;
ACC = ucDa;
T_RST = 1;
for(i=8; i>0; i--)
{
T_IO = ACC0;
T_CLK = 1;
T_CLK = 0;
ACC = ACC >> 1;
}
}
/
名称 : uc_RTOutputByte()
功能 : 从DS1302读取1Byte数据
输入 : 无
返回值: ACC
/
uchar uc_RTOutputByte(void)
{
uchar i;
T_RST = 1;
for(i=8; i>0; i--)
{
ACC = ACC >>1;
T_IO=1;
ACC7 = T_IO;
T_CLK = 1;
T_CLK = 0;
}
return(ACC);
}
/
名称 : v_W1302(uchar ucAddr, uchar ucDa)
功能 : 往DS1302写入数据
输入 : ucAddr: DS1302地址, ucDa: 要写的数据
返回值 : 无
/
void v_W1302(uchar ucAddr, uchar ucDa)
{
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); // 写地址
_nop_();
_nop_();
v_RTInputByte(ucDa); // 写1Byte数据
T_CLK = 1;
T_RST = 0;
}
/
名称 : uc_R1302(uchar ucAddr)
功能 : 读取DS1302某地址的数据
输入 : ucAddr: DS1302地址
返回值 : ucDa :读取的数据
/
uchar uc_R1302(uchar ucAddr)
{
uchar ucDa;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(ucAddr); //写地址,命令
_nop_();
_nop_();
ucDa = uc_RTOutputByte(); //读1Byte数据
T_CLK = 1;
T_RST = 0;
return(ucDa);
}
/
名称 : v_BurstW1302T
功能 : 往DS1302写入时钟数据(多字节方式)
输入 : pSecDa: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年 控制
8Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B 1B
返回值 : 无
/
void v_BurstW1302T(uchar pSecDa)
{
uchar i;
v_W1302(0x8e, 0x00); //控制命令,WP=0,写 *** 作
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(0xbe); //0xbe:时钟多字节写命令
for(i=8; i>0; i--) //8Byte = 7Byte 时钟数据 + 1Byte 控制
{
v_RTInputByte(pSecDa); //写1Byte数据
pSecDa++;
}
T_CLK = 1;
T_RST = 0;
}
/
名称 : v_BurstR1302T(uchar pSecDa)
功能 : 读取DS1302时钟数据
输入 : pSecDa: 时钟数据地址 格式为: 秒 分 时 日 月 星期 年
7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
返回值 : ucDa :读取的数据
/
void v_BurstR1302T(uchar pSecDa)
{
uchar i;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(0xbf); //0xbf:时钟多字节读命令
for(i=8; i>0; i--)
{
pSecDa = uc_RTOutputByte(); //读1Byte数据
pSecDa++;
}
T_CLK = 1;
T_RST = 0;
}
/
名称 : v_BurstW1302R(uchar pReDa)
功能 : 往DS1302寄存器数写入数据(多字节方式)
输入 : pReDa: 寄存器数据地址
返回值 : 无
/
void v_BurstW1302R(uchar pReDa)
{
uchar i;
v_W1302(0x8e,0x00); //控制命令,WP=0,写 *** 作
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(0xfe); //0xbe:时钟多字节写命令
for(i=31; i>0; i--) //31Byte 寄存器数据
{
v_RTInputByte(pReDa); //写1Byte数据
pReDa++;
}
T_CLK = 1;
T_RST = 0;
}
/
名称 : v_BurstR1302R(uchar pReDa)
功能 : 读取DS1302寄存器数据
输入 : pReDa: 寄存器数据地址
返回值 : 无
/
void v_BurstR1302R(uchar pReDa)
{
uchar i;
T_RST = 0;
T_CLK = 0;
T_RST = 1;
v_RTInputByte(0xff); //0xbf:时钟多字节读命令
for(i=31; i>0; i--) //31Byte 寄存器数据
{
pReDa = uc_RTOutputByte(); //读1Byte数据
pReDa++;
}
T_CLK = 1;
T_RST = 0;
}
/
名称 : v_Set1302(uchar pSecDa)
功能 : 设置初始时间
输入 : pSecDa: 初始时间地址。初始时间格式为: 秒 分 时 日 月 星期 年
7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
返回值: 无
/
void v_Set1302(uchar pSecDa)
{
uchar i;
uchar ucAddr = 0x80;
v_W1302(0x8e, 0x00); //控制命令,WP=0,写 *** 作
for(i=7; i>0; i--)
{
v_W1302(ucAddr, pSecDa); // 秒 分 时 日 月 星期 年
pSecDa++;
ucAddr += 2;
}
v_W1302(0x8e, 0x80); //控制命令,WP=1,写保护
}
/
名称 : v_Get1302(uchar ucCurtime[])
功能 : 读取DS1302当前时间
输入 : ucCurtime: 保存当前时间地址。当前时间格式为: 秒 分 时 日 月 星期 年
7Byte (BCD码) 1B 1B 1B 1B 1B 1B 1B
返回值 : 无
/
void v_Get1302(uchar ucCurtime[])
{
uchar i;
uchar ucAddr = 0x81;
for(i=0; i<7; i++)
{
ucCurtime[i] = uc_R1302(ucAddr); //格式为: 秒 分 时 日 月 星期 年
ucAddr += 2;
}
}
/
名称 : dectobcd(uchar dec)
功能 : DEC码转换为BCD码
输入 : dec码
输出 : bcd码
/
uchar dectobcd(uchar dec)
{
uchar bcd;
bcd = 0;
while(dec >= 10)
{
dec -= 10;
bcd++;
}
bcd <<= 4;
bcd |= dec;
return bcd;
}
/
名称 : bcdtodec(uchar bcd)
功能 : BCD码转换为DEC码
输入 : bcd码
输出 : dec码
/
uchar bcdtodec(uchar bcd)
{
uchar data1;
data1 = bcd & 0x0f; //取BCD低4位
bcd = bcd & 0x70; //剔除BCD的最高位和低4位。
data1 += bcd >> 1;
data1 += bcd >> 3; //用位移代替乘法运算
return data1;
}
/
名称 : Write_DS1302Init()
功能 : 往DS1302中写入数据。最开始显示的数据就是在这里设置的。
输入 : 无
输出 : 无
/
void Write_DS1302Init(void)
{
v_W1302(0x8e,0);
v_W1302(0x80,0x50); //写入秒
v_W1302(0x8e,0);
v_W1302(0x82,0x59); //写入分
v_W1302(0x8e,0);
v_W1302(0x84,0x07); //写入小时
v_W1302(0x8e,0);
v_W1302(0x86,0x08); //写入日
v_W1302(0x8e,0);
v_W1302(0x88,0x08); //写入月
v_W1302(0x8e,0);
v_W1302(0x8a,0x05); //写入星期
v_W1302(0x8e,0);
v_W1302(0x8c,0x08); //写入年
}
/
名称 : Run_DS1302(void)
功能 : 读出DS1302中的数据,并在液晶1602上进行显示
输入 : 无
输出 : 无
/
void Run_DS1302(void)
{
uchar sec, min, hour, day, month, year;
while(1)
{
v_W1302(0x8f, 0);
sec = bcdtodec(uc_R1302(0x81)); //读出DS1302中的秒
v_W1302(0x8f, 0);
min = bcdtodec(uc_R1302(0x83)); //读出DS1302中的分
v_W1302(0x8f, 0);
hour = bcdtodec(uc_R1302(0x85)); //读出DS1302中的小时
v_W1302(0x8f, 0);
day = bcdtodec(uc_R1302(0x87)); //读出DS1302中的日
v_W1302(0x8f, 0);
month = bcdtodec(uc_R1302(0x89)); //读出DS1302中的月
v_W1302(0x8f, 0);
year = bcdtodec(uc_R1302(0x8d)); //读出DS1302中的年
L1602_char(2, 6, hour / 10 % 10 + 48);
L1602_char(2, 7, hour % 10 + 48);
L1602_char(2, 8, ':');
L1602_char(2, 9, min / 10 % 10 + 48);
L1602_char(2, 10, min % 10 + 48);
L1602_char(2, 11, ':');
L1602_char(2, 12, sec / 10 % 10 + 48);
L1602_char(2, 13, sec % 10 + 48);
L1602_char(1, 8, year / 10 % 10 + 48);
L1602_char(1, 9, year % 10 + 48);
L1602_char(1, 10, '-');
L1602_char(1, 11, month / 10 % 10 + 48);
L1602_char(1, 12, month % 10 + 48);
L1602_char(1, 13, '-');
L1602_char(1, 14, day / 10 % 10 + 48);
L1602_char(1, 15, day % 10 + 48);
}
}
/
名称 : Main(void)
功能 : 主函数
输入 : 无
输出 : 无
/
void Main(void)
{
L1602_init();
L1602_string(1,1,"DAYS 20");
L1602_string(2,1,"TIME");
Write_DS1302Init();
Run_DS1302();
}
SPI通信的时钟速率和通信速率之间是倒数关系,通信速率就是指在时钟速率下,理论上的最大通信速度。因为一个时钟传递一个BIT的数据,假设时钟周期10ms,那么通信速率就是100bps,注意通信速率的单位不是HZ哦,HZ是频率的单位。
以上就是关于STC单片机的SPI功能能不能驱动时钟芯片DS1302全部的内容,包括:STC单片机的SPI功能能不能驱动时钟芯片DS1302、请教用SPI模块进行通讯时的时钟速度设置、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)