单片机
返回首页

基于PIC16F877A的秒表程序

2017-12-07 来源:eefocus

//该源程序已在实验板上调试通过,读者可直接引用,并可利用软件编程的灵活性,加以拓展,实现更为复杂的功能。

//此程序实现计时秒表功能,时钟显示范围00.00~99.99秒,分辨度:0.01秒

//定义0.01 秒、0.1 秒、1秒、10秒计时器
#include 
#include  
unsigned  char  s0,s1,s2,s3;

unsigned  char   s[4];
unsigned  char   k ,data ,sreg;
unsigned   int  i;
const table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90};
//不带小数点的显示段码表
const table0[10]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10};
//带小数点的显示段码表
//TMR0初始化子程序
void  tmint()
{
 T0CS=0;    //TMR0工作于定时器方式
 PSA=1;     //TMR0不用分频
 T0IF=0;     //清除TMR0的中断标志
 T0IE=1;     //TMR0中断允许
}
//spi显示初始化子程序
void  SPIINIT()
{
 PIR1=0;
 SSPCON=0x30;
 SSPSTAT=0xC0;
//设置SPI的控制方式,允许SSP方式,并且时钟下降沿发送。与'74HC595,当其
//SCLK从低到高跳变时,串行输入寄存器'的特点相对应
 TRISC=0xD7;   //SDO引脚为输出,SCK引脚为输出
 TRISA5=0;    //RA5引脚置为输出,输出显示锁存信号
}
//系统其它部分初始化子程序
void  initial()
{
 TRISB1=0;
 TRISB2=0;
 TRISB4=1;
 TRISB5=1;    //设置与键盘有关的各口的输入输出方式
 RB1=0;
 RB2=0;     //建立键盘扫描的初始条件
}
//SPI传输数据子程序
void   SPILED(data)
{
 SSPBUF=data;   //启动发送
 do {
     ;
  }while(SSPIF==0);
 SSPIF=0;
}
//显示子程序,显示4位数
void  dispaly()
{
 RA5=0;     //准备锁存
 for(k=4;k>0;k--)
 {
  data=s[k-1];
  if(k==3) data=table0[data];//第二位需要显示小数点
  else data=table[data];
  SPILED(data);  //发送显示段码
 }
 for(k=0;k<4;k++)
 {
  data=0xFF;
  SPILED(data);  //连续发送4个DARK,使显示好看一些
 }
 RA5=1;     //最后给锁存信号,代表显示任务完成
}
//软件延时子程序
void   DELAY()
{
 for(i = 3553; --i ;) continue;

//键扫描子程序
void  KEYSCAN()
{
while(1){ 
while(1)
 {
  dispaly();   //调用一次显示子程序
  if ((RB5==0)||(RB4==0)) break;
 }
  DELAY();   //若有键按下,则软件延时
  if ((RB5==0)||(RB4==0)) break;//若还有键按下,则终止循环扫描,返回
   }
}
//等键松开子程序
void  keyrelax()
{
while(1){
 dispaly();    //调用一次显示子程序
 if ((RB5==1)&&(RB4==1)) break;
 }      //为防止按键过于灵敏,每次等键松开才返回
}
//系统赋值初始化子程序
void  inizhi()

 s0=0x00;
 s[0]=s0;
 s1=0x00;
 s[1]=s1;
 s2=0x00;
 s[2]=s2;
 s3=0x00;
 s[3]=s3;     //s0=s1=s2=s3=0,并放入显示缓冲数组中
 sreg=0x00;    //tmr0中断次数寄存器清0
}
//中断服务程序
void  interrupt clkint(void)
{
 TMR0=0X13;   //对TMR0写入一个调整值。因为写入TMR0后接着的
 //两个周期不能增量,中断需要3个周期的响应时间,
 //以及C语言自动进行现场保护要消耗周期
 T0IF=0;     //清除中断标志
 CLRWDT();
 sreg=sreg+1;    //中断计数器加1
 if(sreg==40)    //中断次数为40后,才对S0,S1,S2,S3 操作
 {
  sreg=0;
  s0=s0+1;
  if(s0==10){
   s0=0 ;
   s1=s1+1;
   if(s1==10){
    s1=0 ;
    s2=s2+1;
    if(s2==10){
     s2=0;
     s3=s3+1;
     if(s3==10) s3=0 ;
    }
   }
  }
 }
 s[0]=s0;
 s[1]=s1;
 s[2]=s2;
 s[3]=s3;
}
//主程序
main()
{
 OPTION=0XFF;
 tmint();     //TMR0初始化
 SPIINIT();    //spi显示初始化
 initial();     //系统其它部分初始化
 di();     //总中断禁止
 while(1) { 
  inizhi();    //系统赋值初始化
  KEYSCAN();  //键扫描,直到开始键按下
  keyrelax();   //等键松开
  ei();    //总中断允许
  TMR0=0X08;
 KEYSCAN();  //键扫描直到停止键按下,在键扫描时有显示
  keyrelax() ;   //等键松开
  di();    //总中断禁止
  KEYSCAN();  //键扫描到清0键按下,在键扫描时有显示 
  keyrelax() ;   //等键松开
 }
}


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • PIC单片机控制的遥控防盗报警器电路

  • 短波AM发射器电路设计图

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 如何构建一个触摸传感器电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章