总结:
一、DS1302实时时钟spi时序程序编写
1.底层spi时序编写
2.上层调用(底层时序)程序编写
二、定义数组变量存储时间(秒、分、时、日、月、周、年)时间数据
三、定义ds1302读和写函数
四、定义数码管(SMG)函数
五、主函数调用
编程实例:
/********************* DS1302实时时钟 —— 动态数码管显示 **************************/
/* DS1302的程序设计遵循 底层逻辑 和 上层逻辑。底层逻辑指ds1302的spi时序,上层逻辑指定义新函数并调用底层spi时序并输入数据 */
#include "reg51.h"
// 首先需要定义ds1302管脚
sbit DS1302_IO = P3^4;
sbit DS1302_RST = P3^5;
sbit DS1302_SCLK = P3^6;
//定义 位选 管脚
sbit LSA = P2^0;
sbit LSB = P2^1;
sbit LSC = P2^2;
//define SMG = P0;
typedef unsigned char uchar; //全局变量定义 : 定义名为uchar 的unsigned char 类型的别名变量
// WRITE 要写入ds1302的地址数据数组
uchar code WRITE_RTC_ADDR[7] = {0X80, 0X82, 0X84, 0X86, 0X88, 0X8A, 0X8C};//88 // code 常量数组,数据设定后不再发生改变
// 定义: 全局变量数组 定义要写入ds1302的时间寄存器的数据
//uchar ds1302_time[7] = {0x24, 0x39, 0x11, 0x06, 0x12, 0x02, 0x16};
// read 要读出的数据的地址数据数组
uchar code READ_RTC_ADDR[7] = {0X81, 0X83, 0X85, 0X87, 0X89, 0X8B, 0X8D}; // code 常量数组,数据设定后不再发生改变
//用于保存 读出的时间的数据数组 (全局变量)
uchar time[7] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x23};
// 秒 分 时
//定义数码管段选数组d\位选数组w
uchar code dx_value[16] = {0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0XFe, 0XF6, 0XEe, 0XBe, 0X9c, 0X7a, 0X9e, 0X8e}; //0 - f
void Delay_ds1302_ms(uchar i) //函数用于spi底层时序间隔频率
{
while(i--);
}
void Delay_SMG_ms(uchar i) //函数用于spi底层时序间隔频率
{
while(i--);
}
/*
void Delay900ms(void) //误差 -0.000000000205us 用于串口发送频率
{
unsigned char a,b,c;
for(c=127;c>0;c--)
for(b=128;b>0;b--)
for(a=24;a>0;a--);
}
*/
/* 一.定义底层SPI (也就是ds1302时序,写入ds1302数据)*/
void Ds1302_write_reg(uchar addr, uchar dat)
{
uchar i = 0;
uchar j = 0;
//时序开始
DS1302_SCLK = 0;
Delay_ds1302_ms(3);
DS1302_RST = 0;
Delay_ds1302_ms(3);
DS1302_RST = 1;
Delay_ds1302_ms(3);
// 开始向ds1302写入地址和数据
for(i=0; i<8; i++)
{
DS1302_IO = (addr & 0x01);
addr >>= 1;
DS1302_SCLK = 1;
Delay_ds1302_ms(3);
DS1302_SCLK = 0;
Delay_ds1302_ms(3);
}
for(j=0; j<8; j++) // 循环8次表示8个bit位
{
DS1302_IO = (dat & 0x01);
dat >>= 1;
DS1302_SCLK = 1;
Delay_ds1302_ms(3);
DS1302_SCLK = 0;
Delay_ds1302_ms(3);
}
// 重置spi时序
DS1302_RST = 0;
Delay_ds1302_ms(3);
}
// 定义底层SPI (也就是ds1302时序,下降沿时读出ds1302发出的数据)
uchar Ds1302_READ_reg(uchar addr)
{
uchar i = 0;
uchar j = 0;
uchar dat = 0;
uchar value = 0;
//ds1302 spi时序开始
DS1302_SCLK = 0;
Delay_ds1302_ms(3);
DS1302_RST = 0;
Delay_ds1302_ms(3);
DS1302_RST = 1;
Delay_ds1302_ms(3);
// 写入ds1302的地址数据
for(i=0; i<8; i++)
{
DS1302_IO = (addr & 0x01);
addr >>= 1;
DS1302_SCLK = 1;
Delay_ds1302_ms(3);
DS1302_SCLK = 0;
Delay_ds1302_ms(3);
}
//读取ds1302发出的地址数据
for(j=0; j<8; j++)
{
dat = DS1302_IO;
value |= (dat << j);
DS1302_SCLK = 1;
Delay_ds1302_ms(3);
DS1302_SCLK = 0;
Delay_ds1302_ms(3);
}
// 重置spi时序
DS1302_RST = 0;
Delay_ds1302_ms(3);
DS1302_SCLK = 1;
Delay_ds1302_ms(3);
// 解决读取时间是FF的问题
DS1302_IO = 0;
return value;
}
/* 二.定义上层函数:定义函数将数据 写入 ds1302函数 与 定义函数使单片机 读出 ds1302的时间数据 */
// 写入ds1302数据初始化函数
void ds1302_write_time(void)
{
uchar i = 0;
// 定义数组用于write函数数据输入
// uchar ds1302_time[7] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x23};
Ds1302_write_reg(0x8E, 0X00); // 关闭保护
for(i=0; i<7; i++)
{
Ds1302_write_reg(WRITE_RTC_ADDR[i], time[i]);
}
Ds1302_write_reg(0x8E, 0X80);//打开保护
}
//读出ds1302数据
void ds1302_read_time(void)
{
uchar i = 0;
for(i=0; i<7; i++) // 7次循环表示7个时间寄存器
{
time[i] = Ds1302_READ_reg(READ_RTC_ADDR[i]); //读出7个时间寄存器的值 并用time【】数组保存
}
}
// 三、定义数码管读取函数 value[]:段选 addr:位选
void SMG_display(uchar dat[])
{
uchar i = 0;
for(i=0; i<8; i++)
{
switch(i) // 定义位选循环与选择
{
case 0: LSC=0; LSB=0; LSA=0; break;
case 1: LSC=0; LSB=0; LSA=1; break;
case 2: LSC=0; LSB=1; LSA=0; break;
case 3: LSC=0; LSB=1; LSA=1; break;
case 4: LSC=1; LSB=0; LSA=0; break;
case 5: LSC=1; LSB=0; LSA=1; break;
case 6: LSC=1; LSB=1; LSA=0; break;
case 7: LSC=1; LSB=1; LSA=1; break;
}
P0 = dat[i]; //定义数码管段选函数
Delay_SMG_ms(100);
P0 = 0x00; //消隐
}
}
/* 四、 主函数主程序调用 */
void main(void)
{
// 1.先定义一个数组用于存储BCD码转换出来的数组元素
uchar time_buf[8];
// 2.需要调用写时间函数
ds1302_write_time();
while(1)
{
// 3.调用读出时间函数
ds1302_read_time();
// 4.1302读出的数据是bcd码,将bcd码转换成smg对应数组数据元素后赋值新数组
time_buf[0] = dx_value[ time[2] >> 4 ];
time_buf[1] = dx_value[ time[2] & 0x0f ];
time_buf[2] = 0x02;
// 时
time_buf[3] = dx_value[ time[1] >> 4 ];
time_buf[4] = dx_value[ time[1] & 0x0f ];
time_buf[5] = 0x02;
// 分
time_buf[6] = dx_value[ time[0] >> 4 ];
time_buf[7] = dx_value[ time[0] & 0x0f ];
// 5.调用smg 函数调入段码参数值
SMG_display(time_buf);
}
}