欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

51单片机与AVR(SPI)单片机驱动DS1302

发布时间:2023/12/8 42 豆豆
生活随笔 收集整理的这篇文章主要介绍了 51单片机与AVR(SPI)单片机驱动DS1302 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

本代码来源于网络,记录下来怕忘记

CE信号高电平读写数据

读写时前8位为地址位,后8位为数据。在写数据时SCLK为下降沿开始,读数据为上升沿开始读数据。读写都是从D0-D7,且都为BCD码。写入时先将十进制转化为BCD码,在写入寄存器。读取时要把BCD码转化成十进制显示。

int bcd_decimal_code( int bcd) //十进制转BCD {return (bcd + (bcd/10) * 6); } int decimal_bcd_code(int decimal)  //BCD转十进制 {return (decimal - (decimal>>4) * 6); }

51单片机模拟SPI驱动DS1320

#include <reg52.h> #include <intrins.h> #include <LCD1602.h> #define uchar unsigned char #define uint unsigned int sbit SCK_P = P3^6; // 时钟芯片DS1302的SCK管脚 sbit SDA_P = P3^7; // 时钟芯片DS1302的SDA管脚 sbit RST_P = P3^5; // 时钟芯片DS1302的RST管脚 sbit key = P1^7; uchar TimeBuff_write[7]={17,9,1,6,18,30,40}; // 时间数组 uchar TimeBuff[7] ={ 0,0,0,0, 0, 0, 0}; // TimeBuff[0] 代表年份,范围00-99 // TimeBuff[1] 代表月份,范围1-12 // TimeBuff[2] 代表日期,范围1-31 // TimeBuff[3] 代表星期,范围1-7 // TimeBuff[4] 代表小时,范围00-23 // TimeBuff[5] 代表分钟,范围00-59 // TimeBuff[6] 代表秒钟,范围00-59/*********************************************************/ // 初始化DS1302 /*********************************************************/ void DS1302_Init(void) {RST_P=0; // RST脚置低 SCK_P=0; // SCK脚置低 SDA_P=0; // SDA脚置低 } /*********************************************************/ // 从DS1302读出一字节数据 /*********************************************************/ uchar DS1302_Read_Byte(uchar addr) { uchar i; uchar temp; RST_P=1; /* 写入目标地址:addr*/ for(i=0;i<8;i++) { if(addr&0x01) SDA_P=1; else SDA_P=0; SCK_P=1; _nop_(); SCK_P=0; _nop_(); addr=addr>> 1; } /* 读出该地址的数据 */ for(i=0;i<8;i++) { temp=temp>>1; if(SDA_P) temp|= 0x80; else temp&=0x7F; SCK_P=1; _nop_(); SCK_P=0; _nop_(); } RST_P=0; return temp; } /*********************************************************/ // 向DS1302写入一字节数据 /*********************************************************/ void DS1302_Write_Byte(uchar addr, uchar dat) { uchar i; RST_P = 1; /* 写入目标地址:addr*/ for(i=0;i<8;i++) { if(addr&0x01) SDA_P=1; else SDA_P=0; SCK_P=1; _nop_(); SCK_P=0; _nop_(); addr=addr>>1; } /* 写入数据:dat*/ for(i=0;i<8;i++) { if(dat&0x01) SDA_P=1; else SDA_P=0; SCK_P=1; _nop_(); SCK_P=0; _nop_(); dat=dat>>1; } RST_P=0; } /*********************************************************/ // 向DS1302写入时间数据 /*********************************************************/ void DS1302_Write_Time() { uchar i; uchar temp1; uchar temp2; for(i=0;i<7;i++) // 十进制转BCD码 { temp1=(TimeBuff_write[i]/10)<<4; temp2=TimeBuff_write[i]%10; TimeBuff_write[i]=temp1+temp2; } DS1302_Write_Byte(0x8E,0x00); // 关闭写保护DS1302_Write_Byte(0x80,0x80); // 暂停时钟 DS1302_Write_Byte(0x8C,TimeBuff_write[0]); // 年 DS1302_Write_Byte(0x88,TimeBuff_write[1]); // 月 DS1302_Write_Byte(0x86,TimeBuff_write[2]); // 日 DS1302_Write_Byte(0x8A,TimeBuff_write[3]); // 星期 DS1302_Write_Byte(0x84,TimeBuff_write[4]); // 时 DS1302_Write_Byte(0x82,TimeBuff_write[5]); // 分 DS1302_Write_Byte(0x80,TimeBuff_write[6]); // 秒 DS1302_Write_Byte(0x80,TimeBuff_write[6]&0x7F); // 运行时钟 DS1302_Write_Byte(0x8E,0x80); // 打开写保护 } /*********************************************************/ // 从DS1302读出时间数据 /*********************************************************/ void DS1302_Read_Time() { uchar i; TimeBuff[0]=DS1302_Read_Byte(0x8D); // 年 TimeBuff[1]=DS1302_Read_Byte(0x89); // 月 TimeBuff[2]=DS1302_Read_Byte(0x87); // 日 TimeBuff[3]=DS1302_Read_Byte(0x8B); // 星期 TimeBuff[4]=DS1302_Read_Byte(0x85); // 时 TimeBuff[5]=DS1302_Read_Byte(0x83); // 分 TimeBuff[6]=(DS1302_Read_Byte(0x81))&0x7F; // 秒 for(i=0;i<7;i++) // BCD转十进制 { TimeBuff[i]=(TimeBuff[i]/16)*10+TimeBuff[i]%16; } } void delay10ms(void) //误差 0us {unsigned char a,b,c;for(c=1;c>0;c--)for(b=38;b>0;b--)for(a=130;a>0;a--); } void main() { uchar bcd=55; init1602();DS1302_Init();key=1;while(1){DS1302_Read_Time();disp1602(0,0,TimeBuff[4]/10+'0');disp1602(0,1,TimeBuff[4]%10+'0');disp1602(0,2,'-');disp1602(0,3,TimeBuff[5]/10+'0');disp1602(0,4,TimeBuff[5]%10+'0');disp1602(0,5,'-');disp1602(0,6,TimeBuff[6]/10+'0');disp1602(0,7,TimeBuff[6]%10+'0');if(key==0){delay10ms();while(key==0); // bcd=(bcd + (bcd/10) * 6); //单独写一个寄存器 // DS1302_Write_Byte(0x82, bcd);//0x82为时寄存器,向时寄存器写入55DS1302_Write_Time() ; //写入一组预设的数据}} }

按键之后

 AVR SPI驱动DS1302

/** DS1302.h** Created: 2022/2/1 17:23:34* Author: admin*/ #ifndef DS1302_H_ #define DS1302_H_ #include <avr/io.h> #include <avr/delay.h> #include <GPIO_IO.h> unsigned char CURDATE[7];//读写操作位 #define CMD_READ 0x01 #define CMD_WRITE 0x00 //时钟 命令 #define CMD_SECOND 0x80 //秒 #define CMD_MINUTE 0x82 //分 #define CMD_HOUR 0x84 //时 #define CMD_DAY 0x86 //日 #define CMD_MONTH 0x88 //月 #define CMD_WEEK 0x8A //星期 DATE #define CMD_YEAR 0x8C //年 #define CMD_CONTROL 0x8E //控制(写保护) #define CMD_TRICKLE_CHARGE 0x90 //涓流充电 #define CMD_CLOCK_BURST 0xBE //连续读取 //时钟配置常量 #define CFG_CLOCK_HALT 0x80 //停止时钟控制位 SECOND bit7 #define CFG_12_24 0x80 //12/24小时值选择位 HOUR bit7 #define CFG_AM_PM 0x20 //AP/PM位 HOUR bit5 #define CFG_PROTECT 0x80 //写保护控制位 CONTROL bit7 打开写保护 #define CFG_UNPROTECT 0x00 //写保护控制位 CONTROL bit7 关闭写保护 //涓流充电控制常量 #define CFG_TC_D1R2 0xA5 //high 1 Diode +2K Resistors #define CFG_TC_D2R8 0xAB //low 2 Diodes+8K Resistors #define CFG_TC_DISABLED 0x00 //Disabled(TCS<>1010 or DS=00 or RS=00) //RAM 命令 #define CMD_RAM_BASE 0xC0 //RAM0~RAM30<<1 地址需左移一位 #define CMD_RAM_BURST 0xFE //连续读取#endif /* DS1302_H_ */ /** DS1302.c** Created: 2022/2/1 17:22:35* Author: admin*/ #include <DS1302.h> //M328p管脚定义 #define DS1302_CE 2 //PB2 SS 必须设为输出 ----DS1302 pin5 #define DS1302_MOSI 3 //PB3 MOSI要串10K电阻到MISO,然后把MISO跟DS1302_IO脚短接在一起的 #define DS1302_MISO 4 //PB4 MISO跟DS1302_IO脚短接在一起的---DS1302 pin6 #define DS1302_SCK 5 //PB5 SCK----DS1302 pin7//宏定义 #define DiDS1302 GPIO_LOW('B',2) //CE=0 DiDS1302 关闭SPI接口 #define EnDS1302 GPIO_HIGH('B',2) //CE=1 EnDS1302 使能SPI接口unsigned char DS1302_EXIST; unsigned char INITDATE[8]={0x50, //59秒0x59, //59分0x23, //23时 24小时制0x06, //06日0x11, //11月0x04, //星期四0x05, //2005年0x80}; //写保护 unsigned char CURDATE[7]; //CURDATE[6] //年 ,00~10 //CURDATE[4] //月 ,01~12 //CURDATE[3] //日 ,01~31(28/30/31) //CURDATE[2] //时 ,00~23 //CURDATE[1] //分 ,00~59 //CURDATE[0] //秒 ,00~59 //CURDATE[5] //星期 ,1~7 一~日//初始化SPI接口 void init_SPI(void) { PORTB=~((1<<DS1302_CE)|(1<<DS1302_MOSI)|(1<<DS1302_MISO)|(1<<DS1302_SCK));//DS1302带内部下拉电阻 DDRB =(1<<DS1302_CE)|(1<<DS1302_SCK)|(1<<DS1302_MOSI);//设定SPI接口 SPCR = (1<<SPE)|(1<<MSTR)|(1<<DORD)|(1<<SPR0);// 使能SPI接口,主机模式,LSB低位在先,模式0,16分频,SPI时钟约460KHz } /*----------------------------------------------------------------------- Single_SPI : 使用SPI接口读写数据到DS1302输入参数: command: 命令选择;wdata: 写入的数据; 返回值 rdata: 读回的数据; (SPI的收发是同时进行的) -----------------------------------------------------------------------*/ unsigned char Single_SPI(unsigned char command,unsigned char wdata) {unsigned char rdata;EnDS1302; // 使能LCD_delay_us(10);SPDR = command; // 传送命令到SPI寄存器loop_until_bit_is_set(SPSR,SPIF); // 等待数据传送完?_delay_us(10);SPDR = wdata; // 传送数据到SPI寄存器loop_until_bit_is_set(SPSR,SPIF); // 等待数据传送完?rdata=SPDR; // 读取数据DiDS1302; // 关断LCD SPI通讯_delay_us(10);return rdata; }/*----------------------------------------------------------------------- Burst_SPI : 使用SPI接口读写一批数据到DS1302输入参数: CMD: 选择Clock/RAM,选择读写lenth: 数据长度pwdata: 写入数据的缓冲区;prdata: 读回数据的缓冲区; (SPI的收发是同时进行的) 读CLOCK的数据从SECOND寄存器开始,到CONTROL寄存器,最大8字节 写CLOCK的数据必须一次写完8个字节 读写RAM的数据从 RAM0地址开始,到RAM30地址,最大31字节 -----------------------------------------------------------------------*/ void Burst_SPI(unsigned char CMD,unsigned char len,unsigned char *pwdata,unsigned char *prdata) {EnDS1302; // 使能SPI通讯_delay_us(10);SPDR=CMD; // 传送命令到SPI寄存器loop_until_bit_is_set(SPSR,SPIF); // 等待数据传送完?_delay_us(10); while (len--){SPDR = *pwdata++; // 传送数据到SPI寄存器loop_until_bit_is_set(SPSR,SPIF); // 等待数据传送完?*prdata++=SPDR; // 读取数据};DiDS1302; // 关断SPI通讯_delay_us(10); }//初始化DS1302 void DS1302_Write_Time(void) {unsigned char temp[8];Single_SPI(CMD_CONTROL |CMD_WRITE, CFG_UNPROTECT); //写允许INITDATE[1]=44;INITDATE[1]=(INITDATE[1] + (INITDATE[1]/10) * 6);Burst_SPI(CMD_CLOCK_BURST|CMD_WRITE,8,&INITDATE[0],&temp[0]); //初始化时间Single_SPI(CMD_TRICKLE_CHARGE, CFG_TC_D1R2); //涓流充电选择Single_SPI(CMD_CONTROL |CMD_WRITE, CFG_PROTECT); //写保护 } #ifndef F_CPU #define F_CPU 16000000UL #endif#include <avr/io.h> #include <util/delay.h> #include <LCD1602.h> #include <GPIO_IO.h> #include <DS1302.h>int main(void) {uchar i;init1602();init_SPI();DS1302_Write_Time();while (1){ Burst_SPI(CMD_CLOCK_BURST|CMD_READ,7,0,&CURDATE[0]); //读取当前时间for(i=1;i<7;i++) // BCD转十进制{CURDATE[i]=(CURDATE[i]/16)*10+CURDATE[i]%16;}CURDATE[0]=CURDATE[0]&0x7f;CURDATE[0]=(CURDATE[0]/16)*10+CURDATE[0]%16;disp1602(0,0,CURDATE[2]/10+'0');disp1602(0,1,CURDATE[2]%10+'0');disp1602(0,2,'-');disp1602(0,3,CURDATE[1]/10+'0');disp1602(0,4,CURDATE[1]%10+'0');disp1602(0,5,'-');disp1602(0,6,CURDATE[0]/10+'0');disp1602(0,7,CURDATE[0]%10+'0');} }

 

#include <GPIO_IO.h> #define BIT(x) (1 << (x)) //PORTB &=~BIT(7);置0 PORTB |=BIT(7);置1 PORTA ^= BIT(7);取反void GPIO_HIGH(uchar x,uchar y)//GPIO置1 {if (x=='B')PORTB |=BIT(y);else if (x=='C')PORTC |=BIT(y);else if (x=='D')PORTD |=BIT(y); } void GPIO_LOW(uchar x,uchar y)//GPIO置0 {if (x=='B')PORTB &=~BIT(y);else if (x=='C')PORTC &=~BIT(y);else if (x=='D')PORTD &=~BIT(y); } void GPIO_TURN(uchar x,uchar y)//GPIO翻转 {if (x=='B')PORTB ^= BIT(y);else if (x=='C')PORTC ^= BIT(y);else if (x=='D')PORTD ^= BIT(y); }

 

总结

以上是生活随笔为你收集整理的51单片机与AVR(SPI)单片机驱动DS1302的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。