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