3I]W_S89_C7F5414{RG55XK.png (94.38 KB, 下載次數: 136)
下載附件
電路圖
2018-12-16 22:04 上傳
這是電路圖,用了3個595驅動兩個4位共陰數碼管,按鍵、蜂鳴器、指示燈都忘記畫了
#define DS1302_SCK_PIN GPIO_Pin_7 //ds1302sck
#define DS1302_IO_PIN GPIO_Pin_6 //ds1302io
#define DS1302_CE_PIN GPIO_Pin_5 //ce
#define KEY1 GPIO_Pin_15 //按鍵
#define KEY2 GPIO_Pin_14
#define KEY3 GPIO_Pin_13
#define KEY4 GPIO_Pin_12
#define DEEP GPIO_Pin_11//蜂鳴器
#define LIGHT GPIO_Pin_8//指示燈
這些是代碼里引腳的IO定義
做好的效果,還有些BUG,需要完善
IMG_20181216_220149.jpg (7.65 MB, 下載次數: 100)
下載附件
成品
2018-12-16 22:04 上傳
功能有顯示時間 時分秒 年月日 周
修改時間(星期是通過算法算出來的)
鬧鐘
單片機源程序如下:
- #include "stm32f10x.h" //STM32頭文件
- #include "sys.h"
- #include "delay.h"
- #include "usart.h"
- #include "flash.h"
- #define FLASH_START_ADDR 0x0801f000 //寫入的起始地址
- //READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};//讀取時間的命令地址,已經通過讀寫操作來直接實現這些地址
- //WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};//寫時間的命令地址
- my_time TIME = {0}; //顯示時間的結構體
- u8 smgduan[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};
- u8 nz[2]={8,20};
- u8 b=0,c=0x00,d=0x00;
- u8 k1=0,k4=0,w=4,num=0;
- u8 key1,key4;
- u16 j,i,a;
- //---DS1302時鐘初始化2016年5月7日星期六12點00分00秒。---////---DS1302時鐘初始化2016年5月7日星期六12點00分00秒。---//
- u8 init_time[] = {0,0X18,0x20,0x25,0x11,0x07,0x18}; //初始化時間:秒 分 時 日 月 周 年
- u8 write[]= {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};//寫秒void display_real_time(void);
- u8 setime[7];
- u8 timedata[8];
- u8 weixian[8]={0x10,0x20,0x40,0x80,0x01,0x02,0x04,0x08};
- static void ds1302_gpio_init(void);
- static void ds1302_writebyte(u8 byte_1);//寫一個字節; byte是保留字,不能作為變量
- static void ds1302_writedata(u8 addr,u8 data_);//給某地址寫數據,data是c51內部的關鍵字,表示將變量定義在數據存儲區,故此處用data_;
- static u8 ds1302_readbyte(void);//讀一個字節
- static u8 ds1302_readdata(u8 addr);//讀取某寄存器數據;
- static void DS1302_delay_us(u16 time); //簡單延時1us
- void changetime(void);//改變顯示內容
- char switchkey1(void);//判斷KEY1按下的時間
- char switchkey4(void);//判斷KEY4按下的時間
- void shiftout(u8 num);//595函數
- void putOut(char a,char b,char c);//595函數2
- void setimeput1(char w);//日期顯示
- void setimeput(char w);//SETMODE 顯示
- void setimes(void);//設置時間函數
- void clok(void); //鬧鐘
- void nzs(u8 a);//鬧鐘開關
- void fs(char w);
- int main()
- {
- ds1302_gpio_init();
- //USART1_Init(115200);
- //DS1302_Init();
- while(1)
- {
- //while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY1));
- //while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY4));
- key1=0;
- key4=0;
- d=0xff;
- c=0xff;
- a=FLASH_R(FLASH_START_ADDR);//從指定頁的地址讀FLASH
- b=a&1;
- key1=switchkey1();
- key4=switchkey4();
- display_real_time();
- setimeput1(4);
- if(key1>=99)
- setimes();
- if(key1>10&&key1<50)
- changetime();
- if(key4<90&&key4>=30)
- clok();
- if(GPIO_ReadInputDataBit(DS1302_PORT,KEY2)==0)
- {delay_ms(20);
- if( GPIO_ReadInputDataBit(DS1302_PORT,KEY2)==0)
- b=!b;
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY2));
- a=nz[0]*1000+nz[1]*10+b;
- delay_ms(10);
- FLASH_W(FLASH_START_ADDR,a);
- }
- nzs(b&1);
- GPIO_WriteBit(GPIOA,LIGHT,(BitAction)(b));
- }
- }
- void feng()
- {
- GPIO_WriteBit(DS1302_PORT,DEEP,(BitAction)(0));
- delay_ms(100);
- GPIO_WriteBit(DS1302_PORT,DEEP,(BitAction)(1));
- delay_ms(20);
- }
- void nzs(u8 b)
- {
- if(b==1)
- {
- nz[0]=a/1000;
- nz[1]=(a-(nz[0]*1000))/10;
- if(setime[4]==nz[0]&&setime[5]==nz[1])
- {
- while(setime[4]==nz[0]&&setime[5]==nz[1]&&GPIO_ReadInputDataBit(DS1302_PORT,KEY2))
- {
- feng();
- display_real_time();
- setimeput1(4);
- }
- }
- else
- GPIO_WriteBit(DS1302_PORT,DEEP,(BitAction)(1));
- }
- else
- GPIO_WriteBit(DS1302_PORT,DEEP,(BitAction)(1));
- }
- char switchkey1(void)//判斷按鍵1按下的時間
- {
- if(GPIO_ReadInputDataBit(DS1302_PORT,KEY1)==0)
- delay_ms(10);
- if(GPIO_ReadInputDataBit(DS1302_PORT,KEY1)==0)
- {
- k1=0;
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY1)&&k1<150)
- {
- delay_ms(10);
- k1++;
- }
- }
- return k1;
- }
- char switchkey4(void)//判斷按鍵4按下的時間
- {
- if( GPIO_ReadInputDataBit(DS1302_PORT,KEY4)==0)
- delay_ms(10);
- if( GPIO_ReadInputDataBit(DS1302_PORT,KEY4)==0)
- {
- k4=0;
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY4)&&k4<150)
- {
- delay_ms(10);
- k4++;
- }
- }
- return k4;
- }
- void changetime(void)//按鍵1改變顯示內容
- { num=0;
- i=0;
- while((c&0x10))
- {
- setimeput1(0);
- delay_ms(1);
- if(GPIO_ReadInputDataBit(DS1302_PORT,KEY1)==0)
- { delay_ms(10);
- if(GPIO_ReadInputDataBit(DS1302_PORT,KEY1)==0)
- while(GPIO_ReadInputDataBit(DS1302_PORT,KEY1)==0&&num<42)
- {
- delay_ms(25);
- num++;
- }
- }
- if(num>40||i>4000)
- break;
- if(num<10&&num>2)
- { c=1;
- while(c&0x01)
- {
- for(j=0;j<60;j++)
- {
- GPIO_WriteBit(GPIOA,GPIO_Pin_3,(BitAction)(0));
- shiftout(smgduan[TIME.week]);
- shiftout(~0x04);
- shiftout(0);
- GPIO_WriteBit(GPIOA,GPIO_Pin_3,(BitAction)(1));
- delay_us(20);
- GPIO_WriteBit(GPIOA,GPIO_Pin_3,(BitAction)(0));
- shiftout(255);
- shiftout(255);
- shiftout(255);
- GPIO_WriteBit(GPIOA,GPIO_Pin_3,(BitAction)(1));
- delay_us(30);
- }
- delay_ms(1);
- i++;
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY1))
- {
- delay_ms(10);
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY1))
- {
- while(GPIO_ReadInputDataBit(DS1302_PORT,KEY1)==0&&num<42)
- {
- delay_ms(25);
- num++;
- }
- c=0x00;
- }
-
- }
- if(num>40||i>4000)
- break;
- }
- }
- }
- }
- void setimeput(char w) //SET MODE 時間顯示
- {
- //for(i=0;i<5;i+=2)
- // {
- // timedata[i]=setime[w]/10;
- // timedata[i+1]=setime[w]%10;
- // w++;
- // }
- fs(w);
- for(i=0;i<2;i++)
- {
- for(i=0;i<4;i++)
- {
- putOut(0,~weixian[i],timedata[i]);
- delay_us(50);
- }
- for(i=4;i<8;i++)
- {
- putOut(timedata[i],~weixian[i],0);
- delay_us(50);
- }
- }
- }
- //0x10,0x20,0x40,0x80,0x01,0x02,0x04,0x08
- void fs(char w)
- {
- timedata[0]=setime[w]/10;
- timedata[1]=setime[w]%10;
- timedata[2]=10;
- w++;
- timedata[3]=setime[w]/10;
- timedata[4]=setime[w]%10;
- timedata[5]=10;
- w++;
- timedata[6]=setime[w]/10;
- timedata[7]=setime[w]%10;
- }
-
-
-
- void setimeput1(char w) //時間顯示函數
- {
- //for(i=0;i<5;i+=2)
- // {
- // timedata[i]=setime[w]/10;
- // timedata[i+1]=setime[w]%10;
- // w++;
- // }
- fs(w);
- for(j=0;j<10;j++)
- {
- for(i=0;i<2;i++)
- {
- for(i=0;i<4;i++)
- {
- putOut(0,~weixian[i],timedata[i]);
- delay_us(100);
- }
- for(i=4;i<8;i++)
- {
- putOut(timedata[i],~weixian[i],0);
- delay_us(100);
- }
- }
- }
- }
- void putOut(char a,char b,char c) //595函數
- {
- GPIO_WriteBit(GPIOA,GPIO_Pin_3,(BitAction)(0));
- shiftout(255);
- shiftout(255);
- shiftout(255);
- GPIO_WriteBit(GPIOA,GPIO_Pin_3,(BitAction)(1));
- delay_us(1);
- GPIO_WriteBit(GPIOA,GPIO_Pin_3,(BitAction)(0));
- shiftout(smgduan[a]);
- shiftout(b);
- shiftout(smgduan[c]);
- GPIO_WriteBit(GPIOA,GPIO_Pin_3,(BitAction)(1));
- delay_us(50);
- }
- void setimes(void)//設置時間函數
- {
- u8 s2=0,week;
- num=0;
- i=0;
- while(d&0x10)
- {
- i++;
- setimeput(w);
- delay_us(500);
- if(GPIO_ReadInputDataBit(DS1302_PORT,KEY1)==0)
- {
- delay_ms(10);
- if(GPIO_ReadInputDataBit(DS1302_PORT,KEY1)==0)
- {
- if(s2<2)
- {
- init_time[0]=(setime[6]/10)*16+setime[6]%10;
- init_time[1]=(setime[5]/10)*16+setime[5]%10;
- init_time[2]=(setime[4]/10)*16+setime[4]%10;
- num=0;
- w=0;
- }
- if(s2>1&&s2<4)
- {
- init_time[3]=(setime[2]/10)*16+setime[2]%10;
- init_time[4]=(setime[1]/10)*16+setime[1]%10;
- init_time[6]=(setime[0]/10)*16+setime[0]%10;
- DS1302_Init();
- delay_ms(10);
- setime[3]=0;
- if (setime[1]==1||setime[1]== 2)
- {
- setime[1]+=12;
- setime[0]-=1;
- }
- setime[3]=(setime[2] + 1 + 2 * setime[1] + 3 * (setime[1] + 1) / 5
- + setime[0] + setime[0] / 4 - setime[0] / 100 + setime[0]/ 400) % 7;
- week=setime[3]%10;
- if(setime[3]%10==0)
- week=7;
- init_time[5]=week;
- DS1302_Init();
- delay_ms(10);
- d=~d;
- }
- s2++;
- if(s2>4)
- {
- d=0x00;
- break;
- }
- }
- if(s2>4)
- break;
- if(i>8000)
- break;
- }
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY4))
- {delay_ms(10);
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY4))
- {
- num++;
- if(num>2)
- num=0;
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY4));
- }
- }
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY2))
- {delay_ms(15);
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY2))
- {
- setime[w+num]=setime[w+num]+1;
- if(setime[4]>23||setime[w+num]>59)
- setime[w+num]=0;
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY2));
- }
- }
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY3))
- {delay_ms(15);
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY3))
- {
- if(w+num==4&&setime[4]==0)
- setime[0]=23;
- if(setime[w+num]==0&&w+num!=4)
- setime[w+num]=59;
-
- setime[w+num]=setime[w+num]-1;
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY3));
- }
- }
- if(s2>2)
- break;
- }
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY1));
- }
- void clok(void)
- {
- nz[0]=a/1000;
- nz[1]=(a-(nz[0]*1000))/10;
- num=0;
- while(b&0x1)
- {
- w=0;
- timedata[0]=nz[w]/10;
- timedata[1]=nz[w]%10;
- timedata[2]=10;
- w++;
- timedata[3]=nz[w]/10;
- timedata[4]=nz[w]%10;
- for(i=0;i<4;i++)
- {
- putOut(timedata[4],~weixian[4],0);
- delay_us(30);
- for(i=0;i<4;i++)
- {
- putOut(0,~weixian[i],timedata[i]);
- delay_us(50);
- }
-
- }
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY2))
- {delay_ms(15);
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY2))
- {
- nz[num]=nz[num]+1;
- if(nz[0]>23)
- nz[0]=0;
- if(nz[num]>59)
- nz[num]=0;
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY2));
- }
- }
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY3))
- {delay_ms(15);
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY3))
- {
- if(num==0&&nz[0]==0)
- nz[0]=23;
- if(nz[num]==0&&num!=0)
- nz[num]=59;
-
- nz[num]=nz[num]-1;
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY3));
- }
- }
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY1))
- {
- delay_ms(15);
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY1))
- {
- num++;
- if(num>1)
- num=0;
- while(!GPIO_ReadInputDataBit(DS1302_PORT,KEY1));
- }
- }
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY4))
- {
- delay_ms(15);
- if(!GPIO_ReadInputDataBit(DS1302_PORT,KEY4))
- {
- b=!b;
- a=nz[0]*1000+nz[1]*10+b;
- delay_ms(10);
- FLASH_W(FLASH_START_ADDR,a); //從指定頁的地址寫入FLASH
- }
- }
- delay_us(500);
- }
- }
-
- //基本IO設置
- static void ds1302_gpio_init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- //開啟GPIOD的時鐘
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
-
- //設置GPIO的基本參數
- GPIO_InitStruct.GPIO_Pin = DS1302_SCK_PIN | DS1302_CE_PIN|KEY1|KEY2|KEY3|KEY4;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //這兩個普通端口設為推挽輸出
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //輸出速度50MHz
- GPIO_Init(DS1302_PORT, &GPIO_InitStruct);
- //設置GPIO的基本參數
- GPIO_InitStruct.GPIO_Pin = KEY1|KEY2|KEY3|KEY4 ;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //輸入
- GPIO_Init(DS1302_PORT, &GPIO_InitStruct);
- GPIO_InitStruct.GPIO_Pin = DS1302_IO_PIN|DEEP; //這里最好設成開漏,當然也可以普通推挽,但是需要后面一直切換輸入輸出模式
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; //開漏輸出,需要接上拉,不需要切換輸入輸出了。
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //輸出速度50MHz
- GPIO_Init(DS1302_PORT, &GPIO_InitStruct);
- GPIO_InitStruct.GPIO_Pin =GPIO_Pin_3|GPIO_Pin_2|GPIO_Pin_5|LIGHT; //選擇端口號(0~15或all)
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //選擇IO接口工作方式
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //設置IO接口速度(2/10/50MHz)
- GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
- //寫一個字節
- //數據和地址都是從最低位開始傳輸的
- static void ds1302_writebyte(u8 byte_1)
- {
- u8 i = 0;
- u8 t = 0x01;
-
- for(i = 0;i<8;i++)
- {
- if((byte_1 & t) != 0) //之前的問題出在這里,32的位帶操作不能賦值0和1之外的值。
- {
- DS1302_DATOUT = 1;
- }
- else
- {
- DS1302_DATOUT = 0;
- }
-
- DS1302_delay_us(2);
- DS1302_SCK = 1; //上升沿寫入
- DS1302_delay_us(2);
- DS1302_SCK = 0;
- DS1302_delay_us(2);
-
- t<<= 1;
- }
- DS1302_DATOUT = 1; //釋放IO,后面讀取的話會準確很多
- DS1302_delay_us(2); //因為如果寫完之后IO被置了低電平,開漏輸出模式下讀取的時候會有影響,最好先拉高,再讀取
- }
- //地址寫數據
- static void ds1302_writedata(u8 addr,u8 data_)
- {
- DS1302_CE = 0; DS1302_delay_us(2);
- DS1302_SCK = 0; DS1302_delay_us(2);
- DS1302_CE = 1; DS1302_delay_us(2); //使能片選信號
-
- ds1302_writebyte(addr); //方便后面寫入,轉化之后是地址寄存器的值,
- ds1302_writebyte(data_);
- DS1302_CE = 0; DS1302_delay_us(2);//傳送數據結束,失能片選
- DS1302_SCK = 0; DS1302_delay_us(2);//拉低,準備下一次寫數據
- }
- //讀取一個字節,上升沿讀取
- static u8 ds1302_readbyte(void)
- {
- u8 i = 0;
- u8 data_ = 0;
-
- //因為上面已經把端口設置為開漏,電路外部接了山拉電阻,可以不切換輸入輸出模式,直接使用。
- // DS1302_DAT_INPUT();
-
- DS1302_SCK = 0;
- DS1302_delay_us(3);
- for(i=0;i<7;i++) //這里發現設為8的話輸出數據不對,很亂
- {
- if((DS1302_DATIN) == 1)
- {
- data_ = data_ | 0x80; //低位在前,逐位讀取,剛開始不對,估計是這個的問題
- }
- data_>>= 1;
- DS1302_delay_us(3);
-
- DS1302_SCK = 1;
- DS1302_delay_us(3);
- DS1302_SCK = 0;
- DS1302_delay_us(3);
- }
- return (data_);
- }
- //讀取寄存器的值
- static u8 ds1302_readdata(u8 addr)
- {
- u8 data_ = 0;
- DS1302_CE = 0; DS1302_delay_us(2);
- DS1302_SCK = 0; DS1302_delay_us(2);
- DS1302_CE = 1; DS1302_delay_us(2); //讀寫操作時CE必須為高,切在SCK為低時改變
-
- ds1302_writebyte((addr<<1)|0x81); //寫入讀時間的命令
- data_ = ds1302_readbyte();
-
- DS1302_SCK = 1; DS1302_delay_us(2);
- DS1302_CE = 0; DS1302_delay_us(2);
- DS1302_DATOUT = 0; DS1302_delay_us(3); //這里很多人說需要拉低,但是我發現去掉這個也可以顯示啊,不過為了保險,還是加上。
- DS1302_DATOUT = 1; DS1302_delay_us(2);
-
- return data_;
- }
- void DS1302_Init(void)
- {
- u8 i = 0;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
電子時鐘.7z
(184.72 KB, 下載次數: 675)
2018-12-16 23:01 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|