10. 實時鐘系統設計
10. 實時鐘系統設計
10.1 系統結構
10.2 程式設計
10.2.1 實時鐘程式設計
10.2.2 按鍵和顯示程式設計
10.2.3 系統程式設計
10.3 程式實現
10.1 系統結構
- 實時鐘系統包括STM32MCU、實時鐘電路DS1302、2個按鍵、4個LED、LED顯示器和UART-USB轉換器CP2102
- 實時鐘電路提供實時鐘計時,包括年、月、日、星期、時、分和秒等
- 2個按鍵用於切換LCD顯示和設定實時鐘
- 4個LED指示LCD顯示的內容
- LCD分別顯示年、月、星期、日、時、分和秒等
- UART-USB轉換器CP2102通過USB實現與計算機的序列通訊
- DS1302是美國DALLAS公司推出的一種高效能、低功耗、帶RAM的實時時鐘電路,可以對年、月、星期、日、時、分和秒進行計時,具有閏年補償功能
- DS1302採用三線介面與CPU進行同步通訊,可採用突發方式一次傳送多個位元組的時鐘或RAM資料
- DS1302的工作電壓為2.5-5.5V,8引腳封裝
- DS1302控制位元組
- DS1302讀寫時序
- DS1302時鐘暫存器
10.2 程式設計
10.2.1 實時鐘程式設計
- 實時鐘程式設計根據DS1302讀寫時序進行編寫。DS1302讀寫時序包括2個基本操作:寫時序包括2個寫操作(寫地址和寫資料),讀時序包括1個寫操作(寫地址)和1個讀操作(讀資料)因此,首先編寫2個基本操作的子程式
- DS1302寫子程式
//DS1302寫子程式
//入口引數:data-寫資料
void Ds1302_Write(char data)
{
char m;
for(m=0; m<8; m++)
{
if(data & 1<<m)
GPIOB->BSRR = 1<<7; //PB.07(I/O)=1
else
GPIOB->BRR = 1<<7; //PB.07(I/O)=0
GPIOB->BSRR = 1<<6; //PB.06(SCLK)=1
GPIOB->BRR = 1<<6; //PB.06(SCLK)=0
}
}
- DS1302讀子程式
//DS1302讀子程式
//出口引數:讀資料
char DS1302_Read(void)
{
char m,data=0;
for(m=0;m<8;m++)
{
data |= (GPIOB->IDR>>7&1)<<m; //PB.07(I/O)
GPIOB->BSRR = 1<<6; //PB.06(SCLK)=1
GPIOB->BRR = 1<<6; //PB.06(SCLK)=0
}
return data;
}
- DS1302寫資料子程式
//DS1302寫資料子程式
//入口引數:addr-地址,data-資料
void Ds1302_Write_Data(char addr,char data)
{
RCC->APB2ENR |= 1<<3; //開啟GPIOB時鐘
GPIOB->CRL &= 0x000fffff;
GPIOB->CRL |= 0x33300000; //PB.07-PB.05通用推輓輸出
GPIOB->BSRR = 1<<5; //PB.05(RST)=1
addr = 0x80+(addr<<1); //寫資料
Ds1302_Write(addr);
Ds1302_Write(data);
GPIOB->BRR = 1<<5; //PB.05(RST)=0
}
- DS1302讀資料子程式
//DS1302讀資料子程式
//入口引數:addr-地址
//出口引數:資料
char Ds1302_Read_data(char addr)
{
char data=0;
RCC->APB2ENR |= 1<<3; //開啟GPIOB時鐘
GPIOB->CRL &= 0x000fffff;
GPIOB->CRL |= 0x33300000; //PB.07-PB.05通用推輓輸出
GPIOB->BSRR = 1<<5; //PB.05(RST)=1
addr = 0x80+(addr<<1)+1; //讀資料
Ds1302_Write(addr);
GPIOB->CRL &= 0x0fffffff;
GPIOB->CRL |= 0x40000000; //PB.07(I/O)浮空輸入
data = Ds1302_Read();
GPIOB->BRR 1<<5; //PB.05(RST)=0
return data;
}
10.2.2 按鍵和顯示程式設計
- 按鍵操作和LCD顯示狀態圖
- 系統共有8個狀態:4個顯示狀態(分別顯示年、月日、時分和分秒)和4個設定狀態(分別設定月、日、時和分)
- 狀態間用切換鍵(KEY1)和設定鍵(KEY2)轉換:切換鍵用於切換顯示和設定狀態以及退出設定狀態,設定鍵用於進入設定狀態和設定月、日、時和分等
- 4個顯示狀態和4個設定狀態同時分別用4個LED進行指示
1、按鍵程式設計(按鍵採用中斷方式工作)
- 按鍵介面初始化子程式
//按鍵介面初始化子程式
void Key_Init(void)
{
RCC->APB2ENR |= 1<<3; //開啟按鍵介面(GPIOB)時鐘
RCC->APB2ENR |= 1; //開啟AFIO時鐘
AFIO->EXTICR[2] |= 0x0011; //EXTI9=PB.9,EXTI8=PB.8
EXTI->FTSR |= 0x0300; //EXTI9和EXTI8下降沿觸發
EXTI->IMR |= 0x0300; //允許EXTI9和EXTI8中斷
NVIC->IPR[5] |= 0x80000000; //EXTI9-8中斷搶佔優先順序1
NVIC->ISER[0] |= 1<<23; //允許EXTI9-8中斷
}
- 按鍵介面處理子程式
//按鍵中斷處理子程式
void EXTI9_5_IRQHandler(void)
{
Delay(10); //延時10ms消抖動
if((EXTI->PR&1<<8)&&(~GPIOB->IDR&1<<8))//KEY1按下(PR.8=1,IDR.8=0)
{
if(flag<4) //顯示狀態
{
if(flag<4) //顯示狀態切換
flag=0;
}
else //設定狀態
{
if(++flag == 8) //設定狀態切換
{
flag = 2; //退出設定狀態
GPIOB->BRR = 0xf000; //亮所有LED
Delay(200); //延時200ms
Ds1302_Write_Data(4,month);//寫資料到DS1302
Ds1302_Write_Data(3,date);
Ds1302_Write_Data(2,hour);
Ds1302_Write_Data(1,min);
Ds1302_Write_Data(0,0);
}
}
}
if((EXTI->PR & 1<<9) && (~GPIOB->IDR & 1<<9)) //KEY2按下(PR.9=1,IDR.9=0)
{
if(flag<4)
flag = 4; //進入設定狀態
if(flag == 4) //設定月
{
month = Bin_Bcd(++month); //2-10進位制調整
if(month > 0x12)
month = 1;
}
if(flag == 5) //設定日
{
date = Bin_Bcd(++date); //2-10進位制調整
if(date>0x31)
date = 1;
}
if(flag == 6) //設定時
{
hour = Bin_Bcd(++hour); //2-10 進位制調整
if(hour>0x24)
hour = 0;
}
if(flag == 7) //設定分
{
min = Bin_Bcd(++min); //2-10進位制調整
if(min>0x60)
min = 0;
}
}
EXTI->PR |= 0x0300; //清除中斷觸發請求
}
- 延時子程式Delay()和2-10進位制調整子程式Bin_Bcd()
//延時子程式
void Delay(char ms)
{
msec = 0;
while(msec < ms);
}
//2-10進位制調整子程式
char Bin_Bcd(char data)
{
if((data & 0xf) >9)
data += 6;
return data;
}
- 延時子程式中的msec計時用SysTick中斷實現,相應的SysTick初始化子程式和SysTick中斷處理子程式
//SysTick初始化子程式
void SysTick_Init(void)
{
SysTick->LOAD = 1E3; //設定1ms重灌值(時脈頻率為8MHz/8)
SysTick->CTRL = 2; //計數到0時中斷
SysTick->CTRL = 1; //啟動定時器
}
//SysTick中斷處理子程式
void SysTick_Handler(void)
{
msec += 1; //毫秒計時
}
- 由於SysTick中斷巢狀在按鍵中斷中,而STM32的中斷巢狀是通過搶佔優先順序實現。因此,為了保證程式正常工作,必須用下列語句設定搶佔優先順序
SCB->AIRCR = 0x05FA0600; //1位搶佔優先順序,3位響應優先順序
NVIC->IPR[5] |= 0x80000000; //EXTI9-8中斷搶佔優先順序1
- SysTick的搶佔優先順序預設為0,比EXTI9-8搶佔優先順序高可以在按鍵中斷中巢狀SysTick中斷,實現延時功能
2、顯示程式設計(包括LED狀態指示和LCD資料顯示)
- 顯示處理子程式
//顯示處理子程式
void Disp_Proc(void)
{
switch(flag)
{
case 0: //顯示年
{
GPIOB->BSRR = 0xf000; //滅所有LED
GPIOB->BRR = 0x8000; //亮LED4
Lcd_Proc(0x20,year,0); //顯示年
break;
}
case 1: //顯示月日
{
GPIOB->BSRR = 0xf000; //滅所有LED
GPIOB->BRR = 0x4000; //亮LED3
Lcd_Proc(month,date,2); //顯示月,日
break;
}
case 2: //顯示時分
{
GPIOB->BSRR = 0xf000; //滅所有LED
GPIOB->BRR = 0x2000; //亮LED2
Lcd_Proc(hour,min,8); //顯示時:分
Delay(200);
Lcd_Proc(hour,min,0); //冒號(:)閃爍
break;
}
case 3: //顯示分秒
{
GPIOB->BSRR = 0xf000; //滅所有LED
GPIOB->BRR = 0x1000; //亮LED1
Lcd_Proc(min,sec,0); //顯示分秒
break;
}
case 4: //設定月
{
GPIOB->BSRR = 0xf000; //滅所有LED
GPIOB->BRR = 0x8000; //亮LED4
Lcd_Proc(0xff,date,2); //月閃爍
Delay(200);
Lcd_Proc(month,date,2);
break;
}
case 5: //設定日
{
GPIOB->BSRR = 0xf000; //滅所有LED
GPIOB->BRR = 0x4000; //亮LED3
Lcd_Proc(month,0xff,2); //日閃爍
Delay(200);
Lcd_Proc(month,date,2);
break;
}
case 6: //設定時
{
GPIOB->BSRR = 0xf000; //滅所有LED
GPIOB->BRR = 0x2000; //亮LED2
Lcd_Proc(hour,min,8); //時閃爍
Delay(200);
Lcd_Proc(hour,min,8);
break;
}
case 7: //設定分
{
GPIOB->BSRR = 0xf000; //滅所有LED
GPIOB->BRR = 0x1000; //亮LED1
Lcd_Proc(hour,0xff,0); //分閃爍
Delay(200);
Lcd_Proc(hour,min,8);
break;
}
}
}
- 為了使設定的資料閃爍,需要對Lcd_Proc()中的lcd_code[]資料定義做如下修改
char lcd_code[16]={0xeb,0x60,0xad,0xe5,0x66,0xc70xcf,0x61,
0xef,0xe7,0x6f,0xce,0x8b,0xec,0x8f,0x00};
10.2.3 系統程式設計
- 實時鐘系統主程式和部分初始化子程式流程圖
- 主程式首先對系統進行初始化,包括SCB(系統控制模組)初始化、SysTick初始化、按鍵介面初始化、LED介面初始化、LCD介面初始化和USART1介面初始化等
- 其中SCB初始化設定中斷優先順序組,SysTick初始化允許計數到0時中斷,按鍵介面初始化允許按鍵介面中斷,並設定按鍵中斷的搶佔優先順序低於SysTick中斷的搶佔優先順序,以允許在按鍵中斷巢狀SysTick中斷,實現延時功能
- 系統初始化後寫實時鐘資料到DS1302作為實時鐘的初始資料,然後進入主迴圈
- 主迴圈的主要操作(包括顯示處理和串列埠傳送資料)每1s執行1次。顯示狀態下從DS1302讀取實時鐘資料顯示並通過串列埠進行傳送,設定狀態下不從DS1302讀取實時鐘資料,只顯示當前資料並等待通過按鍵進行設定
- 按鍵程式和延時程式通過中斷機制進行呼叫,可以實時響應按鍵和延時操作,顯示程式和串列埠傳送程式則通過主程式進行呼叫
相關文章
- 實時時鐘、系統時鐘和主機伺服器時鐘的區別伺服器
- 系統時鐘與硬體時鐘
- 聊一聊實時計算系統設計
- 【實時時鐘RTC】MSP430系統實時時鐘RTC學習日誌(完善中)
- Linux 系統時鐘和硬體時鐘Linux
- 硬體時鐘與系統時鐘同步問題
- 下面的實時系統怎麼設計呢。
- 分散式系統:向量時鐘分散式
- (3)跨時鐘域設計
- 論醫院架設NTP時鐘裝置(GPS北斗時鐘系統)重要性
- Linux 硬體時鐘和系統時鐘 - hwclock介紹Linux
- 10.橋接模式設計思想橋接模式
- 關於時鐘的設定 hwcolck ,主要解決系統時鐘和硬體時鐘不一致的問題(轉)
- 分散式系統2:分散式系統中的時鐘分散式
- 分散式系統:Lamport邏輯時鐘分散式LAMP
- win7系統時鐘使用秘籍Win7
- 5分鐘課程:物聯網的系統設計
- 10. 系統分析垃圾收集器
- 醫院GPS時鐘系統(子母鐘系統)構成與行業應用行業
- Win10系統怎麼備份鬧鐘和時鐘Win10
- 實時計算助力1688打造「實時挑貨」系統
- 低程式碼實時數倉構建系統的設計與實踐
- Qt時鐘介面、數字時鐘(12小時制24小時制切換、修改系統時間)QT
- 北斗授時伺服器(時鐘系統)在政務系統應用方案伺服器
- UML 在系統設計時的應用
- 計量系統的設計與實施
- GPS北斗時鐘伺服器(衛星時鐘系統)讓高考時間更加精準伺服器
- Linux系統時鐘(System Clock)和硬體(Real Time Clock,簡稱RTC)時鐘Linux
- 多級時序系統:機器週期,時鐘週期
- 面試官:系統需求多變時如何設計?面試
- Linux程式設計(獲取系統時間)Linux程式設計
- 系統設計面試參考-設計Spotify系統面試
- 系統設計:設計Spotify
- 學號20145332 《資訊保安系統設計基礎》實驗三 實時系統的移植
- win10系統怎樣將時鐘放在桌面上 win10電腦桌面顯示時鐘設定方法Win10
- 基於STM32無線WIFI智慧家居實時控制系統設計(畢設課設)WiFi
- 設計模式的征途—10.裝飾(Decorator)模式設計模式
- iOS倒數計時設計思路和一個系統時間的坑iOS