51單片機秒表仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
0.jpg (96.7 KB, 下載次數: 41)
下載附件
2018-12-3 03:40 上傳
Altium Designer畫的秒表電路原理圖和PCB圖如下:(51hei附件中可下載工程文件)
0.png (20.75 KB, 下載次數: 38)
下載附件
2018-12-3 03:41 上傳
0.png (38.46 KB, 下載次數: 44)
下載附件
2018-12-3 03:41 上傳
單片機源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- //1602定義
- sbit RS = P2^7; //定義端口
- sbit RW = P2^6;
- sbit EN = P2^5;
- #define RS_CLR RS=0 //狀態量定義,方便讀取代碼
- #define RS_SET RS=1
- #define RW_CLR RW=0
- #define RW_SET RW=1
- #define EN_CLR EN=0
- #define EN_SET EN=1
- #define DataPort P0 //1602數據接口
- //按鍵定義
- sbit key1=P1^3; //Up
- sbit key2=P1^2; //Down
- sbit key3=P1^1; //Start/Stop
- sbit key4=P1^4; //Record
- //蜂鳴器定義,用于提示計時超時
- sbit Beep=P1^0; //1時不響,0時響
- //全局變量定義
- unsigned int RecordTableH[11]; //保存分和秒
- unsigned char RecordTableL[11]; //保存毫秒
- unsigned int CountTimeH; //記錄分、秒時間
- unsigned char CountTimeL; //記錄毫秒時間
- unsigned char DataRecordFlag = 0; //數據記錄標志位,表示記錄的數據量(記錄了多少個數據)
- unsigned char DataFlag = 0; //保存數據標志,用于記錄保存數據的個數
- code unsigned char NumTable[]="0123456789";
- bit Counting = 0; //計時標志0暫停/停止,1計時狀態
- //函數聲明
- void LCD1602_WriteCom(unsigned char com); //1602部分
- void LCD1602_WriteData(unsigned char Data);
- void LCD1602_Clear(void);
- void LCD1602_PutString(unsigned char x,unsigned char y,unsigned char *s);
- void LCD1602_PutChar(unsigned char x,unsigned char y,unsigned char Data);
- void LCD1602_Init(void);
- void LCD1602_Delay(unsigned int t);
- void delay_ms(unsigned int t);
- void IniTC0(void) ; //初始化定時計數器0
- void KeyWork(void); //按鍵掃描以及按鍵功能動作
- void DisplayCountTime(void); //顯示計時的時間
- void main()
- {
- IniTC0();
- LCD1602_Init();
- Beep = 1;
-
- LCD1602_PutString(4,0,"Well Come"); //開機歡迎可不要
- LCD1602_PutString(2,1,"Time Counter");
- delay_ms(1000);
- LCD1602_Clear();
-
- while(1)
- {
- DisplayCountTime();
- KeyWork();
- }
- }
- /*------------------------------------------------
- 寫入命令函數
- ------------------------------------------------*/
- void LCD1602_WriteCom(unsigned char com)
- {
- LCD1602_Delay(5);
- RS_CLR;
- RW_CLR;
- EN_SET;
- DataPort= com;
- _nop_();
- EN_CLR;
- }
- /*------------------------------------------------
- 寫入數據函數
- ------------------------------------------------*/
- void LCD1602_WriteData(unsigned char Data)
- {
- LCD1602_Delay(5);
- RS_SET;
- RW_CLR;
- EN_SET;
- DataPort= Data;
- _nop_();
- EN_CLR;
- }
- /*------------------------------------------------
- 清屏函數
- ------------------------------------------------*/
- void LCD1602_Clear(void)
- {
- LCD1602_WriteCom(0x01);
- LCD1602_Delay(5);
- }
- /*------------------------------------------------
- 寫入字符串函數
- ------------------------------------------------*/
- void LCD1602_PutString(unsigned char x,unsigned char y,unsigned char *s)
- {
- if (y == 0)
- {
- LCD1602_WriteCom(0x80 + x); //表示第一行
- }
- else
- {
- LCD1602_WriteCom(0xC0 + x); //表示第二行
- }
- while (*s)
- {
- LCD1602_WriteData( *s);
- s ++;
- }
- }
- /*------------------------------------------------
- 寫入字符函數
- ------------------------------------------------*/
- void LCD1602_PutChar(unsigned char x,unsigned char y,unsigned char Data)
- {
- if (y == 0)
- {
- LCD1602_WriteCom(0x80 + x);
- }else {
- LCD1602_WriteCom(0xC0 + x);
- }
- LCD1602_WriteData( Data);
- }
- /*------------------------------------------------
- 初始化函數
- ------------------------------------------------*/
- void LCD1602_Init(void)
- {
- LCD1602_WriteCom(0x38); /*顯示模式設置*/
- LCD1602_Delay(5);
- LCD1602_WriteCom(0x38);
- LCD1602_Delay(5);
- LCD1602_WriteCom(0x38);
- LCD1602_Delay(5);
- LCD1602_WriteCom(0x38);
- LCD1602_WriteCom(0x08); /*顯示關閉*/
- LCD1602_WriteCom(0x01); /*顯示清屏*/
- LCD1602_WriteCom(0x06); /*顯示光標移動設置*/
- LCD1602_Delay(5);
- LCD1602_WriteCom(0x0C); /*顯示開及光標設置*/
- LCD1602_Clear();
- }
- /*------------------------------------------------
- 1602延時函數
- ------------------------------------------------*/
- void LCD1602_Delay(unsigned int t)
- {
- unsigned char c;
- while(t--)
- {
- for(c = 50; c > 0; c--);
- }
- }
- void delay_ms(unsigned int t)
- {
- unsigned char c;
- while(t--)
- {
- for(c = 50; c > 0; c--);
- }
- }
- void IniTC0(void)
- {
- TMOD=0x01; //設置定時計數器的工作模式
- TR0 = 0; //關閉定時計數器
- TF0 = 0; //清空定時計數器標志位
-
- TH0=0xFC; //定時1ms,當計時時間不準在這修改
- TL0=0x18;
-
- ET0 = 1; //開啟定時計數器0中斷
- EA=1; //開總中斷
- }
- void KeyWork(void) //判斷按鍵按下就動作,提高實時性
- {
- if(key1 == 0) //顯示上一條記錄,只有在不計時時有效
- {
- if(!Counting && DataRecordFlag != 0)//只有不在計時,并且有數據時才能察看(DataRecordFlag表示記錄的數據條數)
- {
- DataFlag++;
- if(DataFlag >= DataRecordFlag)
- {
- DataFlag = DataRecordFlag;
- }
- if(DataFlag >= 10)
- {
- LCD1602_PutString(0,1,"10: ");//顯示條數并且把后面的顯示清空
- }else {
- LCD1602_PutChar(0, 1, NumTable[DataFlag]);
- LCD1602_PutString(1,1,": ");
- }
- LCD1602_PutChar(4, 1, NumTable[(RecordTableH[DataFlag]/60)/10]); //顯示記錄的時間
- LCD1602_PutChar(5, 1, NumTable[(RecordTableH[DataFlag]/60)%10]);
- LCD1602_PutChar(6, 1, ':');
- LCD1602_PutChar(7, 1, NumTable[(RecordTableH[DataFlag]%60)/10]);
- LCD1602_PutChar(8, 1, NumTable[(RecordTableH[DataFlag]%60)%10]);
- LCD1602_PutChar(9, 1, ':');
- LCD1602_PutChar(10, 1, NumTable[RecordTableL[DataFlag]/10]);
- LCD1602_PutChar(11, 1, NumTable[RecordTableL[DataFlag]%10]);
- }
- delay_ms(5); //避開抖動防止多次觸發,期間繼續顯示計數時間
- while(!key1)
- DisplayCountTime(); //等待按鍵釋放,避開抖動防止多次觸發,期間繼續顯示計數時間
- }
- if(key2 == 0) //顯示下一條記錄,只有在不計時時有效
- {
- if(!Counting && DataRecordFlag != 0)//只有不在計時,并且有數據時才能察看(DataRecordFlag表示記錄的數據條數)
- {
- DataFlag--;
- if(DataFlag == 0)
- {
- DataFlag = 1;
- }
- LCD1602_PutChar(0, 1, NumTable[DataFlag]);//顯示條數并且把后面的顯示清空
- LCD1602_PutString(1,1,": ");
-
- LCD1602_PutChar(4, 1, NumTable[(RecordTableH[DataFlag]/60)/10]); //顯示記錄的時間
- LCD1602_PutChar(5, 1, NumTable[(RecordTableH[DataFlag]/60)%10]);
- LCD1602_PutChar(6, 1, ':');
- LCD1602_PutChar(7, 1, NumTable[(RecordTableH[DataFlag]%60)/10]);
- LCD1602_PutChar(8, 1, NumTable[(RecordTableH[DataFlag]%60)%10]);
- LCD1602_PutChar(9, 1, ':');
- LCD1602_PutChar(10, 1, NumTable[RecordTableL[DataFlag]/10]);
- LCD1602_PutChar(11, 1, NumTable[RecordTableL[DataFlag]%10]);
- }
- delay_ms(5); //避開抖動防止多次觸發,期間繼續顯示計數時間
- while(!key2)
- DisplayCountTime(); //等待按鍵釋放,避開抖動防止多次觸發,期間繼續顯示計數時間
- }
- if(key3 == 0) //開始/停止計時
- {
- Counting = !Counting; //切換計時狀態并進行相應地動作
- if(Counting)
- {
- TR0 = 1; //開啟定時器計數,開始計時
- }else {
- TR0 = 0; //關閉定時幾計數,停止計時
- }
- delay_ms(5); //避開抖動防止多次觸發,期間繼續顯示計數時間
- while(!key3)
- DisplayCountTime(); //等待按鍵釋放,避開抖動防止多次觸發,期間繼續顯示計數時間
- }
- if(key4 == 0) //記錄時間
- {
- if(Counting) //在計時時才有用
- {
- DataRecordFlag++;
- DataFlag = DataRecordFlag;
- if(DataRecordFlag > 10) //判斷是否為第十條,第十條數據時進行記錄,超過第十條時無動作需要復位
- {
- DataRecordFlag = 10;
- DataFlag = 10;
- }else {
- if(DataRecordFlag == 10)
- {
- RecordTableH[DataFlag] = CountTimeH;
- RecordTableL[DataFlag] = CountTimeL;
- LCD1602_PutString(0,1,"10: ");
- }else {
- LCD1602_PutChar(0, 1, NumTable[DataRecordFlag]);
- LCD1602_PutString(1,1,": ");
- RecordTableH[DataFlag] = CountTimeH;
- RecordTableL[DataFlag] = CountTimeL;
- }
- }
-
- LCD1602_PutChar(4, 1, NumTable[(RecordTableH[DataRecordFlag]/60)/10]); //顯示記錄的時間
- LCD1602_PutChar(5, 1, NumTable[(RecordTableH[DataRecordFlag]/60)%10]);
- LCD1602_PutChar(6, 1, ':');
- LCD1602_PutChar(7, 1, NumTable[(RecordTableH[DataRecordFlag]%60)/10]);
- LCD1602_PutChar(8, 1, NumTable[(RecordTableH[DataRecordFlag]%60)%10]);
- LCD1602_PutChar(9, 1, ':');
- LCD1602_PutChar(10, 1, NumTable[RecordTableL[DataRecordFlag]/10]);
- LCD1602_PutChar(11, 1, NumTable[RecordTableL[DataRecordFlag]%10]);
- }
- delay_ms(5); //避開抖動防止多次觸發,期間繼續顯示計數時間
- while(!key4)
- DisplayCountTime(); //等待按鍵釋放,避開抖動防止多次觸發,期間繼續顯示計數時間
- }
- }
- void DisplayCountTime(void)
- {
- LCD1602_PutChar(4, 0, NumTable[(CountTimeH/60)/10]); //顯示計時的時間
- LCD1602_PutChar(5, 0, NumTable[(CountTimeH/60)%10]);
- LCD1602_PutChar(6, 0, ':');
- LCD1602_PutChar(7, 0, NumTable[(CountTimeH%60)/10]);
- LCD1602_PutChar(8, 0, NumTable[(CountTimeH%60)%10]);
- LCD1602_PutChar(9, 0, ':');
- LCD1602_PutChar(10, 0, NumTable[CountTimeL/10]);
- LCD1602_PutChar(11, 0, NumTable[CountTimeL%10]);
- }
- void timer0() interrupt 1
- {
- TH0=0xFC; //定時1ms
- TL0=0x18;
-
- if(!(CountTimeL == 99 && CountTimeH == 3599))//判斷是否到達計時最大值,到達59:59:99時無動作并且退出計時狀態(毫秒的進制為100)
- {
- CountTimeL++;
- if(CountTimeL > 99) //毫秒的計數時間到達100時進1到秒
- {
- CountTimeL = 0;
- CountTimeH++;
- if(CountTimeH > 3599) //設定計時最大值,計算方法為59*60+59(到達59分59秒時為最大值)
- {
- CountTimeH = 3599;
- Counting = 0;
- }
- }
- }else {
- Counting = 0; //計時標志位,為1時才開始計時
- Beep = 0; //蜂鳴器響一下
- delay_ms(5);
- Beep = 0;
- }
- }
復制代碼
所有資料51hei提供下載:
秒表+Protues+ADPCB.rar
(674.47 KB, 下載次數: 84)
2018-12-3 03:42 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|