上個月剛做的關于Ds1302時鐘和數(shù)模轉(zhuǎn)換的設計,
檢測電池電壓,自我供電的 包含源碼和工程。
單片機源程序如下:
- /*
- *******************************************************************************
- *
- * 文件名:main.c
- 用DS1302實現(xiàn)簡易電子鐘
- * 用液晶顯示日期時間,并可通過按鍵校時
- *******************************************************************************
- */
- #include <reg52.h>
- struct sTime { //日期時間結(jié)構(gòu)體定義
- unsigned int year;
- unsigned char mon;
- unsigned char day;
- unsigned char hour;
- unsigned char min;
- unsigned char sec;
- unsigned char week;
- };
- bit flag300ms = 1; //300ms定時標志
- bit flag200ms = 1; //200ms定時標志
- unsigned char T0RH = 0; //T0重載值的高字節(jié)
- unsigned char T0RL = 0; //T0重載值的低字節(jié)
- struct sTime bufTime; //日期時間緩沖區(qū)
- unsigned char setIndex = 0; //時間設置索引
- void ConfigTimer0(unsigned int ms);
- unsigned char GetADCValue(unsigned char chn);
- void ValueToString(unsigned char *str, unsigned char val);
- extern void I2CStart();
- extern void I2CStop();
- extern unsigned char I2CReadACK();
- extern unsigned char I2CReadNAK();
- extern bit I2CWrite(unsigned char dat);
- extern void InitLcd1602();
- extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
- void ConfigTimer0(unsigned int ms);
- void RefreshTimeShow();
- extern void InitDS1302();
- extern void GetRealTime(struct sTime *time);
- extern void SetRealTime(struct sTime *time);
- extern void KeyScan();
- extern void KeyDriver();
- extern void InitLcd1602();
- extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
- extern void LcdSetCursor(unsigned char x, unsigned char y);
- extern void LcdOpenCursor();
- extern void LcdCloseCursor();
- void main()
- {
- unsigned char psec=0xAA; //秒備份,初值AA確保首次讀取時間后會刷新顯示
- unsigned char val;
- unsigned char str[10];
- EA = 1; //開總中斷
- ConfigTimer0(1); //T0定時1ms
- InitDS1302(); //初始化實時時鐘
- InitLcd1602(); //初始化液晶
-
- //初始化屏幕上固定不變的內(nèi)容
- LcdShowStr(0, 0, "20 - - ");
- LcdShowStr(1, 1, " : : ");
- LcdShowStr(11, 0, "Vol"); //顯示通道指示
-
- while (1)
- {
- KeyDriver(); //調(diào)用按鍵驅(qū)動
- if (flag200ms && (setIndex == 0))
- { //每隔200ms且未處于設置狀態(tài)時,
- flag200ms = 0;
- GetRealTime(&bufTime); //獲取當前時間
- if (psec != bufTime.sec) //檢測到時間有變化時刷新顯示
- {
- RefreshTimeShow();
- psec = bufTime.sec; //用當前值更新上次秒數(shù)
- }
- }
- if (flag300ms)
- {
- flag300ms = 0;
- //顯示通道0的電壓
- val = GetADCValue(0); //獲取ADC通道0的轉(zhuǎn)換值
- ValueToString(str, val); //轉(zhuǎn)為字符串格式的電壓值
- LcdShowStr(11, 1, str); //顯示到液晶上
- //顯示通道1的電壓
- /*val = GetADCValue(1);
- ValueToString(str, val);
- LcdShowStr(6, 1, str);
- //顯示通道3的電壓
- val = GetADCValue(3);
- ValueToString(str, val);
- LcdShowStr(12, 1, str); */
- }
- }
- }
- /* 將一個BCD碼字節(jié)顯示到屏幕上,(x,y)-屏幕起始坐標,bcd-待顯示BCD碼 */
- void ShowBcdByte(unsigned char x, unsigned char y, unsigned char bcd)
- {
- unsigned char str[4];
-
- str[0] = (bcd >> 4) + '0';
- str[1] = (bcd&0x0F) + '0';
- str[2] = '\0';
- LcdShowStr(x, y, str);
- }
- /* 刷新日期時間的顯示 */
- void RefreshTimeShow()
- {
- ShowBcdByte(2, 0, bufTime.year);
- ShowBcdByte(5, 0, bufTime.mon);
- ShowBcdByte(8, 0, bufTime.day);
- ShowBcdByte(1, 1, bufTime.hour);
- ShowBcdByte(4, 1, bufTime.min);
- ShowBcdByte(7, 1, bufTime.sec);
- }
- /* 刷新當前設置位的光標指示 */
- void RefreshSetShow()
- {
- switch (setIndex)
- {
- case 1: LcdSetCursor(2, 0); break;
- case 2: LcdSetCursor(3, 0); break;
- case 3: LcdSetCursor(5, 0); break;
- case 4: LcdSetCursor(6, 0); break;
- case 5: LcdSetCursor(8, 0); break;
- case 6: LcdSetCursor(9, 0); break;
- case 7: LcdSetCursor(1, 1); break;
- case 8: LcdSetCursor(2, 1); break;
- case 9: LcdSetCursor(4, 1); break;
- case 10: LcdSetCursor(5, 1); break;
- case 11: LcdSetCursor(7, 1); break;
- case 12: LcdSetCursor(8, 1); break;
- default: break;
- }
- }
- /* 遞增一個BCD碼的高位 */
- unsigned char IncBcdHigh(unsigned char bcd)
- {
- if ((bcd&0xF0) < 0x90)
- bcd += 0x10;
- else
- bcd &= 0x0F;
-
- return bcd;
- }
- /* 遞增一個BCD碼的低位 */
- unsigned char IncBcdLow(unsigned char bcd)
- {
- if ((bcd&0x0F) < 0x09)
- bcd += 0x01;
- else
- bcd &= 0xF0;
-
- return bcd;
- }
- /* 遞減一個BCD碼的高位 */
- unsigned char DecBcdHigh(unsigned char bcd)
- {
- if ((bcd&0xF0) > 0x00)
- bcd -= 0x10;
- else
- bcd |= 0x90;
-
- return bcd;
- }
- /* 遞減一個BCD碼的低位 */
- unsigned char DecBcdLow(unsigned char bcd)
- {
- if ((bcd&0x0F) > 0x00)
- bcd -= 0x01;
- else
- bcd |= 0x09;
-
- return bcd;
- }
- /* 遞增時間當前設置位的值 */
- void IncSetTime()
- {
- switch (setIndex)
- {
- case 1: bufTime.year = IncBcdHigh(bufTime.year); break;
- case 2: bufTime.year = IncBcdLow(bufTime.year); break;
- case 3: bufTime.mon = IncBcdHigh(bufTime.mon); break;
- case 4: bufTime.mon = IncBcdLow(bufTime.mon); break;
- case 5: bufTime.day = IncBcdHigh(bufTime.day); break;
- case 6: bufTime.day = IncBcdLow(bufTime.day); break;
- case 7: bufTime.hour = IncBcdHigh(bufTime.hour); break;
- case 8: bufTime.hour = IncBcdLow(bufTime.hour); break;
- case 9: bufTime.min = IncBcdHigh(bufTime.min); break;
- case 10: bufTime.min = IncBcdLow(bufTime.min); break;
- case 11: bufTime.sec = IncBcdHigh(bufTime.sec); break;
- case 12: bufTime.sec = IncBcdLow(bufTime.sec); break;
- default: break;
- }
- RefreshTimeShow();
- RefreshSetShow();
- }
- /* 遞減時間當前設置位的值 */
- void DecSetTime()
- {
- switch (setIndex)
- {
- case 1: bufTime.year = DecBcdHigh(bufTime.year); break;
- case 2: bufTime.year = DecBcdLow(bufTime.year); break;
- case 3: bufTime.mon = DecBcdHigh(bufTime.mon); break;
- case 4: bufTime.mon = DecBcdLow(bufTime.mon); break;
- case 5: bufTime.day = DecBcdHigh(bufTime.day); break;
- case 6: bufTime.day = DecBcdLow(bufTime.day); break;
- case 7: bufTime.hour = DecBcdHigh(bufTime.hour); break;
- case 8: bufTime.hour = DecBcdLow(bufTime.hour); break;
- case 9: bufTime.min = DecBcdHigh(bufTime.min); break;
- case 10: bufTime.min = DecBcdLow(bufTime.min); break;
- case 11: bufTime.sec = DecBcdHigh(bufTime.sec); break;
- case 12: bufTime.sec = DecBcdLow(bufTime.sec); break;
- default: break;
- }
- RefreshTimeShow();
- RefreshSetShow();
- }
- /* 右移時間設置位 */
- void RightShiftTimeSet()
- {
- if (setIndex != 0)
- {
- if (setIndex < 12)
- setIndex++;
- else
- setIndex = 1;
- RefreshSetShow();
- }
- }
- /* 左移時間設置位 */
- void LeftShiftTimeSet()
- {
- if (setIndex != 0)
- {
- if (setIndex > 1)
- setIndex--;
- else
- setIndex = 12;
- RefreshSetShow();
- }
- }
- /* 進入時間設置狀態(tài) */
- void EnterTimeSet()
- {
- setIndex = 2; //把設置索引設置為2,即可進入設置狀態(tài)
- LeftShiftTimeSet(); //再利用現(xiàn)成的左移操作移到位置1并完成顯示刷新
- LcdOpenCursor(); //打開光標閃爍效果
- }
- /* 退出時間設置狀態(tài),save-是否保存當前設置的時間值 */
- void ExitTimeSet(bit save)
- {
- setIndex = 0; //把設置索引設置為0,即可退出設置狀態(tài)
- if (save) //需保存時即把當前設置時間寫入DS1302
- {
- SetRealTime(&bufTime);
- }
- LcdCloseCursor(); //關閉光標顯示
- }
- /* 按鍵動作函數(shù),根據(jù)鍵碼執(zhí)行相應的操作,keycode-按鍵鍵碼 */
- void KeyAction(unsigned char keycode)
- {
- if ((keycode>='0') && (keycode<='9')) //本例中不響應字符鍵
- {
- }
- else if (keycode == 0x26) //向上鍵,遞增當前設置位的值
- {
- IncSetTime();
- }
- else if (keycode == 0x28) //向下鍵,遞減當前設置位的值
- {
- DecSetTime();
- }
- else if (keycode == 0x25) //向左鍵,向左切換設置位
- {
- LeftShiftTimeSet();
- }
- else if (keycode == 0x27) //向右鍵,向右切換設置位
- {
- RightShiftTimeSet();
- }
- else if (keycode == 0x0D) //回車鍵,進入設置模式/啟用當前設置值
- {
- if (setIndex == 0) //不處于設置狀態(tài)時,進入設置狀態(tài)
- {
- EnterTimeSet();
- }
- else //已處于設置狀態(tài)時,保存時間并退出設置狀態(tài)
- {
- ExitTimeSet(1);
- }
- }
- else if (keycode == 0x1B) //Esc鍵,取消當前設置
- {
- ExitTimeSet(0);
- }
- }
- /* 讀取當前的ADC轉(zhuǎn)換值,chn-ADC通道號0~3 */
- unsigned char GetADCValue(unsigned char chn)
- {
- unsigned char val;
-
- I2CStart();
- if (!I2CWrite(0x48<<1)) //尋址PCF8591,如未應答,則停止操作并返回0
- {
- I2CStop();
- return 0;
- }
- I2CWrite(0x40|chn); //寫入控制字節(jié),選擇轉(zhuǎn)換通道
- I2CStart();
- I2CWrite((0x48<<1)|0x01); //尋址PCF8591,指定后續(xù)為讀操作
- I2CReadACK(); //先空讀一個字節(jié),提供采樣轉(zhuǎn)換時間
- val = I2CReadNAK(); //讀取剛剛轉(zhuǎn)換完的值
- I2CStop();
-
- return val;
- }
- /* ADC轉(zhuǎn)換值轉(zhuǎn)為實際電壓值的字符串形式,str-字符串指針,val-AD轉(zhuǎn)換值 */
- void ValueToString(unsigned char *str, unsigned char val)
- {
- //電壓值=轉(zhuǎn)換結(jié)果*2.5V/255,式中的25隱含了一位十進制小數(shù)
- val = (val*50) / 255;
- str[0] = (val/10) + '0'; //整數(shù)位字符
- str[1] = '.'; //小數(shù)點
- str[2] = (val%10) + '0'; //小數(shù)位字符
- str[3] = 'V'; //電壓單位
- str[4] = '\0'; //結(jié)束符
- }
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
kechuang1.zip
(83.42 KB, 下載次數(shù): 6)
2018-6-16 16:04 上傳
點擊文件名下載附件
|