日本欧美一区-日本欧美一区二区三区片-日本强好片久久久久久AAA-日本-区一区二区三区A片-日本人伦一区二区三区-日本人妻A片成人免费看

電子開發(fā) | 基礎(chǔ)入門 | 電路原理圖 | 梯形图实例 | PLC基础   《如果喜欢本站,请按 Ctrl+D 手动收藏!感谢您的支持》一起学习一起进步,电子开发王欢迎您!.

電子開發(fā)網(wǎng)

電子開發(fā)網(wǎng)電子設(shè)計 | 電子開發(fā)網(wǎng)Rss 2.0 會員中心 會員注冊

★电路公式手册,最新版《电子电路公式计算器》,电路公式查询手册 电路公式计算器【电子从业人员必备手册】
☆十天学会单片机实例100 c语言 chm格式。资料内容详细,覆盖例子多,内容广【电子从业人员必备手册】
搜索: 您現(xiàn)在的位置: 電子開發(fā)網(wǎng) >> 電子開發(fā) >> 單片機 >> 正文

單片機電子時鐘程序設(shè)計

作者:佚名    文章來源:本站原創(chuàng)    點擊數(shù):1801    更新時間:2018/3/10
共用體除非必要,否則我們不推薦使用,枚舉的用法比較簡單,在本書 19 章的項目實踐中有很好的示例,這節(jié)課我們先來練習(xí)一下結(jié)構(gòu)體的使用。下邊這個程序的功能是一個帶日期的電子鐘,相當于一個簡易萬年歷了,并且加入了按鍵調(diào)時功能。學(xué)有余力的同學(xué)看到這里,不妨先不看我們提供的代碼,自己寫寫試試。如果能夠獨立寫一個按鍵可調(diào)的萬年歷程序,單片機可以說基本入門了。如果自己還不能夠獨立完成這個程序,那么還是老規(guī)矩,先抄并且理解,而后自己獨立默寫出來,并且要邊默寫邊理解。

本例直接忽略了星期這項內(nèi)容,通過上、下、左、右、回車、ESC 這 6 個按鍵可以調(diào)整時間。這也是一個具有綜合練習(xí)性質(zhì)的實例,雖然在功能實現(xiàn)上沒有多少難度,但要進行的操作卻比較多而且煩瑣,同學(xué)們可以從中體會到把繁雜的功能實現(xiàn)分解為一步步函數(shù)操作的必要性以及方便靈活性。簡單說一下這個程序的幾個要點,方便大家閱讀理解程序。
  1. 把 DS1302 的底層操作封裝為一個 DS1302.c 文件,對上層應(yīng)用提供基本的實時時間的操作接口,這個文件也是我們的又一個功能模塊了,我們的積累也越來越多了。
  2. 定義一個結(jié)構(gòu)體類型 sTime 用來封裝日期時間的各個元素,又用該結(jié)構(gòu)體定義了一個時間緩沖區(qū)變量 bufTime 來暫存從 DS1302 讀出的時間和設(shè)置時間時的設(shè)定值。需要注意的是在其它文件中要使用這個結(jié)構(gòu)體變量時,必須首先再聲明一次 sTime 類型;
  3. 定義一個變量 setIndex 來控制當前是否處于設(shè)置時間的狀態(tài),以及設(shè)置時間的哪一位,該值為 0 就表示正常運行,1~12 分別代表可以修改日期時間的 12 個位;
  4. 由于這節(jié)課的程序功能要進行時間調(diào)整,用到了 1602 液晶的光標功能,添加了設(shè)置光標的函數(shù),我們要改變哪一位的數(shù)字,就在 1602 對應(yīng)位置上進行光標閃爍,所以 Lcd1602.c在之前文件的基礎(chǔ)上添加了兩個控制光標的函數(shù);
  5. 時間的顯示、增減、設(shè)置移位等上層功能函數(shù)都放在 main.c 中來實現(xiàn),當按鍵需要這些函數(shù)時則在按鍵文件中做外部聲明,這樣做是為了避免一組功能函數(shù)分散在不同的文件內(nèi)而使程序顯得凌亂。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/***************************DS1302.c 文件程序源代碼*****************************/
#include <reg52.h>
sbit DS1302_CE = P1^7;
sbit DS1302_CK = P3^5;
sbit DS1302_IO = P3^4;
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; //星期
};
/* 發(fā)送一個字節(jié)到 DS1302 通信總線上 */
void DS1302ByteWrite(unsigned char dat){
unsigned char mask;
for (mask=0x01; mask!=0; mask<<=1){ //低位在前,逐位移出
if ((mask&dat) != 0){ //首先輸出該位數(shù)據(jù)
DS1302_IO = 1;
}else{
DS1302_IO = 0;
}
DS1302_CK = 1; //然后拉高時鐘
DS1302_CK = 0; //再拉低時鐘,完成一個位的操作
}
DS1302_IO = 1; //最后確保釋放 IO 引腳
}
/* 由 DS1302 通信總線上讀取一個字節(jié) */
unsigned char DS1302ByteRead(){
unsigned char mask;
unsigned char dat = 0;
for (mask=0x01; mask!=0; mask<<=1){ //低位在前,逐位讀取
if (DS1302_IO != 0){ //首先讀取此時的 IO 引腳,并設(shè)置 dat 中的對應(yīng)位
dat |= mask;
}
DS1302_CK = 1; //然后拉高時鐘
DS1302_CK = 0; //再拉低時鐘,完成一個位的操作
}
return dat; //最后返回讀到的字節(jié)數(shù)據(jù)
}
/* 用單次寫操作向某一寄存器寫入一個字節(jié),reg-寄存器地址,dat-待寫入字節(jié) */
void DS1302SingleWrite(unsigned char reg, unsigned char dat){
DS1302_CE = 1; //使能片選信號
DS1302ByteWrite((reg<<1)|0x80); //發(fā)送寫寄存器指令
DS1302ByteWrite(dat); //寫入字節(jié)數(shù)據(jù)
DS1302_CE = 0; //除能片選信號
}
/* 用單次讀操作從某一寄存器讀取一個字節(jié),reg-寄存器地址,返回值-讀到的字節(jié) */
unsigned char DS1302SingleRead(unsigned char reg){
unsigned char dat;
DS1302_CE = 1; //使能片選信號
DS1302ByteWrite((reg<<1)|0x81); //發(fā)送讀寄存器指令
dat = DS1302ByteRead(); //讀取字節(jié)數(shù)據(jù)
DS1302_CE = 0; //除能片選信號
return dat;
}
/* 用突發(fā)模式連續(xù)寫入 8 個寄存器數(shù)據(jù),dat-待寫入數(shù)據(jù)指針 */
void DS1302BurstWrite(unsigned char *dat){
unsigned char i;
DS1302_CE = 1;
DS1302ByteWrite(0xBE); //發(fā)送突發(fā)寫寄存器指令
for (i=0; i<8; i++){ //連續(xù)寫入 8 字節(jié)數(shù)據(jù)
DS1302ByteWrite(dat[i]);
}
DS1302_CE = 0;
}
/* 用突發(fā)模式連續(xù)讀取 8 個寄存器的數(shù)據(jù),dat-讀取數(shù)據(jù)的接收指針 */
void DS1302BurstRead(unsigned char *dat){
unsigned char i;
DS1302_CE = 1;
DS1302ByteWrite(0xBF); //發(fā)送突發(fā)讀寄存器指令
for (i=0; i<8; i++){ //連續(xù)讀取 8 個字節(jié)
dat[i] = DS1302ByteRead();
}
DS1302_CE = 0;
}
/* 獲取實時時間,即讀取 DS1302 當前時間并轉(zhuǎn)換為時間結(jié)構(gòu)體格式 */
void GetRealTime(struct sTime *time){
unsigned char buf[8];
DS1302BurstRead(buf);
time->year = buf[6] + 0x2000;
time->mon = buf[4];
time->day = buf[3];
time->hour = buf[2];
time->min = buf[1];
time->sec = buf[0];
time->week = buf[5];
}
/* 設(shè)定實時時間,時間結(jié)構(gòu)體格式的設(shè)定時間轉(zhuǎn)換為數(shù)組并寫入 DS1302 */
void SetRealTime(struct sTime *time){
unsigned char buf[8];
buf[7] = 0;
buf[6] = time->year;
buf[5] = time->week;
buf[4] = time->mon;
buf[3] = time->day;
buf[2] = time->hour;
buf[1] = time->min;
buf[0] = time->sec;
DS1302BurstWrite(buf);
}
/* DS1302 初始化,如發(fā)生掉電則重新設(shè)置初始時間 */
void InitDS1302(){
unsigned char dat;
struct sTime code InitTime[] = { //2013 年 10 月 8 日 12:30:00 星期二
0x2013,0x10,0x08, 0x12,0x30,0x00, 0x02
};
DS1302_CE = 0; //初始化 DS1302 通信引腳
DS1302_CK = 0;
dat = DS1302SingleRead(0); //讀取秒寄存器
if ((dat & 0x80) != 0){ //由秒寄存器最高位 CH 的值判斷 DS1302 是否已停止
DS1302SingleWrite(7, 0x00); //撤銷寫保護以允許寫入數(shù)據(jù)
SetRealTime(&InitTime); //設(shè)置 DS1302 為默認的初始時間
}
}
DS1302.c 最終向外提供出與具體時鐘芯片寄存器位置無關(guān)的、由時間結(jié)構(gòu)類型 sTime 作為接口的實時時間的讀取和設(shè)置函數(shù),如此處理體現(xiàn)了我們前面提到過的層次化編程的思想。應(yīng)用層可以不關(guān)心底層實現(xiàn)細節(jié),底層實現(xiàn)的改變也不會對應(yīng)用層造成影響,比如說日后你可能需要換一款時鐘芯片,而它與 DS1302 的操作和時間寄存器順序是不同的,那么你需要做的也僅是針對這款新的時鐘芯片設(shè)計出底層操作函數(shù),最終提供出同樣的以 sTime 為接口的操作函數(shù)即可,應(yīng)用層無需做任何的改動。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/***************************Lcd1602.c 文件程序源代碼*****************************/
#include <reg52.h>
#define LCD1602_DB P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E = P1^5;
/* 等待液晶準備好 */
void LcdWaitReady(){
unsigned char sta;
LCD1602_DB = 0xFF;
LCD1602_RS = 0;
LCD1602_RW = 1;
do {
LCD1602_E = 1;
sta = LCD1602_DB; //讀取狀態(tài)字
LCD1602_E = 0;
} while (sta & 0x80); //bit7 等于 1 表示液晶正忙,重復(fù)檢測直到其等于 0 為止
}
/* 向 LCD1602 液晶寫入一字節(jié)命令,cmd-待寫入命令值 */
void LcdWriteCmd(unsigned char cmd){
LcdWaitReady();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
LCD1602_E = 1;
LCD1602_E = 0;
}
/* 向 LCD1602 液晶寫入一字節(jié)數(shù)據(jù),dat-待寫入數(shù)據(jù)值 */
void LcdWriteDat(unsigned char dat){
LcdWaitReady();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_E = 1;
LCD1602_E = 0;
}
/* 設(shè)置顯示 RAM 起始地址,亦即光標位置,(x,y)-對應(yīng)屏幕上的字符坐標 */
void LcdSetCursor(unsigned char x, unsigned char y){
unsigned char addr;
if (y == 0){ //由輸入的屏幕坐標計算顯示 RAM 的地址
addr = 0x00 + x; //第一行字符地址從 0x00 起始
}else{
addr = 0x40 + x; //第二行字符地址從 0x40 起始
}
LcdWriteCmd(addr | 0x80); //設(shè)置 RAM 地址
}
/* 在液晶上顯示字符串,(x,y)-對應(yīng)屏幕上的起始坐標,str-字符串指針 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str){
LcdSetCursor(x, y); //設(shè)置起始地址
while (*str != '\0'){ //連續(xù)寫入字符串數(shù)據(jù),直到檢測到結(jié)束符
LcdWriteDat(*str++);
}
}
/* 打開光標的閃爍效果 */
void LcdOpenCursor(){
LcdWriteCmd(0x0F);
}
/* 關(guān)閉光標顯示 */
void LcdCloseCursor(){
LcdWriteCmd(0x0C);
}
/* 初始化 1602 液晶 */
void InitLcd1602(){
LcdWriteCmd(0x38); //16*2 顯示,5*7 點陣,8 位數(shù)據(jù)接口
LcdWriteCmd(0x0C); //顯示器開,光標關(guān)閉
LcdWriteCmd(0x06); //文字不動,地址自動+1
LcdWriteCmd(0x01); //清屏
}
為了本例的具體需求,在之前文件的基礎(chǔ)上添加兩個控制光標效果打開和關(guān)閉的函數(shù),雖然函數(shù)都很簡單,但為了保持程序整體上良好的模塊化和層次化,還是應(yīng)該在液晶驅(qū)動文件內(nèi)以函數(shù)的形式提供,而不是由應(yīng)用層代碼直接來調(diào)用具體的液晶寫命令操作。
/***************************keyboard.c 文件程序源代碼****************************/
(此處省略,可參考之前章節(jié)的代碼)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/*****************************main.c 文件程序源代碼******************************/
#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 flag200ms = 1; //200ms 定時標志
struct sTime bufTime; //日期時間緩沖區(qū)
unsigned char setIndex = 0; //時間設(shè)置索引
unsigned char T0RH = 0; //T0 重載值的高字節(jié)
unsigned char T0RL = 0; //T0 重載值的低字節(jié)
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 確保首次讀取時間后會刷新顯示
EA = 1; //開總中斷
ConfigTimer0(1); //T0 定時 1ms
InitDS1302(); //初始化實時時鐘
InitLcd1602(); //初始化液晶
//初始化屏幕上固定不變的內(nèi)容
LcdShowStr(3, 0, "20 - - ");
LcdShowStr(4, 1, " : : ");
while (1){
KeyDriver(); //調(diào)用按鍵驅(qū)動
if (flag200ms && (setIndex == 0)){ //每隔 200ms 且未處于設(shè)置狀態(tài)時,
flag200ms = 0;
GetRealTime(&bufTime); //獲取當前時間
if (psec != bufTime.sec){ //檢測到時間有變化時刷新顯示
RefreshTimeShow();
psec = bufTime.sec; //用當前值更新上次秒數(shù)
}
}
}
}
/* 將一個 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(5, 0, bufTime.year);
ShowBcdByte(8, 0, bufTime.mon);
ShowBcdByte(11, 0, bufTime.day);
ShowBcdByte(4, 1, bufTime.hour);
ShowBcdByte(7, 1, bufTime.min);
ShowBcdByte(10, 1, bufTime.sec);
}
/* 刷新當前設(shè)置位的光標指示 */
void RefreshSetShow(){
switch (setIndex){
case 1: LcdSetCursor(5, 0); break;
case 2: LcdSetCursor(6, 0); break;
case 3: LcdSetCursor(8, 0); break;
case 4: LcdSetCursor(9, 0); break;
case 5: LcdSetCursor(11, 0); break;
case 6: LcdSetCursor(12, 0); break;
case 7: LcdSetCursor(4, 1); break;
case 8: LcdSetCursor(5, 1); break;
case 9: LcdSetCursor(7, 1); break;
case 10: LcdSetCursor(8, 1); break;
case 11: LcdSetCursor(10, 1); break;
case 12: LcdSetCursor(11, 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;
}
/* 遞增時間當前設(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è)置位的值 */
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);
default: break;
}
RefreshTimeShow();
RefreshSetShow();
}
/* 右移時間設(shè)置位 */
void RightShiftTimeSet(){
if (setIndex != 0){
if (setIndex < 12){
setIndex++;
}else{
setIndex = 1;
}
RefreshSetShow();
}
}
/* 左移時間設(shè)置位 */
void LeftShiftTimeSet(){
if (setIndex != 0){
if (setIndex > 1){
setIndex--;
}else{
setIndex = 12;
}
RefreshSetShow();
}
}
/* 進入時間設(shè)置狀態(tài) */
void EnterTimeSet(){
setIndex = 2; //把設(shè)置索引設(shè)置為 2,即可進入設(shè)置狀態(tài)
LeftShiftTimeSet(); //再利用現(xiàn)成的左移操作移到位置 1 并完成顯示刷新
LcdOpenCursor(); //打開光標閃爍效果
}
/* 退出時間設(shè)置狀態(tài),save-是否保存當前設(shè)置的時間值 */
void ExitTimeSet(bit save){
setIndex = 0; //把設(shè)置索引設(shè)置為 0,即可退出設(shè)置狀態(tài)
if (save){ //需保存時即把當前設(shè)置時間寫入 DS1302
SetRealTime(&bufTime);
}
LcdCloseCursor(); //關(guān)閉光標顯示
}
/* 按鍵動作函數(shù),根據(jù)鍵碼執(zhí)行相應(yīng)的操作,keycode-按鍵鍵碼 */
void KeyAction(unsigned char keycode){
if ((keycode>='0') && (keycode<='9')){ //本例中不響應(yīng)字符鍵
}else if (keycode == 0x26){ //向上鍵,遞增當前設(shè)置位的值
IncSetTime();
}else if (keycode == 0x28){ //向下鍵,遞減當前設(shè)置位的值
DecSetTime();
}else if (keycode == 0x25){ //向左鍵,向左切換設(shè)置位
LeftShiftTimeSet();
}else if (keycode == 0x27){ //向右鍵,向右切換設(shè)置位
RightShiftTimeSet();
}else if (keycode == 0x0D){ //回車鍵,進入設(shè)置模式/啟用當前設(shè)置值
if (setIndex == 0){ //不處于設(shè)置狀態(tài)時,進入設(shè)置狀態(tài)
EnterTimeSet();
}else{ //已處于設(shè)置狀態(tài)時,保存時間并退出設(shè)置狀態(tài)
ExitTimeSet(1);
}
}else if (keycode == 0x1B){ //Esc 鍵,取消當前設(shè)置
ExitTimeSet(0);
}
}
/* 配置并啟動 T0,ms-T0 定時時間 */
void ConfigTimer0(unsigned int ms){
unsigned long tmp; //臨時變量
tmp = 11059200 / 12; //定時器計數(shù)頻率
tmp = (tmp * ms) / 1000; //計算所需的計數(shù)值
tmp = 65536 - tmp; //計算定時器重載值
tmp = tmp + 28; //補償中斷響應(yīng)延時造成的誤差
T0RH = (unsigned char)(tmp>>8); //定時器重載值拆分為高低字節(jié)
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零 T0 的控制位
TMOD |= 0x01; //配置 T0 為模式 1
TH0 = T0RH; //加載 T0 重載值
TL0 = T0RL;
ET0 = 1; //使能 T0 中斷
TR0 = 1; //啟動 T0
}
/* T0 中斷服務(wù)函數(shù),執(zhí)行按鍵掃描和 200ms 定時 */
void InterruptTimer0() interrupt 1{
static unsigned char tmr200ms = 0;
TH0 = T0RH; //重新加載重載值
TL0 = T0RL;
KeyScan(); //按鍵掃描
tmr200ms++;
if (tmr200ms >= 200){ //定時 200ms
tmr200ms = 0;
flag200ms = 1;
}
}
main.c 主文件,負責(zé)所有應(yīng)用層的功能實現(xiàn),文件比較長,還是那句話“不難但比較煩瑣”,希望對具體問題分析細化能力還不太強的同學(xué)們把這個文件多練習(xí)幾遍,學(xué)習(xí)一下其中把具體問題逐步細化并一步步實現(xiàn)出來的編程思想,多進行此類練習(xí),鍛煉程序思維能力,將來遇到具體項目設(shè)計需求的時候,你很快就可以找到方法并實現(xiàn)它們了。
Tags:單片機電子時鐘,程序設(shè)計,單片機時鐘,c語言  
責(zé)任編輯:admin
請文明參與討論,禁止漫罵攻擊,不要惡意評論、違禁詞語。 昵稱:
1分 2分 3分 4分 5分

還可以輸入 200 個字
[ 查看全部 ] 網(wǎng)友評論
    没有任何评论
电子开发网:汇集综合各类电子制作与电路图的网站,plc工控技术,模电数电知识,单片机EDA等等!荟萃电路图网站精华,为工程师创造价值。欢迎关注微信公众号:电子开发网!

三菱PLC软件 GX Wor

西门子200smartPLC选

模拟量转换工程量转

简述555定时器工作原

西门子S7-200 SMART

TIA Portal博途软件
 简单三极管逆变器
 TL494制作50HZ逆变
 80W简单的功放电路
 555制作的简易电子
 850热风枪电路图原
 直流12v荧光灯电路
關(guān)于我們 - 聯(lián)系我們 - 廣告服務(wù) - 友情鏈接 - 網(wǎng)站地圖 - 版權(quán)聲明 - 在線幫助 - 文章列表
返回頂部
刷新頁面
下到頁底
晶體管查詢