最近闲来无事,调试了一下时钟芯片DS1302程序,挺好使
[复制链接]
调试好使的程序。
以下是调试的主要程序:
#include<avr/io.h> #include<util/delay.h> #include "HW.h"
//#define BURST_MODE
#define DS1302_DDR DDRB #define DS1302_PORT PORTB #define DS1302_PIN PINB #define DS1302_DDRCS DDRD #define DS1302_PORTCS PORTD #define DS1302_CK PB7 #define DS1302_IO PB6 #define DS1302_CE PD2
#define delay_bus(x) _delay_loop_1(x*2)
static inline void ds1302_select(void) { DS1302_PORTCS|=BIT(DS1302_CE); delay_bus(2); }
static inline void ds1302_unselect(void) { DS1302_PORTCS&=~BIT(DS1302_CE); delay_bus(2); }
//实现读一字节时序 static uint8_t ds1302_read_byte(void) { uint8_t i,ret=0; for(i=0;i<8;i++) { ret>>=1; if(DS1302_PIN & BIT(DS1302_IO)) ret|=0x80; //给一脉冲 DS1302_PORT|=BIT(DS1302_CK); delay_bus(1); DS1302_PORT&=~BIT(DS1302_CK); delay_bus(1); } return ret; }
//实现写一字节时序 static void ds1302_write_byte(uint8_t dat) { uint8_t i; //IO口设置为输出 DS1302_DDR|=BIT(DS1302_IO); DS1302_PORT&=~BIT(DS1302_IO);
for(i=0;i<8;i++) { //设置好数据口 if(dat& 0x01) DS1302_PORT|=BIT(DS1302_IO); else DS1302_PORT&=~BIT(DS1302_IO); delay_bus(1); //给一脉冲 DS1302_PORT|=BIT(DS1302_CK); delay_bus(1); DS1302_PORT&=~BIT(DS1302_CK); dat>>=1; } //IO口恢复到输入状态 DS1302_PORT&=~BIT(DS1302_IO); DS1302_DDR&=~BIT(DS1302_IO); delay_bus(1); }
//读寄存器 addr: 0~8 uint8_t rtc_read_reg(uint8_t addr) { uint8_t ret; addr<<=1; addr|=0x81; ds1302_select(); ds1302_write_byte(addr); ret=ds1302_read_byte(); ds1302_unselect(); return ret; }
//写寄存器 void rtc_write_reg(uint8_t addr,uint8_t dat) { addr<<=1; addr|=0x80; ds1302_select(); ds1302_write_byte(addr); ds1302_write_byte(dat); ds1302_unselect(); }
//读RAM //在多字节(BURST)模式下读取 x 长度的数据到buf指向的存储区 //在单字节模式下从地址为x(0~31)的RAM中读一字节存储到buf处 void rtc_read_ram(uint8_t x,uint8_t *buf) { #ifdef BURST_MODE uint8_t i; ds1302_select(); ds1302_write_byte(0xff); //read burts ram for(i=0;i<x;i++) buf=ds1302_read_byte(); ds1302_unselect(); #else x<<=1; x|=0xc1; ds1302_select(); ds1302_write_byte(x); *buf=ds1302_read_byte(); ds1302_unselect(); #endif }
//写RAM //在多字节(BURST)模式下写 x 长度的数据到DS1302内部RAM,从0地址开始写 //在单字节模式下在地址为x(0~31)的RAM片写入一字节数据 void rtc_write_ram(uint8_t x,uint8_t *buf) { #ifdef BURST_MODE uint8_t i; #endif
rtc_write_reg(7,0);//写使能
#ifdef BURST_MODE ds1302_select(); ds1302_write_byte(0xfe); //write burts ram for(i=0;i<x;i++) ds1302_write_byte(buf); ds1302_unselect(); #else x<<=1; x|=0xc0; ds1302_select(); ds1302_write_byte(x); ds1302_write_byte(*buf); ds1302_unselect(); #endif rtc_write_reg(7,0x80);//写禁止 }
//读取时钟 将读取的时钟以小时,分钟,秒的顺序存入time指向的缓冲区 //读出的数据为二进制格式,而非BCD码 void rtc_get_time(uint8_t *time) { uint8_t s,m=0,h;
h=rtc_read_reg(2); if(h & 0x80)//12小时制 { if(h& BIT(4)) m=10; else m=0; if(h&BIT(5)) m+=12; h=m+(h&0x0f); } else //24小时制 { h&=0x3f; h= (h>>4)*10 + (h & 0x0f); } s=rtc_read_reg(0) & 0x7f; m=rtc_read_reg(1) & 0x7f;
time[2]= (s>>4)*10 + (s & 0x0f); time[1]= (m>>4)*10 + (m & 0x0f); time[0]= h; }
//设置时钟,time中的时钟格式为:时,分,秒二进制式 void rtc_set_time(uint8_t *time) { uint8_t h,m,s; h=time[0]%24; m=time[1]%60; s=time[2]%60; //二进制转BCD h=((h/10)<<4) + (h%10); m=((m/10)<<4) + (m%10); s=((s/10)<<4) + (s%10); rtc_write_reg(7,0);//write enable rtc_write_reg(0,s); rtc_write_reg(1,m); rtc_write_reg(2,h); rtc_write_reg(7,0x80);//write disable }
//读日历 将读取的日历以年,月,日的顺序存入date指向的缓冲区 //读出的数据为二进制格式,而非BCD码 void rtc_get_date(uint8_t *date) { uint8_t y,m,d; y=rtc_read_reg(6); m=rtc_read_reg(4)& 0x1f; d=rtc_read_reg(3)& 0x3f; //BCD转二进制 date[0]=(y>>4)*10 + (y&0x0f); date[1]=(m>>4)*10 + (m&0x0f); date[2]=(d>>4)*10 + (d&0x0f); }
//设置日历 void rtc_set_date(uint8_t *date) { uint8_t y,m,d; //二进制转BCD码 y=((date[0]/10)<<4) + (date[0]%10); m=((date[1]/10)<<4) + (date[1]%10); d=((date[2]/10)<<4) + (date[2]%10); //写入DS1302 rtc_write_reg(7,0); rtc_write_reg(6,y); rtc_write_reg(4,m); rtc_write_reg(3,d); rtc_write_reg(7,0x80); }
//读周 void rtc_get_day(uint8_t *day) { *day=rtc_read_reg(5) & 0x07; }
//设置周 void rtc_set_day(uint8_t *day) { rtc_write_reg(7,0); rtc_write_reg(5,(*day)&0x07); rtc_write_reg(7,0x80); }
//初始化接口和各寄存器 void rtc_init(void) { //CE,CK口设置为输出,IO口设置为输入 DS1302_DDRCS |= BIT(DS1302_CE); DS1302_DDR|=BIT(DS1302_CK); DS1302_PORTCS &=~(BIT(DS1302_CE)); DS1302_PORT&=(BIT(DS1302_CK)|BIT(DS1302_IO)); DS1302_DDR&=~BIT(DS1302_IO);
if(rtc_read_reg(0) & 0x80)//如果处于暂停状态 { rtc_write_reg(7,0);//写允许 rtc_write_reg(0,0);//运行 rtc_write_reg(7,0x80);//写保护 } }
|