#include<reg52.h>
#include <intrins.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
sbit SDA=P1^5; //資料
sbit SCK=P1^4; //時鐘
sbit RST=P1^3; //DS1302復位(片選)
uint8 time[7]={0,0,0,0,0,0,0};//秒分時日月周年10-08-15 23:59:50 7代表周日
#define DS1302_W_ADDR 0x80
#define DS1302_R_ADDR 0x81
P1M0 = 0x10; P1M1 = 0x00;
void delay(uint16 n)
{
while(n--);
}
void ds1302_reset()//令SCK=0;RST=1
{
RST=0;//停止資料傳送
SCK=0;//時鐘總線清零
delay(10);
RST=1;//資料操作
}
//寫一個位元組
void ds1302_write_byte(uint8 dat)
{
uint8 i;
for(i=0;i<8;i++)
{
SDA=dat & 0x01;
SCK=1;
delay(20);
SCK=0;
dat>>=1;
delay(20);
}
}
//讀一個位元組
//對于資料輸出:開始的8 個SCLK 周期,輸入一個讀命令位元組,資料位元組在后8 個SCLK周期的下降沿輸出
//注意,第一個資料位元組的第一個下降沿發生后,命令字的最后一位被寫入
//(Note that the first data bit to be transmitted occurs on the first falling edge after the last bit of the command byte is written. ),
//也就是命令位元組最后一個位元組寫入后產生的下降沿使得第一個資料位被讀取
uint8 ds1302_read_byte()
{
uint8 i,dat=0;//用dat存盤讀到的資料
for(i=0;i<8;i++)
{
dat>>=1;
if(SDA==1)
dat=dat | 0x80;//因為從低位開始讀
SCK=1;
delay(20);
SCK=0; //由上面解釋可以知道:我們首先應該判斷 if(SDA==1),然后進行SCK=1,SCK=0
delay(20);
}
return dat;
}
//清除寫保護
void ds1302_clear_WP()
{
ds1302_reset();
RST=1;
ds1302_write_byte(0x8E);//寫入地址
ds1302_write_byte(0x00);//寫入資料
//寫完后
SDA=0;
RST=0;
}
//設定寫保護
void ds1302_set_WP()
{
ds1302_reset();
RST=1;
ds1302_write_byte(0x8E);//寫入地址
ds1302_write_byte(0x80);//寫入資料
//寫完后
SDA=0;
RST=0;
}
//寫入ds1302
void ds1302_write(uint8 addr,uint8 dat)
{
ds1302_reset();
RST=1;
ds1302_write_byte(addr);//寫入地址
ds1302_write_byte(dat);//寫入資料
//寫完后
RST=0;
SDA=0;
}
//從ds1302讀資料
uint8 ds1302_read(uint8 addr)
{
uint8 temp=0;//存盤讀出來的資料
ds1302_reset();
RST=1;
ds1302_write_byte(addr);//寫入地址
temp=ds1302_read_byte();//寫入資料
//寫完后
RST=0;
SDA=0;
return temp;
}
/**
* 設定時鐘資料
其中涉及二進制和BCD轉換 因為ds1302存BCD ,但是機器只認識二進制
例如:存入ds1302為50 0101 0000 那么我們寫入的是ds1302_write(80)
*/
void set_time(uint8 *timedata)
{
uint8 i;
uint8 temp=0;
for(i=0;i<7;i++)
{
temp=timedata[i]/10;
timedata[i]=timedata[i]%10;
timedata[i]=timedata[i]+temp*16;
}
ds1302_clear_WP();//對ds1302操作前先將wp位清零
temp=DS1302_W_ADDR;//寫入起始位置
for(i=0;i<7;i++)
{
ds1302_write(temp,timedata[i]);
temp+=2;
}
ds1302_set_WP();
}
/**
* 讀時鐘資料(BCD格式)
*/
void read_time(uint8 *timedata)
{
uint8 i,temp;
temp=DS1302_R_ADDR;//讀起始位置
for(i=0;i<7;i++)
{
timedata[i]=ds1302_read(temp);
temp+=2;
}
}
/* UART初始化
* 波特率:9600
*/
void uart_init(void)
{
SCON = 0x50;
AUXR |= 0x40;
AUXR &= 0xFE;
TMOD &= 0x0F;
TMOD |= 0x20;
TL1 = 0xDC;
TH1 = 0xDC;
ET1 = 0;
TR1 = 1;
}
/**
* UART發送一位元組
*/
void UART_Send_Byte(uint8 dat)
{
SBUF=dat;
while(TI==0);
TI=0;
}
/**
* 將資料轉換成ASC碼并通過UART發送出去
*/
void UART_Send_Dat(uint8 dat) //注意是關于16取余
{
UART_Send_Byte(dat/16+'0');
UART_Send_Byte(dat%16+'0');
}
void main()
{
uart_init();
set_time(&time); //設定時間值
while(1)
{
read_time(&time); //秒分時日月周年
UART_Send_Dat(time[6]);
UART_Send_Byte('-');
UART_Send_Dat(time[4]);
UART_Send_Byte('-');
UART_Send_Dat(time[3]);
UART_Send_Byte(' ');
UART_Send_Dat(time[2]);
UART_Send_Byte(':');
UART_Send_Dat(time[1]);
UART_Send_Byte(':');
UART_Send_Dat(time[0]);
UART_Send_Byte('\r');
UART_Send_Byte('\n');
delay(100000);
}
}

單片機是STC15W4K56A4,卡一天了也找不出原因,大佬幫忙看看謝謝了
uj5u.com熱心網友回復:
參考下:https://blog.csdn.net/qq_29246181/article/details/105474102轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/35571.html
標籤:單片機/工控
上一篇:暴力DP背包問題巧解...2020數學建模大賽B題...穿越沙漠
下一篇:日記
