蓝桥杯驱动程序带注释--DS1302

合集下载

ds1302程序及原理图

ds1302程序及原理图

/**************************************************;文件名:DS1302.c;功能:设置时间,然后将时间读出显示在数码管上;硬件描述:PORTD口接数码管的8个笔段; PORTA 0~2及PORTE 0~2分别接6位数码管的位;RC3接SCK,RC4接SDA,RC2接RST*/#include "pic.h"#define uchar unsigned char#define uint unsigned int#define Hidden 16__CONFIG(HS&WDTDIS&LVPDIS); //配置文件,设置为HS方式振荡,禁止看门狗,低压编程关闭ucharDispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x8 6,0x8E,0xFF};uchar BitTab[]={0xfb,0xfd,0xfe};uchar DispBuf[6];#define LSB 0x01#define WrEnDisCmd 0x8e //写允许/禁止指令代码#define WrEnDat 0x00 //写允许数据#define WrDisDat 0x80 //写禁止数据#define OscEnDisCmd 0x80 //振荡器允许/禁止指令代码#define OscEnDat 0x00 //振荡器允许数据#define OscDisDat 0x80 //振荡器禁止数据#define WrMulti 0xbe //写入多个字节的指令代码#define WrSingle 0x84 //写入单个字节的指令代码#define RdMulti 0xbf //读出多个字节的指令代码#define cClk RC3 //与时钟线相连的PIC16F877A芯片的管脚#define cDat RC4 //与数据线相连的PIC16F877A芯片的管脚#define cRst RC2 //与复位端相连的PIC16F877A芯片的管脚#define SCL_CNT TRISC3 //SCL管脚控制位#define SDA_CNT TRISC4 //SDA管脚控制位#define RST_CNT TRISC2 //RST管脚控制位void mDelay(uint DelayTime){ uint temp;for(;DelayTime>0;DelayTime--){ for(temp=0;temp<270;temp++){;}}}void interrupt Disp(){ static uchar dCount; //用作显示的计数器if(TMR1IF==1&&TMR1IE==1)//Timer 1 inetrrupt{TMR1H=-(8000/256);TMR1L=-(8000%256); //重置定时初值}PORTA|=0x07; //关前面的显示PORTE|=0X07; //关前面的显示PORTD=DispTab[DispBuf[dCount]]; //显示第i位显示缓冲区中的内容if(dCount<3)PORTE&=BitTab[dCount]; //第1~3位是由PORTE控制的elsePORTA&=BitTab[dCount-3]; //第4~6位是由PORTA的低3位控制的dCount++;if(dCount==6)dCount=0;TMR1IF=0; //清中断标志}//数码管位 1 2 3 4 5 6//引脚RE0 RE1 RE2 RA2 RA1 RA0//根据这个表,只要改变PORTA&=0xfe,即可点亮任意一个数码管//例:PORTA&=0xfd //点亮第5位数码管// PORTE&=0xfe //点亮第3位数码管void uDelay(uchar i){ for(;i>0;i--){;}}void SendDat(uchar Dat){ uchar i;for(i=0;i<8;i++){cDat=Dat&LSB; //数据端等于tmp数据的末位值Dat>>=1;cClk=1;uDelay(1);cClk=0;}}/*写入1个或者多个字节,第1个参数是相关命令#define WrMulti 0xbe //写入多个字节的指令代码#define WrSingle 0x84 //写入单个字节的指令代码第2个参数是待写入的值第3个参数是待写入数组的指针*/void WriteByte(uchar CmdDat,uchar Num,uchar *pSend){uchar i=0;SDA_CNT=0; //数据端设为输出cRst=0;uDelay(1);cRst=1;SendDat(CmdDat);for(i=0;i<Num;i++){ SendDat(*(pSend+i));}cRst=0;}/*读出字节,第一个参数是命令#define RdMulti 0xbf //读出多个字节的指令代码第2个参数是读出的字节数,第3个是指收数据数组指针*/void RecByte(uchar CmdDat,uchar Num,uchar *pRec){uchar i,j,tmp;SDA_CNT=0; //数据端设为输出cRst=0; //复位引脚为低电平uDelay(1);cClk=0;uDelay(1);cRst=1;SendDat(CmdDat); //发送命令SDA_CNT=1; //数据端设为输入for(i=0;i<Num;i++){ for(j=0;j<8;j++){ tmp>>=1;if(cDat)tmp|=0x80;cClk=1;uDelay(1);cClk=0;}*(pRec+i)=tmp;}uDelay(1);cRst=0;}/*当写保护寄存器的最高位为0时,允许数据写入寄存器。

ds1302的驱动程序

ds1302的驱动程序

#ifndef __ds1302_H#define __ds1302_H/*------宏定义------*/#define uchar unsigned char#define uint unsigned int/******************RTC常量******************/#define TRUE 1#define FALSE 0#define RTC_CLK PD2#define RTC_DATA PD3#define RTC_CS PD4//命令#define RD 0x01 //读出#define WR 0x00 //写入#define C_SEC 0x80 //秒#define C_MIN 0x82 //分#define C_HR 0x84 //时#define C_DAY 0x86 //日#define C_MTH 0x88 //月#define C_WK 0x8A //星期DATE#define C_YR 0x8C //年#define C_WP 0x8E //控制(写保护)#define C_CHARGE 0x90 //涓流充电#define C_BURST 0xBE //时钟多字节//配置#define CLK_HALT 0x80 //停止时钟控制位SECOND bit7#define CLK_START 0x00 //启动时钟#define CHARGE_START 0xa5 //启动涓流充电#define M12_24 0x80 //12/24小时值选择位HOUR bit7 #define PROTECT 0x80 //写保护控制位CONTROL bit7 #define UPROTECT 0x00 //写保护控制位CONTROL bit7 //涓流充电控制常量#define TC_D1R2 0xA5 //high 1 Diode +2K Resistors#define TC_D2R8 0xAB //low 2 Diodes+8K Resistors#define TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00) //RAM 命令#define C_RAMBASE 0xC0 //RAM0~RAM30<<1 地址需左移一位uchar time_1sok;void delay_nus(unsigned int n) //N us延时函数{char i=0;while(n--)for(i=0;i<8;i++);}void delay_nms(unsigned int n) //N ms延时函数{unsigned int i;while(n--)for(i=0;i<1140;i++);}/*******************************************函数名称: DS1302_init功能: 初始化DS1302的数据接口参数: 无返回值: 无/********************************************/void DS1302_portinit(void){DDRD|=BIT(RTC_CLK)|BIT(RTC_DATA)|BIT(RTC_CS);//将时钟端(RTC_CLK)数据端(RTC_DATA)片选端(RTC_CS)设置为输出}/*******************************************函数名称: DS1302_writeB功能: 向DS1302写入一个字节数据(没有RST操作)参数: byte--要写入的数据返回值: 无/********************************************/void DS1302_writeB(uchar byte){uchar i;for(i=0;i<8;i++) //8位数据计数{PORTD&=~BIT(RTC_CLK); //拉低时钟端if(byte&0x01) //当前位是否是1{PORTD|=BIT(RTC_DATA); //当前位是1,拉高数据端}else{PORTD&=~BIT(RTC_DATA); //当前位是0,拉低数据端}delay_nus(10); //调整时钟和脉冲宽度PORTD|=BIT(RTC_CLK); //时钟上升沿(DS1302采样数据)byte>>=1; //数据右移1位,为送出新数据位做准备}}/*******************************************函数名称: DS1302_readB功能: 从DS1302读出一个字节数据(没有RST操作)参数: 无返回值: byte--读出的数据/********************************************/uchar DS1302_readB(void){uchar i,byte=0;DDRD&=~BIT(RTC_DA TA); //将数据端口设置为输入PORTD&=~BIT(RTC_DA TA); //无上拉电阻for(i=0;i<8;i++) //8位数据计数{byte>>=1; //保存读入的数据位PORTD|=BIT(RTC_CLK); //时钟上升沿delay_nus(10); //延时,调整时钟脉冲宽度PORTD&=~BIT(RTC_CLK); //时钟下降沿,DS1302输出数据位delay_nus(10); //等待数据变化(MEGA16太快,必须等待DS1302的数据位输出,否则不能正确读出)if(PIND&BIT(RTC_DA TA)) //当前位是否是高电平{byte|=BIT(PB7); //是高电平就将返回数据的当前位置1}else{byte&=~BIT(PB7); //是低电平就将返回数据的当前位置0}}DDRD|=BIT(RTC_DA TA); //最后将数据端口设置为输出return byte; //返回读出的数据}/*******************************************函数名称: DS1302_writeD功能: 向DS1302的某个地址写入一个字节数据参数: addr--地址值(寄存器或RAM)data--要写入的地址返回值: 无/********************************************/void DS1302_writeD(uchar addr,uchar data){PORTD&=~BIT(RTC_CS); //拉低片选端PORTD&=~BIT(RTC_CLK); //拉低时钟端delay_nus(10);PORTD|=BIT(RTC_CS); //拉高片选端delay_nus(10); //调整片选脉冲DS1302_writeB(addr); //写入操作命令(地址)delay_nus(10);PORTD&=~BIT(RTC_CLK); //拉低时钟端delay_nus(10);DS1302_writeB(data); //写入数据PORTD&=~BIT(RTC_CLK); //拉低时钟端delay_nus(10); //调整片选脉冲PORTD&=~BIT(RTC_CS); //拉低片选端}/******************************************* 函数名称: DS1302_readD功能: 从DS1302的某个地址读出一个字节数据参数: addr--地址值(寄存器或RAM)返回值: data--读出的数据/********************************************/ uchar DS1302_readD(uchar addr){uchar data;PORTD&=~BIT(RTC_CS); //拉低片选端PORTD&=~BIT(RTC_CLK); //拉低时钟端delay_nus(10);PORTD|=BIT(RTC_CS); //拉高片选端delay_nus(10); //调整片选脉冲DS1302_writeB(addr); //写入操作命令(地址)delay_nus(10);data=DS1302_readB(); //读出数据delay_nus(10);PORTD&=~BIT(RTC_CLK); //拉低时钟端PORTD&=~BIT(RTC_CS); //拉低片选端return data; //返回读出的数据}/******************************************* 函数名称: DS1302_setT功能: 设置DS1302的时间参数: ptTimeD--设置时间数组指针返回值: 无/********************************************/ void DS1302_setT(uchar ptTimeD[]){uchar i;uchar addr = 0x80; //写入地址从秒寄存器开始DS1302_writeD(C_WP|WR,UPROTECT); //控制命令,WP位为0,允许写操作delay_nms(5);for(i=0;i<7;i++){DS1302_writeD(addr|WR,ptTimeD[i]); // 秒分时日月星期年addr+=2;delay_nms(1);}DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作}/*******************************************函数名称: DS1302_getT功能: 读取DS1302的当前时间参数: time[]--读取的时间数组返回值: 无/********************************************/void DS1302_getT(uchar time[]){uchar i;////////下面的是单次读写///////////////////////////* uchar addr = 0x80; //读取地址从秒寄存器开始for(i=0;i<7;i++){time[i]=DS1302_readD(addr|RD); // 秒分时日月星期年addr+=2;}*//////////////////////////////////////////////////////////////下面是多字节读取///////////////PORTD&=~BIT(RTC_CS); //拉低片选端delay_nms(10);PORTD|=BIT(RTC_CS); //拉高片选端delay_nms(10); //调整片选脉冲DS1302_writeB(0xbf); // 0xbf:时钟多字节读取命令for (i=0;i<8;i++) //时间数据的存放格式是:{ //秒,分,时,日,月,星期,年,控制time[i]=DS1302_readB(); //【7个数据(BCD格式)+1个控制】}PORTD&=~BIT(RTC_CS); //拉低片选端///////////////////////////////////////////////PORTD&=~BIT(RTC_CLK); //拉低时钟端(时钟端在不操作时为低)}/*******************************************函数名称: DS1302_check功能: 检测DS1302是否正常工作参数: 无返回值: exist--为TRUE为检测到DS1302,为FALSE为没检测到/********************************************/uchar DS1302_check(void){uchar exist;DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令DS1302_writeD(C_RAMBASE|WR,0xA5); //RAM0写入0xA5exist=DS1302_readD(C_RAMBASE|RD); //读取RAM0if(exist==0xA5){exist=TRUE; //如果读取值与写入值相等,返回TRUE }else{exist=FALSE; //如果读取值与写入值不相等,返回FALSE}return exist;}/*******************************************函数名称: DS1302_init功能: 初始化DS1302参数: 无返回值: 无/********************************************/void DS1302_init(void){DS1302_writeD(C_WP|WR,UPROTECT); //写入写允许命令DS1302_writeD(C_SEC|WR,CLK_START); //启动振荡器,DS1302开始工作//DS1302_writeD(C_CHARGE|WR,CHARGE_START);//启动涓流充电DS1302_writeD(C_WP|WR,PROTECT); //控制命令,WP位为1,不允许写操作}/*******************************************函数名称: BCD_ASCII功能: 将压缩BCD码转换成ascii码参数: BCD--将要转换的压缩BCD码ptasc--转换后的ASCII码数组指针返回值: 无/********************************************/void BCD_ASCII(uchar BCD,uchar ptasc[]){ptasc[0]=BCD/16|0x30; //0X58 35 38 //转换十位ptasc[1]=BCD&0x0F|0x30; //转换个位}/***********************************把gettime从十六进制转换为十进制T[]用来寄存转换后的数据***********************************/void change_gettime(uchar gettime[],uchar T[]){uchar i,da;for(i=0;i<7;++i){da=gettime[i]/16;if(da)da*=10;else da=0;da+=gettime[i]%16;T[i]=da;}}/*********************************把十进制转换为13b20显示的十六进制数T[]用来寄存转换后的数据************************************/void change_settime(uchar T[],uchar settime[]){uchar i,da;for(i=0;i<7;++i){da=T[i]/10*16;da+=T[i]%10;settime[i]=da;}}#endif。

DS1302驱动程序

DS1302驱动程序
delay1(10);
}
SDA = 0;
RST = 0; //复位置0,结束突发连写连读
set_ds1302_WP(); //写保护
for (i=0; i<7; i++) // 转化为正常格式
{
tmp = timedata[i] / 16;
timedata[i] = timedata[i] % 16;
}
/**
* 设置写保护
*/
void set_ds1302_WP(void)
{
reset_ds1302();
RST = 1;
write_ds1302_byte(0x8E);
write_ds1302_byte(0x80);
SDA = 0;
RST = 0;
}
for (i=0; i<7; i++) //7组数据秒分时日月周年分别写入寄 //存器中
{
write_ds1302_byte(timedata[i]);
delay1(10);
}
write_ds1302_byte(0); //写入0,
SDA = 0;
RST = 1;
}
/**
* 清除写保护
*/
void clear_ds1302_WP(void)
{
reset_ds1302();
RST = 1;
write_ds1302_byte(0x8E);
write_ds1302_byte(0);
SDA = 0;
RST = 0;
Timer_display(time[2],time[1],time[0]);

DS1302时钟芯片驱动程序

DS1302时钟芯片驱动程序

DS1302时钟芯片驱动程序//DS1302时钟芯片驱动程序#include <reg51.h>//下面是引脚连接关系sbit clock_dat=P1^0;sbit clock_clk=P1^1;sbit clock_clk=P1^2;sbit a0=ACC^0;sbit a1=ACC^1;sbit a2=ACC^2;sbit a3=ACC^3;sbit a4=ACC^4;sbit a5=ACC^5;sbit a6=ACC^6;sbit a7=ACC^7;void clock_out(unsigned char dd) {ACC=dd;clock_dat=a0;clock_clk=1;clock_clk=0; clock_dat=a1;clock_clk=1;clock_clk=0; clock_dat=a2;clock_clk=1;clock_clk=0; clock_dat=a3;clock_clk=1;clock_clk=0; clock_dat=a4;clock_clk=1;clock_clk=0; clock_dat=a5;clock_clk=1;clock_clk=0; clock_dat=a6;clock_clk=1;clock_clk=0; clock_dat=a7;clock_clk=1;clock_clk=0; }unsigned char clock_in(void) {clock_dat=1;a0=clock_dat;clock_clk=1;clock_clk=0;a1=clock_dat; clock_clk=1;clock_clk=0;a2=clock_dat; clock_clk=1;clock_clk=0;a3=clock_dat; clock_clk=1;clock_clk=0;a4=clock_dat; clock_clk=1;clock_clk=0;a5=clock_dat;clock_clk=1;clock_clk=0;a6=clock_dat;clock_clk=1;clock_clk=0;a7=clock_dat;return(ACC);}unsigned char read_clock(unsigned char ord) {unsigned char dd=0;clock_clk=0;clock_rst=0;clock_rst=1;clock_out(ord);dd=clock_in();clock_rst=0;clock_clk=1;return(dd);}void write_clock(unsigned char ord,unsigned char dd) {clock_clk=0;clock_rst=0;clock_rst=1;clock_out(ord);clock_out(dd);clock_rst=0;clock_clk=1;}/*注意事项:1.每次上电,必须把秒寄存器高位(第7位)设置为0,时钟才能走时。

STM32F103驱动DS1302程序(带注释)

STM32F103驱动DS1302程序(带注释)

S T M32F103驱动D S1302程序(带注释) -CAL-FENGHAI-(2020YEAR-YICAI)_JINGBIAN1简介主控芯片是STM32F103ZET6,DS1302模块在某宝购买,测试两个小时,发现一个小时大概差1秒钟。

芯片受温度、电压影响较大。

输出结果用串口打印到串口调试助手。

如果要oled或者其他显示需要转换为十进制。

2.代码部分2.1 led部分------------led.h--------------------#ifndef __LED_H#define __LED_H#include "sys.h"void LED_Init(void);//初始化#endif------------led.c--------------------#include "led.h"//LED IO初始化void LED_Init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//LED0-->PB.5 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度为50MHzGPIO_Init(GPIOB, &GPIO_InitStructure);//根据设定参数初始化GPIOB.5GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB5 输出高}2.2 usart部分---------------usart.h------------------------#ifndef __USART_H#define __USART_H#include "stdio.h"#include "sys.h"void uart_init(u32 bound);void usart1_send_string(u8 *BuffToSend);void usart1_sendbyte(u8 data);#endif---------------usart.c-----------------------#include "sys.h"#include "usart.h"void uart_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Peri ph_GPIOA, ENABLE); //使能USART1,GPIOA时钟//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器//USART 初始化设置USART_ART_BaudRate = bound;//串口波特率USART_ART_WordLength =USART_WordLength_8b;//字长为8位数据格式USART_ART_StopBits =USART_StopBits_1;//一个停止位USART_ART_Parity = USART_Parity_No;//无奇偶校验位USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART1, ENABLE); //使能串口1}//打印字节void usart1_sendbyte(u8 data){USART_SendData(USART1, data);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);}//打印字符串void usart1_send_string(u8 *BuffToSend){u8 i=0;while(BuffToSend[i]!='\0'){USART_SendData(USART1, BuffToSend[i]);while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);i++;}}2.3 ds1302部分---------------ds1302.h-----------------------#ifndef __DS1302_H#define __DS1302_H#include "sys.h"//写年月日时间寄存器#define WriteSecond 0x80#define WriteMinute 0x82#define WriteHour 0x84#define WriteDay 0x86#define WriteMonth 0x88#define writeWeek 0x8a#define writeYear 0x8c//读年月日时间寄存器#define ReadSecond 0x81#define ReadMinute 0x83#define ReadHour 0x85#define ReadDay 0x87#define ReadMonth 0x89#define ReadWeek 0x8b#define ReadYear 0x8d//引脚分配 SDA-PC3 SCL-PC4 RST-PC5#define DS_SDA_IN {GPIOC->CRL&=0XFFFF0FFF;GPIOC->CRL|=(u32)8<<12;}#define DS_SDA_OUT {GPIOC->CRL&=0XFFFF0FFF;GPIOC->CRL|=(u32)3<<12;}#define DS_SDA_DATAGPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3)//SDA#define DS_SDA_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_3)#define DS_SDA_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_3) #define DS_SCK_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_4)//SCL #define DS_SCK_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_4)#define DS_RST_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_5)//CE #define DS_RST_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_5) void ds1302_init(void);void write_one_byte(u8 data);u8 read_one_byte(void);void ds1302_write_data(u8 reg,u8 data);u8 ds1302_read_data(u8 reg);void time_init(void);void time_read(void);u8 hex_to_bcd(u8 hex_data);u8 bcd_to_hex(u8 bcd_data);#endif---------------ds1302.c-----------------------#include "ds1302.h"#include "delay.h"u8 DSsecond,DSminute,DShour,DSweek,DSday,DSmonth,DSyear; u8 time[7]={0x18,0x06,0x10,0x19,0x23,0x59,0x30};//年星期月日时分秒void ds1302_init(){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin =GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);GPIO_ResetBits(GPIOC,GPIO_Pin_5);//CE拉低GPIO_SetBits(GPIOC, GPIO_Pin_3|GPIO_Pin_4); //拉高}//写入一个字节void write_one_byte(u8 data){u8 i;DS_SDA_OUT;for(i=0;i<8;i++){DS_SCK_LOW;if(data&0x01) //从低位开始{DS_SDA_HIGH;}else{DS_SDA_LOW;}delay_us(2);DS_SCK_HIGH;data>>=1;delay_us(2);}}//读一个字节u8 read_one_byte(){u8 i,data;DS_SDA_IN ;for(i=0;i<8;i++){data>>=1;DS_SCK_HIGH;if(DS_SDA_DATA==1){data|=0x80;}else{data&=0x7F;}delay_us(2);DS_SCK_LOW;}return data;}//ds1302写寄存器写数据void ds1302_write_data(u8 reg,u8 data) {DS_SCK_LOW;DS_RST_LOW;//初始rst为低delay_us(2);DS_RST_HIGH;//sck为低时rst才可置高write_one_byte(reg); //sck低到高delay_us(5);DS_SCK_LOW;write_one_byte(data); //sck低到高delay_us(5);//DS_SCK_HIGH;DS_RST_LOW;}//读ds1302寄存器数据u8 ds1302_read_data(u8 reg){u8 temp;DS_SCK_LOW;DS_RST_LOW;//初始rst为低delay_us(2);DS_RST_HIGH;//sck为低时rst才可置高 delay_us(2);write_one_byte(reg); //sck低到高delay_us(5);DS_SCK_LOW;temp=read_one_byte(); //sck由高到低delay_us(5);//DS_SCK_HIGH;DS_RST_LOW;return temp;}u8 hex_to_bcd(u8 hex_data){u8 temp;temp=(hex_data/10*16 + hex_data%10);return temp;}u8 bcd_to_hex(u8 bcd_data){u8 temp;temp=(bcd_data/16*10 + bcd_data%16);return temp;}//time初始化void time_init(){ds1302_write_data(0x8e,0x00);//关闭写保护ds1302_write_data(writeYear ,(time[0]));//写入hex格式数据ds1302_write_data(writeWeek,(time[1]));ds1302_write_data(WriteMonth,(time[2]));ds1302_write_data(WriteDay,(time[3]));ds1302_write_data(WriteHour,(time[4]));ds1302_write_data(WriteMinute,(time[5]));//ds1302_write_data(WriteSecond,(time[6]));//ds1302_write_data(0x8e,0x80);//开启写保护}//读取寄存器时间void time_read(){DSyear=ds1302_read_data(ReadYear);DSweek=ds1302_read_data(ReadWeek);DSmonth=ds1302_read_data(ReadMonth);DSday=ds1302_read_data(ReadDay);DShour=ds1302_read_data(ReadHour);DSminute=ds1302_read_data(ReadMinute);DSsecond=ds1302_read_data(ReadSecond);}2.4主函数---------------main-----------------------#include "sys.h"#include "delay.h"#include "usart.h"#include "led.h"#include "ds1302.h"Extern u8DSsecond,DSminute,DShour,DSweek,DSday,DSmonth,DSyear; int main(void){delay_init();LED_Init();uart_init(115200);ds1302_init();time_init();while(1){time_read();//更新时间usart1_sendbyte(DSyear);usart1_sendbyte(DSmonth);usart1_sendbyte(DSday);usart1_sendbyte(DShour);usart1_sendbyte(DSminute);usart1_sendbyte(DSsecond);usart1_sendbyte(DSweek);GPIO_ResetBits(GPIOB,GPIO_Pin_5); //LED0闪烁delay_ms(250);GPIO_SetBits(GPIOB,GPIO_Pin_5); //delay_ms(250);}}3.结果串口调试助手hex显示,打印的是十六进制数据。

DS1302驱动程序详解1

DS1302驱动程序详解1

DS1302驱动程序详解DS1302引脚介绍特性介绍驱动程序详解sbit IO=P1^0; //DS1302数据线sbit SCLK=P1^1; //DS1302时钟线sbit RST=P1^2; //DS1302复位线uchar WEEK[][4]={"SUN","***","MON","TUS","WEN","THU","FRI","SAT"}; //亦可定义成指针数组*WEEK[]uchar LCD_DSY_BUFFER1[]={"DA TE 00-00-00 "};uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00 "};uchar DateTime[7];void Initialize_LCD();void Display_LCD_String(uchar p,uchar *s);void DelayMS(uint ms);//------------------------------------------------------------------//向DS1302写入一个字节//------------------------------------------------------------------void Write_A_Byte_TO_DS1302(uchar x){uchar i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备for (i=0;i<8;i++){IO=x & 0x01; //取出x的第0位数据写入1302SCLK=1; //上升沿写入数据SCLK=0; //重新拉低SCLK,形成脉冲x >>=1; //将x的各数据位右移1位,准备写入下一个数据位}}//------------------------------------------------------------------//从DS1302读取一个字节,//注意:DS1302中所存放的数据是BCD码,在读写时要注意转换////------------------------------------------------------------------uchar Get_A_Byte_FROM_DS1302(){uchar i,b=0x00;for (i=0;i<8;i++){b |= _crol_((uchar)IO,i);//将uchar类型的IO数据左移i位SCLK=1; //将SCLK置于高电平,为下降沿读出SCLK=0; //时钟下降沿读取}return (b/16)*10+b%16; //将BCD码转换为十进制数}//------------------------------------------------------------------//从DS1302指定位置读取数据//------------------------------------------------------------------ uchar Read_Data(uchar addr){uchar dat;RST=0; //拉低RSTSCLK=0; //确保写数据前SCLK被拉低RST=1; //启动数据传输Write_A_Byte_TO_DS1302(addr); //写入命令字dat=Get_A_Byte_FROM_DS1302();SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递return dat;}//------------------------------------------------------------------//读取当前日期时间//------------------------------------------------------------------ void GetTime(){uchar i,addr =0x81;for (i=0;i<7;i++){DateTime[i] = Read_Data(addr);addr+=2;}}//------------------------------------------------------------------//日期与时间值转换为数字字符//------------------------------------------------------------------ void Format_DataTime(uchar d,uchar *a){a[0]=d/10+'0';a[1]=d%10+'0';}//------------------------------------------------------------------//主程序//------------------------------------------------------------------ void main(){Initialize_LCD();while(1){GetTime();Format_DataTime(DateTime[6],LCD_DSY_BUFFER1+5); //0x8D 年份寄存器Format_DataTime(DateTime[4],LCD_DSY_BUFFER1+8); //0x89 月份寄存器Format_DataTime(DateTime[3],LCD_DSY_BUFFER1+11); //0x87 日期寄存器//星期strcpy (LCD_DSY_BUFFER1+13,WEEK[DateTime[5]]);//将字符串WEEK[DateTime[5]]复制到字符数组LCD_DSY_BUFFER1+13中//0x8B 周日寄存器Format_DataTime(DateTime[2],LCD_DSY_BUFFER2+5); //0x85 小时寄存器Format_DataTime(DateTime[1],LCD_DSY_BUFFER2+8); //0x83 分钟寄存器Format_DataTime(DateTime[0],LCD_DSY_BUFFER2+11); //0x81 秒寄存器Display_LCD_String(0x00,LCD_DSY_BUFFER1); //第一行显示年、月、日、星期几Display_LCD_String(0x40,LCD_DSY_BUFFER2); //第二行显示小时、分钟、秒}}。

DS1302时钟程序(完整版),液晶显示

DS1302时钟程序(完整版),液晶显示

#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar table0[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; //液晶显示数字0——9代码sbit SCLK=P1^0;sbit DATA=P1^1;sbit CE=P1^2;sbit RS=P2^0;sbit RW=P2^1;sbit EN=P2^2;sbit FB=P0^7;sbit start=P1^4;sbit stop=P1^5;uchar i;/*******************延时n微秒函数*****************/void delaynus(uchar n) //n us延时函数{// uchar i;for(i=n;i>0;i--);}/*******************写数据函数*****************/void write1302(uchar add,uchar dat){CE=0;SCLK=0;CE=1;for(i=0;i<8;i++) //写入地址{DATA=add&0x01;SCLK=1;SCLK=0;add>>=1;}for(i=0;i<8;i++) //写入数据{DATA=dat&0x01;SCLK=1;SCLK=0;dat>>=1;}SCLK=1;CE=0;}/*******************读数据函数*****************/uchar read1302(uchar add){uchar dat;CE=0;SCLK=0;CE=1;for(i=8;i>0;i--) //写入地址{DATA=add&0x01;SCLK=1;SCLK=0;add>>=1;}for(i=8;i>0;i--) //读出数据/********************为神马???**************************/{dat>>=1;if(DATA==1)dat=dat|0x80;SCLK=1;SCLK=0;}SCLK=1;CE=0;return dat;}/*******************DS1302初始化函数*****************/void init1302(){uchar flag;flag=read1302(0x81);if(flag&0x80){write1302(0x8e,0x00);write1302(0x80,0x00);write1302(0x82,(((1/10)<<4)|(1%10)));write1302(0x84,(((20/10)<<4)|(20%10)));write1302(0x86,(((19/10)<<4)|(19%10)));write1302(0x88,(((7/10)<<4)|(7%10)));write1302(0x8a,((2/10)<<4)|(2%10));write1302(0x8c,(((11/10)<<4)|(11%10)));write1302(0x90,0xa5); //充电。

DS1302程序

DS1302程序

;1.每次上电,必须把秒寄存器高位(第7位)设置为0,时钟才能走时。

;2.如果需要写入数据和时钟日历信息,必须把“写保护”寄存器设置成为0 ;内存数据定义BitCnt data 30h ; 数据位计数器ByteCnt data 31h ; 数据字节计数器Command data 32h ; 命令字节地址RcvDat DATA 40H ; 接收数据缓冲区XmtDat DATA 50H ; 发送数据缓冲区;端口位定义IO_DATA bit P1.1 ; 数据传送总线SCLK bit P1.0 ; 时钟控制总线RST bit P1.2 ; 复位总线RS EQU P1.3;确定具体硬件的连接方式RW EQU P1.4 ;确定具体硬件的连接方式E EQU P1.5 ;确定具体硬件的连接方式ORG 0000HLJMP START;**************************** ;main programORG 0030HSTART: CLR RSTMOV SP,#2AH;------------------------------------初始化1302-------------------------SET1302:LCALL Write_Multiplebyte;初始化1302,将我们要设定的数据写入CG:LCALL Read_Multiplebyte;将我们设定的数据读出来MOV P3,#10000000BLCALL ENABLEMOV P3,#00011100BLCALL ENABLEMOV P3,#00110000BLCALL ENABLEMOV P3,#01100000BLCALL ENABLEMOV P3,#00000001BLCALL ENABLELCALL STLCDJNB P2.4,SETB_TIMELCALL YSLJMP CGSETB_TIME:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#01110011BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIME1JB P2.5,LJMP_ADDINC 45HLJMP_ADD:JB P2.6,LJMP_SUBBDEC 45HLJMP_SUBB:MOV A,45HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULIMOV A,45HADD A,#6MOV 45H,ACHULI:MOV A,45HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULIMOV A,45HSUBB A,#6MOV 45H,AZAICHULI:LCALL STLCDMOV P3,#01110011BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTTTTLJMP SETB_TIMEOUTPUTTTT:LJMP OUTPUTSETB_TIME1:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#11010011BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIME2JB P2.5,LJMP_ADD1INC 43HLJMP_ADD1:JB P2.6,LJMP_SUBB1DEC 43HLJMP_SUBB1:MOV A,43HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI1MOV A,43HADD A,#6MOV 43H,ACHULI1:MOV A,43HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI1MOV A,43HSUBB A,#6MOV 43H,AZAICHULI1:LCALL STLCDMOV P3,#11010011BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTLJMP SETB_TIME1SETB_TIME2:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#00010011BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIME3JB P2.5,LJMP_ADD2INC 44HLJMP_ADD2:JB P2.6,LJMP_SUBB2DEC 44HLJMP_SUBB2:MOV A,44HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI2MOV A,44HADD A,#6MOV 44H,ACHULI2:MOV A,44HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI2MOV A,44HSUBB A,#6MOV 44H,AZAICHULI2:LCALL STLCDMOV P3,#00010011BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTLJMP SETB_TIME2OUTPUT:LCALL Write_Enable;写允许MOV Command,#0BEh ;命令字节为BEhMOV ByteCnt,#8 ;多字节写入模式此模块为8 个MOV R0,#XmtDat;数据地址覆给R0MOV XmtDat,40H ;秒单元内容为59hMOV XmtDat+1,41H ;分单元内容为59hMOV XmtDat+2,42H ;时单元内容为13hMOV XmtDat+3,43H ;日期单元内容为21hMOV XmtDat+4,44H ;月单元内容为06hMOV XmtDat+5,45H ;星期单元内容为03hMOV XmtDat+6,46H ;年单元内容为00hMOV XmtDat+7,#0 ;写保护单元内容为00hLCALL Send_Byte ;调用写入数据子程序LJMP CGSETB_TIME3:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#10100011BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIME4JB P2.5,LJMP_ADD3INC 46HLJMP_ADD3:JB P2.6,LJMP_SUBB3DEC 46HLJMP_SUBB3:MOV A,46HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI3MOV A,46HADD A,#6MOV 46H,ACHULI3:MOV A,46HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI3MOV A,46HSUBB A,#6MOV 46H,AZAICHULI3:LCALL STLCDMOV P3,#10100011BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTLJMP SETB_TIME3SETB_TIME4:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#11010001BJNB P2.4,SETB_TIME5JB P2.5,LJMP_ADD4INC 40HLJMP_ADD4:JB P2.6,LJMP_SUBB4DEC 40HLJMP_SUBB4:MOV A,40HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI4MOV A,40HADD A,#6MOV 40H,ACHULI4:MOV A,40HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI4MOV A,40HSUBB A,#6MOV 40H,AZAICHULI4:LCALL STLCDMOV P3,#11010001BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTTLJMP SETB_TIME4SETB_TIME5:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#00010001BJNB P2.4,SETB_TIME6JB P2.5,LJMP_ADD5INC 41HLJMP_ADD5:JB P2.6,LJMP_SUBB5DEC 41HLJMP_SUBB5:MOV A,41HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI5MOV A,41HADD A,#6MOV 41H,ACHULI5:MOV A,41HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI5MOV A,41HSUBB A,#6MOV 41H,AZAICHULI5:LCALL STLCDMOV P3,#00010001BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTTLJMP SETB_TIME5OUTPUTT:LJMP OUTPUTSETB_TIME6:LCALL YSMOV P3,#11110000B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV P3,#10100001BLCALL ENABLE;调用写入命令子程序JNB P2.4,SETB_TIMEEJB P2.5,LJMP_ADD6INC 42HLJMP_ADD6:JB P2.6,LJMP_SUBB6DEC 42HLJMP_SUBB6:MOV A,42HMOV B,#16DIV ABMOV A,BCJNE A,#10,CHULI6MOV A,42HADD A,#6MOV 42H,ACHULI6:MOV A,42HMOV B,#16DIV ABMOV A,BCJNE A,#15,ZAICHULI6MOV A,42HSUBB A,#6MOV 42H,AZAICHULI6:LCALL STLCDMOV P3,#10100001BLCALL ENABLE;调用写入命令子程序JNB P2.7,OUTPUTTLJMP SETB_TIME6SETB_TIMEE:LJMP SETB_TIMESend_Byte:CLR RST ;复位引脚为低电平所有数据传送终止NOPCLR SCLK; 清时钟总线NOPSETB RST ;复位引脚为高电平逻辑控制有效NOPMOV A,Command; 准备发送命令字节MOV BitCnt,#08hS_Byte0:RRC A ;将最低位传送给进位位CMOV IO_DATA,C ;位传送至数据总线NOPSETB SCLK ;时钟上升沿发送数据有效NOPCLR SCLK ;清时钟总线DJNZ BitCnt,S_Byte0 ;位传送未完毕则继续NOPS_Byte1: ;准备发送数据MOV A,@R0 ;传送数据过程与传送命令相同MOV BitCnt,#08hS_Byte2:RRC AMOV IO_DATA,CNOPSETB SCLKNOPCLR SCLKDJNZ BitCnt,S_Byte2INC R0 ;发送数据的内存地址加1DJNZ ByteCnt,S_Byte1 ;字节传送未完毕则继续NOPCLR RST ;逻辑操作完毕清RSTRETReceive_Byte:CLR RST ;复位引脚为低电平所有数据传送终止NOPCLR SCLK ;清时钟总线NOPSETB RST ;复位引脚为高电平逻辑控制有效MOV A,Command ;准备发送命令字节MOV BitCnt,#08h ;传送位数为8R_Byte0:RRC A ;将最低位传送给进位位CMOV IO_DATA,C ;位传送至数据总线NOPSETB SCLK ;时钟上升沿发送数据有效NOPCLR SCLK ;清时钟总线DJNZ BitCnt,R_Byte0 ;位传送未完毕则继续NOPR_Byte1: ;准备接收数据CLR A ;清类加器CLR C ;清进位位CMOV BitCnt,#08h ;接收位数为8R_Byte2:NOPMOV C,IO_DATA ;数据总线上的数据传送给CRRC A ;从最低位接收数据SETB SCLK ;时钟总线置高NOPCLR SCLK ;时钟下降沿接收数据有效DJNZ BitCnt,R_Byte2 ;位接收未完毕则继续MOV @R1,A ;接收到的完整数据字节放入接收内存缓冲区INC R1 ;接收数据的内存地址加1DJNZ ByteCnt,R_Byte1 ;字节接收未完毕则继续NOPCLR RST ;逻辑操作完毕清RSTRET;--写保护寄存器操作------------------------------------------ Write_Enable:MOV Command,#8Eh ;命令字节为8EMOV ByteCnt,#1 ;单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#00h ;数据内容为0 写入允许ACALL Send_Byte ;调用写入数据子程序RET;当写保护寄存器的最高位为1 时禁止数据写入寄存器---------------Write_Disable:MOV Command,#8Eh ;命令字节为8EMOV ByteCnt,#1 ;单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#80h ;数据内容为80h 禁止写入ACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处;当把秒寄存器的第7 位时钟停止位设置为0 时起动时钟开始---------Osc_Enable:MOV Command,#80h ; 命令字节为80MOV ByteCnt,#1 ; 单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#00h ;数据内容为0 振荡器工作允许ACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处;当把秒寄存器的第7 位时钟停止位设置为1 时时钟振荡器停止HT1380 进入低功耗方式---------------Osc_Disable:MOV Command,#80h ;命令字节为80MOV ByteCnt,#1 ;单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#80h ;数据内容为80h 振荡器停止ACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处;写入00 年6 月21 日星期三13 时59 分59---------------------Write_Multiplebyte:MOV Command,#0BEh ;命令字节为BEhMOV ByteCnt,#8 ;多字节写入模式此模块为8 个MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#48h ;秒单元内容为59hMOV XmtDat+1,#14h ;分单元内容为59hMOV XmtDat+2,#09h ;时单元内容为13hMOV XmtDat+3,#16h ;日期单元内容为21h MOV XmtDat+4,#15h ;月单元内容为06hMOV XmtDat+5,#05h ;星期单元内容为03h MOV XmtDat+6,#07 ;年单元内容为00hMOV XmtDat+7,#0 ;写保护单元内容为00h ACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处;读出寄存器0-7 的内容程序设置如下Read_Multiplebyte:MOV Command,#0BFh ;命令字节为BFhMOV ByteCnt,#8 ;多字节读出模式此模块为8 个MOV R1,#RcvDat ;数据地址覆给R1ACALL Receive_Byte; 调用读出数据子程序RET; 返回调用本子程序处SSH:MOV B,#16DIV ABMOV 61H,BMOV 62H,AMOV R1,#62HMOV A,@R1MOV DPTR,#TABMOVC A,@A+DPTRMOV P3,ASETB RSCLR RWCLR ELCALL DELAYSETB EMOV A,@R1MOV DPTR,#TABMOVC A,@A+DPTRMOV P3,ASETB RSCLR RWCLR ELCALL DELAYSETB ERETENABLE:CLR RS ;写入控制命令的子程序CLR RWCLR EACALL DELAYSETB ERETDELAY:MOV P3,#0FFH ;判断液晶显示器是否忙的子程序CLR RSSETB RWCLR ENOPSETB EJB P3.0,DELAY ;如果P1.7为高电平表示忙就循环等待RET;写入8 时12 小时模式程序设置如下Write_Singlebyte:MOV Command,#84h ; 命令字节为84hMOV ByteCnt,#1 ; 单字节传送模式MOV R0,#XmtDat ;数据地址覆给R0MOV XmtDat,#88h ;数据内容为88hACALL Send_Byte ;调用写入数据子程序RET ;返回调用本子程序处MOV P3,#00000001B;显示器开、光标开、光标允许闪烁LCALL ENABLE ;调用写入命令子程序MOV A,#0;显示时间字符MOV R7,#0TIME:MOV DPTR,#TAB2MOVC A,@A+DPTRMOV P3,ALCALL CCFF1INC R7MOV A,R7CJNE A,#5,TIMEMOV A,42HLCALL SSHMOV P3,#10110100BLCALL CCFF1MOV A,41HLCALL SSHMOV P3,#10110100BLCALL CCFF1MOV A,40HLCALL SSHMOV P3,#00000011BLCALL ENABLEMOV A,#0;显示日期字符MOV R7,#0DATE:MOV DPTR,#TAB1MOVC A,@A+DPTRMOV P3,ALCALL CCFF1INC R7CJNE A,#5,DATEMOV A,46HLCALL SSHMOV P3,#10110100B LCALL CCFF1MOV A,44HLCALL SSHMOV P3,#10110100B LCALL CCFF1MOV A,43HLCALL SSHMOV P3,#00000100B LCALL CCFF1MOV A,45HLCALL SSHRETYS:MOV R5,#60D2:MOV R6,#50D1: MOV R7,#66DJNZ R7, $DJNZ R6,D1DJNZ R5,D2RETCCFF1:SETB RSCLR RWCLR ELCALL DELAY SETB ERETTAB:DB00001100B,10001100B,01001100B,11001100B,00101100B,10101100B,01101100B,111 01100B,00011100B,10011100B,01110100B,10110100BTAB2:DB 00101010b,10010110b,10110110b,10100110b,01011100bTAB1:DB 00100010b,10000110b,00101110b,10100110b,01011100bEND。

STM32F103驱动DS1302程序(带注释)

STM32F103驱动DS1302程序(带注释)

1简介主控芯片是STM32F103ZET6,DS1302模块在某宝购买,测试两个小时,发现一个小时大概差1秒钟。

芯片受温度、电压影响较大。

输出结果用串口打印到串口调试助手。

如果要oled或者其他显示需要转换为十进制。

2.代码部分2.1 led部分------------led.h--------------------#ifndef __LED_H#define __LED_H#include "sys.h"void LED_Init(void);//初始化#endif------------led.c--------------------#include "led.h"//LED IO初始化void LED_Init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//LED0-->PB.5 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//IO口速度为50MHzGPIO_Init(GPIOB, &GPIO_InitStructure);//根据设定参数初始化GPIOB.5GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB5 输出高}2.2 usart部分---------------usart.h------------------------#ifndef __USART_H#define __USART_H#include "stdio.h"#include "sys.h"void uart_init(u32 bound);void usart1_send_string(u8 *BuffToSend);void usart1_sendbyte(u8 data);#endif---------------usart.c-----------------------#include "sys.h"#include "usart.h"void uart_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Peri ph_GPIOA, ENABLE); //使能USART1,GPIOA时钟//USART1_TX GPIOA.9GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9//USART1_RX GPIOA.10初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC 寄存器//USART 初始化设置USART_ART_BaudRate = bound;//串口波特率USART_ART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_ART_StopBits = USART_StopBits_1;//一个停止位USART_ART_Parity = USART_Parity_No;//无奇偶校验位USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式USART_Init(USART1, &USART_InitStructure); //初始化串口1USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断USART_Cmd(USART1, ENABLE); //使能串口1 }//打印字节void usart1_sendbyte(u8 data){USART_SendData(USART1, data);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);}//打印字符串void usart1_send_string(u8 *BuffToSend){u8 i=0;while(BuffToSend[i]!='\0'){USART_SendData(USART1, BuffToSend[i]);while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);i++;}}2.3 ds1302部分---------------ds1302.h-----------------------#ifndef __DS1302_H#define __DS1302_H#include "sys.h"//写年月日时间寄存器#define WriteSecond 0x80#define WriteMinute 0x82#define WriteHour 0x84#define WriteDay 0x86#define WriteMonth 0x88#define writeWeek 0x8a#define writeYear 0x8c//读年月日时间寄存器#define ReadSecond 0x81#define ReadMinute 0x83#define ReadHour 0x85#define ReadDay 0x87#define ReadMonth 0x89#define ReadWeek 0x8b#define ReadYear 0x8d//引脚分配 SDA-PC3 SCL-PC4 RST-PC5#define DS_SDA_IN {GPIOC->CRL&=0XFFFF0FFF;GPIOC->CRL|=(u32)8<<12;}#define DS_SDA_OUT{GPIOC->CRL&=0XFFFF0FFF;GPIOC->CRL|=(u32)3<<12;}#define DS_SDA_DATA GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3)//SDA#define DS_SDA_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_3)#define DS_SDA_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_3)#define DS_SCK_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_4)//SCL#define DS_SCK_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_4)#define DS_RST_HIGH GPIO_SetBits(GPIOC,GPIO_Pin_5)//CE#define DS_RST_LOW GPIO_ResetBits(GPIOC,GPIO_Pin_5)void ds1302_init(void);void write_one_byte(u8 data);u8 read_one_byte(void);void ds1302_write_data(u8 reg,u8 data);u8 ds1302_read_data(u8 reg);void time_init(void);void time_read(void);u8 hex_to_bcd(u8 hex_data);u8 bcd_to_hex(u8 bcd_data);#endif---------------ds1302.c-----------------------#include "ds1302.h"#include "delay.h"u8 DSsecond,DSminute,DShour,DSweek,DSday,DSmonth,DSyear;u8 time[7]={0x18,0x06,0x10,0x19,0x23,0x59,0x30};//年星期月日时分秒void ds1302_init(){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure);GPIO_ResetBits(GPIOC,GPIO_Pin_5);//CE拉低GPIO_SetBits(GPIOC, GPIO_Pin_3|GPIO_Pin_4); //拉高}//写入一个字节void write_one_byte(u8 data){u8 i;DS_SDA_OUT;for(i=0;i<8;i++){DS_SCK_LOW;if(data&0x01) //从低位开始{DS_SDA_HIGH;}else{DS_SDA_LOW;}delay_us(2);DS_SCK_HIGH;data>>=1;delay_us(2);}}//读一个字节u8 read_one_byte(){u8 i,data;DS_SDA_IN ;for(i=0;i<8;i++){data>>=1;DS_SCK_HIGH;if(DS_SDA_DATA==1){data|=0x80;}else{data&=0x7F;}delay_us(2);DS_SCK_LOW;}return data;}//ds1302写寄存器写数据void ds1302_write_data(u8 reg,u8 data) {DS_SCK_LOW;DS_RST_LOW;//初始rst为低delay_us(2);DS_RST_HIGH;//sck为低时rst才可置高 write_one_byte(reg); //sck低到高delay_us(5);DS_SCK_LOW;write_one_byte(data); //sck低到高delay_us(5);//DS_SCK_HIGH;DS_RST_LOW;}//读ds1302寄存器数据u8 ds1302_read_data(u8 reg){u8 temp;DS_SCK_LOW;DS_RST_LOW;//初始rst为低delay_us(2);DS_RST_HIGH;//sck为低时rst才可置高 delay_us(2);write_one_byte(reg); //sck低到高delay_us(5);DS_SCK_LOW;temp=read_one_byte(); //sck由高到低delay_us(5);//DS_SCK_HIGH;DS_RST_LOW;return temp;}u8 hex_to_bcd(u8 hex_data){u8 temp;temp=(hex_data/10*16 + hex_data%10);return temp;}u8 bcd_to_hex(u8 bcd_data){u8 temp;temp=(bcd_data/16*10 + bcd_data%16);return temp;}//time初始化void time_init(){ds1302_write_data(0x8e,0x00);//关闭写保护ds1302_write_data(writeYear ,(time[0]));//写入hex格式数据ds1302_write_data(writeWeek,(time[1]));ds1302_write_data(WriteMonth,(time[2]));ds1302_write_data(WriteDay,(time[3]));ds1302_write_data(WriteHour,(time[4]));ds1302_write_data(WriteMinute,(time[5]));//ds1302_write_data(WriteSecond,(time[6]));//ds1302_write_data(0x8e,0x80);//开启写保护}//读取寄存器时间void time_read(){DSyear=ds1302_read_data(ReadYear);DSweek=ds1302_read_data(ReadWeek);DSmonth=ds1302_read_data(ReadMonth);DSday=ds1302_read_data(ReadDay);DShour=ds1302_read_data(ReadHour);DSminute=ds1302_read_data(ReadMinute);DSsecond=ds1302_read_data(ReadSecond);}2.4主函数---------------main-----------------------#include "sys.h"#include "delay.h"#include "usart.h"#include "led.h"#include "ds1302.h"Extern u8 DSsecond,DSminute,DShour,DSweek,DSday,DSmonth,DSyear;int main(void){delay_init();LED_Init();uart_init(115200);ds1302_init();time_init();while(1){time_read();//更新时间usart1_sendbyte(DSyear);usart1_sendbyte(DSmonth);usart1_sendbyte(DSday);usart1_sendbyte(DShour);usart1_sendbyte(DSminute);usart1_sendbyte(DSsecond);usart1_sendbyte(DSweek);GPIO_ResetBits(GPIOB,GPIO_Pin_5); //LED0闪烁delay_ms(250);GPIO_SetBits(GPIOB,GPIO_Pin_5); //delay_ms(250);}}3.结果串口调试助手hex显示,打印的是十六进制数据。

ds1302程序

ds1302程序

#include<reg52.h>#define uchar unsigned charsbit RST=P1^2;sbit SDA=P1^1;sbit SCLK=P1^0;sbit rs=P1^3;sbit lcden=P1^4;sbit key1=P3^7;sbit key2=P3^6;sbit key3=P3^5;uchar t,addr,x,y;void delay(unsigned char t){unsigned char i,j;for(i=t;i>0;i--)for(j=110;j>0;j--);}void delayus(unsigned char t1){for(;t1>0;t1--);}void write_com(unsigned char com)//写lcd1602控制命令{rs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_dat(unsigned char dat) //写lcd1602显示数据命令{rs=1;P0=dat;delay(5);lcden=1;delay(5);lcden=0;}void DS1302WriteByte(uchar dat){uchar i;SCLK=0;delayus(2);for(i=0;i<8;i++){SDA=dat&0x01;delayus(2);SCLK=1;delayus(2);SCLK=0;dat>>=1;}}void DS1302Read(uchar cmd) //读ds1302的时间信息并显示出来{uchar dat,a2,i;RST=0;SCLK=0;RST=1;DS1302WriteByte(cmd);delayus(2);for(i=0;i<8;i++){dat>>=1;if(SDA==1)dat|=0x80;SCLK=1;delayus(2);SCLK=0;delayus(2);}SCLK=1;RST=0;if(cmd==0x8b){dat=dat%16;write_dat(0x30+dat);}else{a2=dat%16;dat=dat/16;write_dat(0x30+a2);write_dat(0x30+dat);}}void DS1302Write(uchar cmd, uchar dat) //写时间信息到ds1302 {RST=0;SCLK=0;RST=1;DS1302WriteByte(cmd);DS1302WriteByte(dat);SCLK=1;RST=0;}void init() //初始化部分{P2=0; //关闭锁存器端口write_com(0x01);write_com(0x38);write_com(0x0c);write_com(0x04);DS1302Write(0x8e,0x00);}void key() //按键控制部分{ uchar q;if(key1==0){DS1302Write(0x80,0x80);write_com(0x0f);delay(40);if(key1==0){t++;if(t==9)t=1;switch(t){case 1:write_com(0x85); addr=0x85;break;case 2:write_com(0x88); addr=0x88;break;case 3:write_com(0x8b); addr=0x8b;break;case 4:write_com(0x8e); addr=0x8e;break;case 5:write_com(0xc5); addr=0xc5;break;case 6:write_com(0xc8); addr=0xc8;break;case 7: write_com(0xcb); addr=0xcb;break;case 8: x=x*16+y;DS1302Write(0x80,x);write_com(0x0c);t=0;break;}while(key1==0);x=0;y=0;}}if(key2==0||key3==0){delay(40);if(key2==0){if(t==4)y=0;elsex++;}if(key3==0)y++;switch (t){case 1: if(x==10)x=0;if(y==10)y=0;q=x*16+y;DS1302Write(0x8c,q);break;case 2: if(x==0){if(y==10)y=0;}if(x==1){ if(y==3)y=0;}if(x==2)x=0;q=x*16+y;DS1302Write(0x88,q); break;case 3: if(x==4)x=0;if(y==32)y=0;q=x*16+y;DS1302Write(0x86,q);break;case 4:if(y==8)y=0;q=x*16+y;DS1302Write(0x8a,q); break;case 5: if(x==0||x==1){if(y==10)y=0;}if(x==2){ if(y==4)y=0;}if(x==3)x=0;q=x*16+y;DS1302Write(0x84,q); break;case 6:if(x==6)x=0;if(y==10)y=0;q=x*16+y;DS1302Write(0x82,q);break;case 7: if(x==6)x=0;if(y==10)y=0;q=x*16+y+0x80;DS1302Write(0x80,q);break;}if(addr==0x8e){write_com(addr);write_dat(0x30+y);write_com(addr);}else{write_com(addr);write_dat(0x30+y);write_dat(0x30+x);write_com(addr);}while(key2==0||key3==0);}}void main(){init();while(1){key();if(t==0){write_com(0xcb); // 在第二行显示DS1302Read(0x81); // 读秒write_dat(0x3a);DS1302Read(0x83); // 读分write_dat(0x3a);DS1302Read(0x85); // 读时write_com(0x8e); // 在第一行显示DS1302Read(0x8b); // 读星期write_dat(0x2a);write_dat(' ');DS1302Read(0x87); // 读日write_dat(0x2f);DS1302Read(0x89); // 读月write_dat(0x2f);DS1302Read(0x8d); // 读年write_dat(0x30);write_dat(0x32);} }}。

ds1302中文资料

ds1302中文资料

功能特色:●时钟计数功能,可以对秒、分钟、小时、月、星期、年的计数。

年计数可达到2100年。

●有31*8位的额外数据暂存寄存器●最少I/O引脚传输,通过三引脚控制●工作电压:2.0-5.5V●工作电流小于320 纳安(2.0V)●读写时钟寄存器或内部RAM(31*8位的额外数据暂存寄存)可以采用单字节模式和突发模式●8-pin DIP封装或8-pin SOICs●兼容TTL (5.0V)●可选的工业级别,工作温度-40 – 85摄氏度●兼容DS1202较DS1202增加的功能:1.可通过Vcc1进行涓流充电2.双重电源补给3.备用电源可采用电池或者超级电容(0.1F以上),可以用老式电脑主板上的3.6V充电电池。

如果断电时间较短(几小时或几天)时,就可以用漏电较小的普通电解电容器代替。

100 μF就可以保证1小时的正常走时。

DS1302在第一次加电后,必须进行初始化操作。

初始化后就可以按正常方法调整时间。

功能简述:DS1302包括时钟/日历寄存器和31字节(8位)的数据暂存寄存器,数据通信仅通过一条串行输入输出口。

实时时钟/日历提供包括秒、分、时、日期、月份和年份信息。

闰年可自行调整,可选择12小时制和24小时制,可以设置AM、PM。

只通过三根线进行数据的控制和传递:、、。

通过备用电源可以让芯片在小于1MW的功率下运作。

工作过程:主要工作原理图如Figure 1 所示:移位寄存器,控制逻辑,晶振,时钟和RAM 。

在进行任何数据传输时,必须被制高电平(注意虽然将它置为高电平,内部时钟还是在晶振作用下走时的,此时,允许外部读写数据),在每个SCLK 上升沿时数据被输入,下降沿时数据被输出,一次只能读写一位,适度还是写需要通过串行输入控制指令来实现(也是一个字节),通过8个脉冲便可读取一个字节从而实现串行输入与输出。

最初通过8个时钟周期载入控制字节到移位寄存器。

如果控制指令选择的是单字节模式,连续的8个时钟脉冲可以进行8位数据的写和8位数据的读操作,SCLK 时钟的上升沿时,数据被写入DS1302,SCLK 脉冲的下降沿读出DS1302的数据。

DS1302时钟芯片C51驱动程序

DS1302时钟芯片C51驱动程序

DS1302时钟芯片C51驱动程序/**********************************************程序名称:DS1302时钟芯片C51驱动程序简要说明:read_clockS函数为读取时钟数据调用Set_time即可调整时间并写入DS1302sel为调整标志,可通过外部按键来更改其值来源:整理杜洋程序文档所得**********************************************///定义头文件#include/************************************************************** ****///定义DS1302时钟接口sbit clock_clk = P1 ^ 0; //ds1302_clk(时钟线)sbit clock_dat = P1 ^ 1; //ds1302_dat(数据线)sbit clock_Rst = P1 ^ 2; //ds1302_Rst(复位线)/************************************************************** ****///定义累加器A中的各位sbit a0 = ACC ^ 0;sbit a1 = ACC ^ 1;sbit a2 = ACC ^ 2;sbit a3 = ACC ^ 3;sbit a4 = ACC ^ 4;sbit a5 = ACC ^ 5;sbit a6 = ACC ^ 6;sbit a7 = ACC ^ 7;/************************************************************** ****///定义全局变量unsigned char yy,mo,dd,xq,hh,mm,ss; //定义时间映射全局变量/************************************************************** ****///声明unsigned char clock_in(void);void clock_out(unsigned char dd);void Init_1302(void);unsigned char read_clock(unsigned char ord);void read_clockS(void);void Set_time(unsigned char sel);void write_clock(unsigned char ord, unsigned char dd);/************************************************************** ****///常用时钟数据读取void read_clockS(void){ss = read_clock(0x81); //读取秒数据mm = read_clock(0x83); //读取分钟数据hh = read_clock(0x85); //小时dd = read_clock(0x87); //日mo = read_clock(0x89); //月xq = read_clock(0x8b); //星期yy = read_clock(0x8d); //年}/************************************************************** ****///调时用加1或减1程序void Set_time(unsigned char sel){//根据选择调整的相应项目加1或减1并写入DS1302,sel为调整项标志,通过外部程序来影响它signed char address,item;signed char max,mini;if(sel==6) {address=0x80; max=0;mini=0;} //秒7if(sel==5) {address=0x82; max=59;mini=0;} //分钟6if(sel==4) {address=0x84; max=23;mini=0;} //小时5if(sel==3) {address=0x8a; max=7;mini=1;} //星期4if(sel==2) {address=0x86; max=31;mini=1;} //日3if(sel==1) {address=0x88; max=12;mini=1;} //月2if(sel==0) {address=0x8c; max=99; mini=0;} //年1//读取1302某地址上的数值转换成10进制赋给itemitem=((read_clock(address+1))/16)*10 + (read_clock(address+1))%16;if(ADD_KEY == 0){item++;} //增加键(ADD_KEY)按下,数加1if(DEC_KEY == 0){item--;} //减少键(DEC_KEY)按下,数减 1 if(item>max) item=mini; //查看数值有效范围if(itemwrite_clock(0x8e,0x00); //允许写操作write_clock(address,(item/10)*16+item%10);//转换成16进制写入1302write_clock(0x8e,0x80); //写保护,禁止写操作}/************************************************************** ****///设置1302的初始时间void Init_1302(void)//(2009年1月1日00时00分00秒星期一){write_clock(0x8e,0x00); //允许写操作write_clock(0x8c,0x09); //年write_clock(0x8a,0x01); //星期write_clock(0x88,0x01); //月write_clock(0x86,0x01); //日write_clock(0x84,0x00); //小时write_clock(0x82,0x00); //分钟write_clock(0x80,0x00); //秒write_clock(0x90,0xa5); //充电write_clock(0x8e,0x80); //禁止写操作}/************************************************************** ****///DS1302写数据(底层协议)void write_clock(unsigned char ord, unsigned char dd){clock_clk=0;clock_Rst=0;clock_Rst=1;clock_out(ord);clock_out(dd);clock_Rst=0;clock_clk=1;}/************************************************************** ****///1302驱动程序(底层协议)void clock_out(unsigned char dd){ACC=dd;clock_dat=a0; clock_clk=1; clock_clk=0;clock_dat=a1; clock_clk=1; clock_clk=0;clock_dat=a2; clock_clk=1; clock_clk=0;clock_dat=a3; clock_clk=1; clock_clk=0;clock_dat=a4; clock_clk=1; clock_clk=0;clock_dat=a5; clock_clk=1; clock_clk=0;clock_dat=a6; clock_clk=1; clock_clk=0;clock_dat=a7; clock_clk=1; clock_clk=0;}/************************************************************** ****///DS1302写入字节(底层协议)unsigned char clock_in(void){clock_dat=1;a0=clock_dat;clock_clk=1; clock_clk=0; a1=clock_dat;clock_clk=1; clock_clk=0; a2=clock_dat;clock_clk=1; clock_clk=0; a3=clock_dat;clock_clk=1; clock_clk=0; a4=clock_dat;clock_clk=1; clock_clk=0; a5=clock_dat;clock_clk=1; clock_clk=0; a6=clock_dat;clock_clk=1; clock_clk=0; a7=clock_dat;return(ACC);}/************************************************************** ****///DS1302读数据(底层协议)unsigned char read_clock(unsigned char ord){unsigned char dd=0;clock_clk=0;clock_Rst=0;clock_Rst=1;clock_out(ord);dd=clock_in();clock_Rst=0;clock_clk=1;return(dd);}/************************************************************** ****/。

DS1302驱动程序

DS1302驱动程序

DS1302是课程设计和毕业设计经常用到的时钟芯片,还在愁怎么对DS1302操作吗?那么看完DS1302驱动程序,一切变得那么简单。

DS1302驱动程序://===========DS1302.H================#ifndef _DS1302_H__#define _DS1302_H__//DS1302管脚定义sbit T_IO=P2^6; //位定义1302芯片的接口,数据输出端定义在P2.5引脚sbit T_RST=P2^7; //位定义1302芯片的接口,复位端口定义在P2.6引脚sbit T_CLK=P2^5; //位定义1302芯片的接口,时钟输出端口定义在P2.4引脚//变量定义声明unsigned char TableDs1302[7]={55,59,23,4,3,5,11}; //初始化时时间日期设置//秒分时日月星期年//函数定义声明void Write1302(unsigned char ); //向1302写一个字节数据void WriteSet1302(unsigned char ,unsigned char );//根据命令字,向1302写一个字节数据unsigned char Read1302(void);//从1302读一个字节数据unsigned char ReadSet1302(unsigned char Cmd);//根据命令字从1302读取一个字节数据void InitDS1302(void);//初始化1302void GetTime(void);//获取1302的时间/*****************************************************函数功能:向1302写一个字节数据入口参数:x***************************************************/void Write1302(unsigned char dat){unsigned char i;T_CLK=0; //拉低T_CLK,为脉冲上升沿写入数据做好准备Delay1Us(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续写8个二进制位数据{T_IO=dat&0x01; //取出dat的第0位数据写入1302Delay1Us(2); //稍微等待,使硬件做好准备T_CLK=1; //上升沿写入数据Delay1Us(2); //稍微等待,使硬件做好准备T_CLK=0; //重新拉低T_CLK,形成脉冲dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位}}/*****************************************************函数功能:根据命令字,向1302写一个字节数据入口参数:Cmd,储存命令字;dat,储存待写的数据,为十进制数***************************************************/void WriteSet1302(unsigned char Cmd,unsigned char dat){T_RST=0; //禁止数据传递T_CLK=0; //确保写数居前T_CLK被拉低T_RST=1; //启动数据传输Delay1Us(2); //稍微等待,使硬件做好准备Write1302(Cmd); //写入命令字Write1302((dat/10<<4)|(dat%10)); //写数据T_CLK=1; //将时钟电平置于已知状态T_RST=0; //禁止数据传递}/*****************************************************函数功能:从1302读一个字节数据入口参数:x***************************************************/unsigned char Read1302(void){unsigned char i,dat;Delay1Us(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续读8个二进制位数据{dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位if(T_IO==1) //如果读出的数据是1dat|=0x80; //将1取出,写在dat的最高位T_CLK=1; //将T_CLK置于高电平,为下降沿读出Delay1Us(2); //稍微等待T_CLK=0; //拉低T_CLK,形成脉冲下降沿Delay1Us(2); //稍微等待}return dat; //将读出的数据返回}/*****************************************************函数功能:根据命令字,从1302读取一个字节数据入口参数:Cmd***************************************************/unsigned char ReadSet1302(unsigned char Cmd){unsigned char temp,dat1,dat2;T_RST=0; //拉低T_RSTT_CLK=0; //确保写数居前T_CLK被拉低T_RST=1; //启动数据传输Write1302(Cmd); //写入命令字temp=Read1302(); //读出数据T_CLK=1; //将时钟电平置于已知状态T_RST=0; //禁止数据传递dat1=temp/16; //16进制转成BCDdat2=temp%16;temp=dat1*10+dat2; //转换成10进制数字return (temp); //将读出的数据返回}/*****************************************************函数功能: 1302进行初始化设置***************************************************/void InitDS1302(void){unsigned char i,add;add=0x80;WriteSet1302(0x8e,0x00); //允许写入for(i=0;i<7;i++){WriteSet1302(add,TableDs1302[i]);add+=2;}WriteSet1302(0x90,0xa6); //写充电控制寄存器.WriteSet1302(0x8e,0x80); //禁止写入}/*****************************************************程序功能:获取DS1302时间*****************************************************/void GetTime(){unsigned char i,add=0x81;WriteSet1302(0x8e,0x00); //允许向DS1302写入数据for(i=0;i<7;i++){TableDs1302[i]=ReadSet1302(add); //获得的数据已转换为十进制add+=2;}WriteSet1302(0x8e,0x80); //获取完一次时间,禁止向DS1302写入数据,提高可靠}endif。

蓝桥杯单片机训练[4]---DS1302时钟芯片

蓝桥杯单片机训练[4]---DS1302时钟芯片

蓝桥杯单⽚机训练[4]---DS1302时钟芯⽚DS1302是由美国DALLAS公司推出的具有涓细电流充电能⼒的低功耗实时时钟芯⽚。

它可以对年、⽉、⽇、周、时、分、秒进⾏计时,且具有闰年补偿等多种功能。

单⽚机与DS1302通过SPI协议进⾏通信,LSB先⾏,由于举办⽅会提供SPI驱动,⾥⾯读写时序给的很明⽩,关于SPI协议这⾥就不具体讲了,我们下⾯只关注如何使⽤这个芯⽚。

RTC寄存器如下:注意:(1)DS1302采⽤的BCD码,写⼊和读出时需要进⾏转化!(2)CH为时钟暂停标志,置0时钟开始计时(3)WP为写保护位,置0时才可以写⼊数据我们需要实现的功能简单来说就两个1.初始化时间2.读取时间1.我们想要配置初始时间,⾸先要将写保护(WP)关掉,即将8Eh地址最⾼位置零,然后就可以愉快的往时分秒寄存器写相应时间啦,这时要⾮常注意,上⾯RTC寄存器数据是以BCD码进⾏存储的,因此必须将我们的数转为BCD码。

举个栗⼦,我们平常接触到的⼗进制数23,等价于20+3,⽽其BCD码直接就是0x23,就是把⼗位和各位分别放到⾼四位和低四位。

初始化代码如下:void Ds1302_write(u8 h,u8 m,u8 s){Write_Ds1302_Byte(0x8e,0x00); //关闭写保护Write_Ds1302_Byte(0x84,h/10*16+h%10); //时Write_Ds1302_Byte(0x82,m/10*16+m%10); //分Write_Ds1302_Byte(0x80,s/10*16+s%10); //秒Write_Ds1302_Byte(0x8e,0x80); //开启写保护}以BCD码写⼊数据⼤概也就执⾏上⾯⼀次,⽽我们从寄存器把时间读回来却⼀直都是BCD码,⾮常不⽅便,⼀次还得整个函数:u8 bcd_to_dat(u8 n) //传⼊BCD码返回⼗进制数{u8 t1,t2;t1=n/16,t2=n%16;t1=t1*10+t2;return t1;}好了,在上⾯进⾏时间的初始化后,我们就可以愉快的读取时间啦,这⾥时分秒被保存在全局变量中,⽅⾯调⽤。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档