本實驗用可用數位管實現秒錶計時功能,並用按鍵實現暫停,繼續,清零複位, 在數位管暫停實現LED燈閃爍 1. Led燈由C連接埠控制,高電平有效 2. 數位管的位段由A連接埠控制,資料區段由D連接埠控制 3. 按鍵串連B連接埠 RB0 暫停鍵 RB2 繼續鍵 RB4 秒錶計時開始 4. 中斷服務 當RB0暫停鍵按下時,產生中斷,秒錶暫停保持不動,開始執行led閃爍, 當RB2按下時,延時片刻,返回秒錶計時,按下複位鍵從新開始 要求:MPLAB8.5以上編譯,mcd-2下載器,pic工程板,關閉看門狗定時器,低電壓編程 */ #include<p18cxxx.h> //***************共陽數位管定義******************************** 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; } } } } } |