本实验用可用数码管实现秒表计时功能,并用按键实现暂停,继续,清零复位,
在数码管暂停实现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;
}
}
}
}
}