51单片机秒表仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
Altium Designer画的秒表电路原理图和PCB图如下:(51hei附件中可下载工程文件)
单片机源程序如下:
- #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)
|