51单片机与AVR(SPI)单片机驱动DS1302
生活随笔
收集整理的這篇文章主要介紹了
51单片机与AVR(SPI)单片机驱动DS1302
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
本代碼來源于網(wǎng)絡(luò),記錄下來怕忘記
CE信號高電平讀寫數(shù)據(jù)
讀寫時前8位為地址位,后8位為數(shù)據(jù)。在寫數(shù)據(jù)時SCLK為下降沿開始,讀數(shù)據(jù)為上升沿開始讀數(shù)據(jù)。讀寫都是從D0-D7,且都為BCD碼。寫入時先將十進制轉(zhuǎn)化為BCD碼,在寫入寄存器。讀取時要把BCD碼轉(zhuǎn)化成十進制顯示。
int bcd_decimal_code( int bcd) //十進制轉(zhuǎn)BCD {return (bcd + (bcd/10) * 6); } int decimal_bcd_code(int decimal) ?//BCD轉(zhuǎn)十進制 {return (decimal - (decimal>>4) * 6); }51單片機模擬SPI驅(qū)動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}; // 時間數(shù)組 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讀出一字節(jié)數(shù)據(jù) /*********************************************************/ 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; } /* 讀出該地址的數(shù)據(jù) */ 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寫入一字節(jié)數(shù)據(jù) /*********************************************************/ 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; } /* 寫入數(shù)據(jù):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寫入時間數(shù)據(jù) /*********************************************************/ void DS1302_Write_Time() { uchar i; uchar temp1; uchar temp2; for(i=0;i<7;i++) // 十進制轉(zhuǎn)BCD碼 { temp1=(TimeBuff_write[i]/10)<<4; temp2=TimeBuff_write[i]%10; TimeBuff_write[i]=temp1+temp2; } DS1302_Write_Byte(0x8E,0x00); // 關(guān)閉寫保護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讀出時間數(shù)據(jù) /*********************************************************/ 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轉(zhuǎn)十進制 { 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() ; //寫入一組預(yù)設(shè)的數(shù)據(jù)}} }按鍵之后
?AVR SPI驅(qū)動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 //連續(xù)讀取 //時鐘配置常量 #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 關(guān)閉寫保護 //涓流充電控制常量 #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 //連續(xù)讀取#endif /* DS1302_H_ */ /** DS1302.c** Created: 2022/2/1 17:22:35* Author: admin*/ #include <DS1302.h> //M328p管腳定義 #define DS1302_CE 2 //PB2 SS 必須設(shè)為輸出 ----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 關(guān)閉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帶內(nèi)部下拉電阻 DDRB =(1<<DS1302_CE)|(1<<DS1302_SCK)|(1<<DS1302_MOSI);//設(shè)定SPI接口 SPCR = (1<<SPE)|(1<<MSTR)|(1<<DORD)|(1<<SPR0);// 使能SPI接口,主機模式,LSB低位在先,模式0,16分頻,SPI時鐘約460KHz } /*----------------------------------------------------------------------- Single_SPI : 使用SPI接口讀寫數(shù)據(jù)到DS1302輸入?yún)?shù): command: 命令選擇;wdata: 寫入的數(shù)據(jù); 返回值 rdata: 讀回的數(shù)據(jù); (SPI的收發(fā)是同時進行的) -----------------------------------------------------------------------*/ 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); // 等待數(shù)據(jù)傳送完?_delay_us(10);SPDR = wdata; // 傳送數(shù)據(jù)到SPI寄存器loop_until_bit_is_set(SPSR,SPIF); // 等待數(shù)據(jù)傳送完?rdata=SPDR; // 讀取數(shù)據(jù)DiDS1302; // 關(guān)斷LCD SPI通訊_delay_us(10);return rdata; }/*----------------------------------------------------------------------- Burst_SPI : 使用SPI接口讀寫一批數(shù)據(jù)到DS1302輸入?yún)?shù): CMD: 選擇Clock/RAM,選擇讀寫lenth: 數(shù)據(jù)長度pwdata: 寫入數(shù)據(jù)的緩沖區(qū);prdata: 讀回數(shù)據(jù)的緩沖區(qū); (SPI的收發(fā)是同時進行的) 讀CLOCK的數(shù)據(jù)從SECOND寄存器開始,到CONTROL寄存器,最大8字節(jié) 寫CLOCK的數(shù)據(jù)必須一次寫完8個字節(jié) 讀寫RAM的數(shù)據(jù)從 RAM0地址開始,到RAM30地址,最大31字節(jié) -----------------------------------------------------------------------*/ 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); // 等待數(shù)據(jù)傳送完?_delay_us(10); while (len--){SPDR = *pwdata++; // 傳送數(shù)據(jù)到SPI寄存器loop_until_bit_is_set(SPSR,SPIF); // 等待數(shù)據(jù)傳送完?*prdata++=SPDR; // 讀取數(shù)據(jù)};DiDS1302; // 關(guān)斷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]); //讀取當(dāng)前時間for(i=1;i<7;i++) // BCD轉(zhuǎn)十進制{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翻轉(zhuǎn) {if (x=='B')PORTB ^= BIT(y);else if (x=='C')PORTC ^= BIT(y);else if (x=='D')PORTD ^= BIT(y); }?
總結(jié)
以上是生活随笔為你收集整理的51单片机与AVR(SPI)单片机驱动DS1302的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里云服务器带宽下载上传速度表(1Mbp
- 下一篇: EFM32G232F64时钟树