pic秒表实验

2019-04-15 14:32发布

     
本实验用可用数码管实现秒表计时功能,并用按键实现暂停,继续,清零复位,
在数码管暂停实现LED灯闪烁
1. Led灯由C端口控制,高电平有效
2. 数码管的位段由A端口控制,数据段由D端口控制
3. 按键连接B端口
RB0    暂停键
RB2    继续键
RB4    秒表计时开始
4. 中断服务
当RB0暂停键按下时,产生中断,秒表暂停保持不动,开始执行led闪烁,
当RB2按下时,延时片刻,返回秒表计时,按下复位键从新开始
要求:MPLAB8.5以上编译,mcd-2下载器,pic工程板,关闭看门狗定时器,低电压编程
*/
#include
//***************共阳数码管定义********************************
const unsigned int table[10] = {0xc0,0xf9, 0xa4 ,0xb0 ,0x99,
               0x92 , 0x82 , 0xf8 , 0x80, 0x90}; //0-9定义无小数点
     
const unsigned int table1[10] = {0x40,0x79, 0x24 ,0x30 ,0x19,
               0x12 , 0x02 , 0x78 , 0x00, 0x10};//{0-9}带小数点
//***************延时函数************************************ 
//*************中断服务函数声明******************************
void  PIC18F_High_isr(void);  //中断服务程序
void  PIC18F_Low_isr(void);
//***********************************************************    
void Delay(unsigned int x)
{
    unsigned int i;
 for(i=x; i>0; i--){;}
}  //***********C端口初始化函数-led灯****************************
void PortCB_Inio()
{
    TRISC = 0X00;    //c端口全部为输出
 PORTC = 0X00;    //led全部为灭
}  //*****************A,D和B端口初始化-数码管**********************
void Port_Inio()
{
    ADCON1 = 0XFF;    //配置A端口为数字输入
    TRISA = 0XC0;     //A端口全部为输出,A6,A7输入晶振频率
 TRISD = 0x00;     //D端口初始化为输出
 TRISBbits.TRISB0 = 1;    //RB0,RB1,RB4 配置为输入 暂停
 TRISBbits.TRISB2 = 1;    //继续
 TRISBbits.TRISB4 = 1;    //开始计时键
 INTCON2bits.RBPU = 0;  //使能B端口的内部上拉
 PORTC = 0X00;    //led全部为灭
 
 PORTA = 0X00;         //初始化6位数码管全亮
 PORTD = 0XC0;         //初始化数码管全为0
}
//****************流水灯闪烁函数*************************
void Led()
{
   int k;
   int i;
   PortCB_Inio();     // C端口初始化函数
   TRISBbits.TRISB2 = 1;
 for (k=1000;k>0;k--)
 { 
     //顺序闪
     PORTC = 0X01;          //点亮R0灯
     Delay(1000);               //延时 
     for (i=8; i>0; i--)
     {
        PORTC = PORTC<<1;         //右移一位
           Delay(1000);                   //延时  
     }
     //一亮一闪
     PORTC = 0X00;       //全灭
     PORTC = 0Xff;       //全亮
     Delay(1000);
     PORTC = 0X00;       //全灭
     Delay(1000); 
    
     //反闪
     
       PORTC =0X80;           //10000000 点亮R7灯
       Delay(1000);             //延时
      
       for (i=0; i<8; i++)
       {
           PORTC = PORTC>>1;
           Delay(1000);                   //延时   
       }
       if(k==0)
       {
        break;
       }
       if (PORTBbits.RB2 == 0)      //按下退出中断函数,继续计时
       {
        Delay(400);                //消除抖动
        if (PORTBbits.RB2 == 0)
           {
           break;
        }
       }
    }         
}
//********************声明中断函数***********************
//**********************************************
#pragma code high_vector_section = 0x8  //#pragma code指定后面的程序在rom的起始地址为0X8,终止于0x17
void high_vector()
{
     _asm goto PIC18F_High_isr _endasm  //通过此指令逃到高优先级中断服务程序
}
//**************************************************
#pragma code Low_vector_section = 0x18
void low_vector()
{
     _asm goto PIC18F_Low_isr _endasm   //通过此指令逃到低优先级中断服务程序
}
//****************************************************************
#pragma code  //返回默认的代码段,中断返回 //*************************高低优先级服务函数*********************
#pragma interrupt PIC18F_High_isr   //#pragma interrupt 关键字 跳转到高中断服务程序,下面一定是次程序
void PIC18F_High_isr()     //高级中断服务程序 记得要清中断标志位
{
  
 //同级优先级的判断-标志位进行判断
 if(INTCONbits.INT0IF == 1)   //RB0已按下
 {
    INTCONbits.INT0IF = 0;      //iINT0外部中断标志位  INTCON1寄存器 写成INTCO
    Led();                  //led灯闪 
    }
   
} #pragma interruptlow PIC18F_High_isr    //跳转到低中断服务程序 记得要清楚中断标志位
void PIC18F_Low_isr()
{
   //此实例未实现低优先级中断
    
}
//**************主函数***********************************     
void main()
{
       int mseconds = 0;   //毫秒初始化为0
    int seconds  = 0;   //秒初始化为0
    int minutes  = 0;   //分钟初始化为0
    int count    = 0;   //延时计数变量
    Port_Inio();        //A,D和B端口初始化
      //********************************************************** 
        
    //中断函数设置——RB0和RB1设置
   
     //高优先级设置 1RB0
  INTCON2bits.INTEDG0 = 0; //INTCON2 使能外部中断0(RB0)触发边缘中断(下降源)
  INTCONbits.INT0IF  = 0; //清外部中断标志优先位
  INTCONbits.INT0IE  = 1; //使能int0(供RB0使用)外部中断0使能位
    //INTCON3bits.INT0IP  = 0; //外部中断优先级为高优先级 INT0IP不存在,默认的    
  
  INTCONbits.GIE      = 1;    //开启全局中断
  
       //***********秒表计时***************************************
    if (PORTBbits.RB4 == 0)    //如果RB4按下
    {
        Delay(500);       //延时消除抖动
     if (PORTBbits.RB4 == 0)  //RB4确实按下,则执行下列程序
     {
       while (1)
       {
      ++ count;       //延时计数变量开始加加        
      PORTA =0x3e;       //打开第一个数码管(RA0)
      PORTD=0xff;        //清除显示 刷新作用
      PORTD = table[mseconds %10];  //毫秒的个位
      Delay(200);      //短暂延时       PORTA =0x3d;      //打开第2个数码管(RA1)
      PORTD=0xff;        //清除显示 刷新作用
      PORTD = table[mseconds/10];  //毫秒的十位
      Delay(200);     //短暂延时       PORTA =0x3b;     //打开第3个数码管(RA2)后带有小数点以区分时,分,秒
      PORTD=0xff;        //清除显示 刷新作用
      PORTD = table1[seconds%10];    //秒的个位
      Delay(200);     //短暂延时
     
      PORTA =0x37; //打开第4个数码管(RA3)
      PORTD=0xff;        //清除显示 刷新作用
      PORTD = table[seconds/10];   //秒的十位
      Delay(200);     //短暂延时       PORTA =0x2f;//打开第5个数码管(RA4)后带有小数点以区分时,分,秒
      PORTD=0xff;        //清除显示 刷新作用
      PORTD = table1[minutes%10];  //分的个位
      Delay(200);     //短暂延时       PORTA =0x1f;//打开第6个数码管(RA5)
      PORTD=0xff;        //清除显示 刷新作用
      PORTD = table[minutes/10];   //分的十位
      Delay(200);     //短暂延时
      
      if(count==1)     //1us
      {
       count=0;
       ++mseconds;          //秒开始计数
       seconds  += mseconds/60;    // 当s等于60,m=60/60=1
       mseconds = mseconds%60;     //1%60=1
       minutes += minutes/60;
       seconds = seconds%60;
       minutes = minutes%60;
      }
       }
      }
  }
}

热门文章