完整的課程設(shè)計論文下載(word格式 可編輯):
基于K20的反應(yīng)速度測試.docx
(6.65 MB, 下載次數(shù): 43)
2017-5-9 10:13 上傳
點擊文件名下載附件
程序與解析 下載積分: 黑幣 -5
下面是部分內(nèi)容預(yù)覽(無圖版):
Project1: 反應(yīng)速度測試(主要內(nèi)容,有擴展) 一、 設(shè)計內(nèi)容 (1) 數(shù)碼管倒計時進入準備狀態(tài); (2) 亮燈; (3) 測試人員看見亮燈后按鍵; (4) MCU記錄反應(yīng)時間; (5) 在數(shù)碼管上顯示反應(yīng)時間; (6) 按另一鍵重新開始; (7) 如果出現(xiàn)搶跑的情況,給出提示。 二、設(shè)計思路 (1)數(shù)碼管倒計時進入準備狀態(tài):檢測SW1是否按下,如果按下,則讓數(shù)碼管SELECT-LED0按順序顯示四個數(shù)字:3、2、1、0。 (2)判斷是否搶跑并亮燈:在倒計時中,判斷SW5是否按下,如果按下,則為搶跑,點亮led1,2,3,4,且數(shù)碼管顯示0;如果倒計時過程中SW5沒有按下,則在數(shù)碼管正常倒計時到0的同時點亮led1燈; (3)設(shè)定定時中斷中斷時間:設(shè)定PIT時鐘通道0的倒計時開始時間,令number_ms等于1,則設(shè)定了1ms的定時中斷; (4)定時中斷設(shè)計:每次中斷都執(zhí)行判斷SW5是否按下,如果沒有按下,則計數(shù)count=count+1;如果SW5按下,則進入數(shù)碼管顯示子程序,數(shù)碼管顯示當前count值,即單位為毫秒; (5)重新重啟:循環(huán)檢測SW1狀態(tài),SW1一旦按下,則重新進入程序初始,實現(xiàn)重新啟動功能; 三、主要程序流程圖(加簡單文字解釋)
file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps1C46.tmp.jpg 四、程序清單(加注釋) 4.1:程序初始化: 4.1.1 數(shù)碼管顯示初始化: //第一步,使能port A和port D, 即將系統(tǒng)時鐘門控寄存器SIM_SCGC5的第9位和第12位置1 IM_SCGC5 |=(0x1000 | 0x0200); //第二步,設(shè)置port A和port D為通用輸入輸出端口 PORTA_PCR12=0x100; PORTA_PCR13=0x100; PORTA_PCR14=0x100; PORTA_PCR15=0x100; PORTA_PCR16=0x100; PORTA_PCR17=0x100; PORTD_PCR0 = 0x0100; PORTD_PCR1 = 0x0100; PORTD_PCR2 = 0x0100; PORTD_PCR3 = 0x0100; PORTD_PCR4 = 0x0100; PORTD_PCR5 = 0x0100; PORTD_PCR6 = 0x0100; PORTD_PCR7 = 0x0100;
4.1.2 LED燈初始化: SIM_SCGC5|=SIM_SCGC5_PORTC_MASK; //使能port C,port C 的0到11位設(shè)置為通用輸入輸出端口 PORTC_PCR0=PORT_PCR_MUX(0X1); //LED1 PORTC_PCR1=PORT_PCR_MUX(0X1); PORTC_PCR2=PORT_PCR_MUX(0X1); PORTC_PCR3=PORT_PCR_MUX(0X1); //LED2 PORTC_PCR4=PORT_PCR_MUX(0X1); PORTC_PCR5=PORT_PCR_MUX(0X1); PORTC_PCR6=PORT_PCR_MUX(0X1); //LED3 PORTC_PCR7=PORT_PCR_MUX(0X1); PORTC_PCR8=PORT_PCR_MUX(0X1); PORTC_PCR9=PORT_PCR_MUX(0X1); //LED4 PORTC_PCR10=PORT_PCR_MUX(0X1); PORTC_PCR11=PORT_PCR_MUX(0X1); GPIOC_PDDR|=0XFFF; //設(shè)置port C的第0位到第11位為輸出 GPIOC_PDOR=0XFFF; //將存放port C輸出數(shù)據(jù)的寄存器相應(yīng)位置1,表示LED燈全滅 4.1.3 左右按鍵初始化:
SIM_SCGC5|=SIM_SCGC5_PORTB_MASK; //使能port C SIM_SCGC5|=SIM_SCGC5_PORTE_MASK; //設(shè)置port B和port E為通用輸入輸出端口,使能中斷,并設(shè)置中斷方式為下降沿觸發(fā)中斷(將第0位和第1位置1,邊沿觸發(fā)使能;將IRQx位設(shè)置為1010表示下降沿觸發(fā)) PORTB_PCR17=0x0A0103; PORTB_PCR16=0x0A0103; PORTB_PCR11=0x0A0103; PORTB_PCR10=0x0A0103; PORTE_PCR2=0x0A0103; PORTE_PCR3=0x0A0103; PORTE_PCR4=0x0A0103; PORTE_PCR5=0x0A0103; GPIOB_PDDR&= ~0x30C00; //按鍵端口全部設(shè)置為輸入 GPIOE_PDDR&= ~0x3C; 4.1.4 IRQ使能初始化: int div; div=irq/32; //得到非優(yōu)先寄存器的寄存器號 if (irq > 91) irq=91; //確定irq號為有效的irq號 switch(div) { case 0x0: NVICICPR0=1<<(irq%32); //中斷清除使能 NVICISER0=1<<(irq%32); //中斷設(shè)置使能 break; case 0x1: NVICICPR1=1<<(irq%32); NVICISER1=1<<(irq%32); break; case 0x2: NVICICPR2=1<<(irq%32); NVICISER2=1<<(irq%32); break; } 注意:調(diào)用該函數(shù)時需要帶參數(shù) IRQ number=1; 4.1.5 PIT時鐘初始化: /*開啟PIT 時鐘,即將系統(tǒng)時鐘門控寄存器SIM_SCGC6的PIT位置1*/ SIM_SCGC6|=SIM_SCGC6_PIT_MASK; PIT_MCR&=~(PIT_MCR_MDIS_MASK); //使能PIT時鐘模塊 PIT_LDVAL0=20000*number_ms; //設(shè)定PIT時鐘通道0的倒計時開始時間 PIT_TCTRL0|=PIT_TCTRL_TIE_MASK;// 使能PIT時鐘通道0的IRQ功能 PIT_TCTRL0|=PIT_TCTRL_TEN_MASK; //使能定時器 4.2 SWI中斷程序: int a[4]={3,2,1,0}; //倒計時 for(i=0;i<=3;i++) { if(PORTE_ISFR&0X04||PORTE_ISFR&0X020) GPIOC_PDOR&=~0x249; //若搶跑,則四個LED燈均亮 else { GPIOD_PDOR = num[a]; GPIOA_PDOR = Select_LED0; if(a!=0) delay2(); } //3,2,1后面均有延時,0后面沒有,保證數(shù)到0時燈即亮 }//數(shù)碼管顯示倒計時 GPIOC_PDOR&=~0x01; //LED1亮 PORTB_ISFR |= 0x00FF00; 4.3 定時中斷程序: 根據(jù)前面的初始化程序可知,定時器中斷周期為1ms,因此計數(shù)器counter加1,對應(yīng)的延遲時間為1ms,為了簡化程序,我們在數(shù)碼管上顯示的時間單位為ms,即測量反應(yīng)時間的靈敏度為1ms;這樣我們只需把計數(shù)器counter的值轉(zhuǎn)化為十進制,在數(shù)碼管上顯示出來即可。 void pit_channel0_ISR(void) { if((PORTE_ISFR&0X04)==0) count++; //反應(yīng)鍵未按下,計時 else renew(count); //反應(yīng)鍵按下,停止計時,用數(shù)碼管顯示 PIT_TFLG0|=PIT_TFLG_TIF_MASK;//Clear the flag of channel0,PIT } 4.4 數(shù)碼管顯示子程序: void renew (int s) { int i; int f=s; f=f%1000000; int a[6]={10,10,10,10,10,10}; Select_LED=Select_LED0; for(i=5;i>=0;i--) { a=f%10; f/=10; if(f==0) break; } for(i=5;i>=0;i--) { GPIOD_PDOR = num[a]; GPIOA_PDOR =Select_LED; Select_LED=Select_LED<<1; Select_LED++; delay1(); } } 4.5 擴展部分程序: 4.5.1 數(shù)碼管顯示程序擴展: void renew1(int s) { int i; int f=s; f=f%1000; int a[6]={10,10,10,10,10,10}; Select_LED=Select_LED0; for(i=2;i>=0;i--) { a=f%10; f/=10; if(f==0) break; } for(i=2;i>=0;i--) { GPIOD_PDOR = num[a]; GPIOA_PDOR =Select_LED; Select_LED=Select_LED<<1; Select_LED++; delay1(); } } 同理,void renew2(int s)與void renew1(int s)非常相似,只要把LED=Select_LED0改為LED=Select_LED3即可。 4.5.2 定時中斷程序擴展: void pit_channel0_ISR(void) { if((PORTE_ISFR&0X04)==0) count1++; //反應(yīng)鍵sw5未按下,計時 else if((PORTE_ISFR&0X04)!=0) renew1(count1); //反應(yīng)鍵按下,停止計時,用數(shù)碼管顯示 if((PORTE_ISFR&0X020)==0) count2++; //反應(yīng)鍵sw8未按下,計時 else if((PORTE_ISFR&0X020)!=0) renew2(count2); //反應(yīng)鍵按下,停止計時,用數(shù)碼管顯示 PIT_TFLG0|=PIT_TFLG_TIF_MASK; } 五、調(diào)試過程 1、在調(diào)試過程中,我們遇到了摁鍵中斷和定時中斷沖突的情況,后來通過一點一點理順思路發(fā)現(xiàn),正在運行摁鍵中斷時,即使初始化了PIT時鐘模塊,也只能開啟定時器倒計時的功能,但是定時器倒計時到0的時候并不能進入定時中斷子程序中執(zhí)行相應(yīng)語句。 2、倒計時至0時,LED1燈沒有立即亮,而是延遲了一會兒才亮,檢查發(fā)現(xiàn),原來程序中3,2,1和0后面均有延時,于是我們就將0從for循環(huán)中提取出來,單獨顯示,并且不加延時,保證數(shù)到0時燈即亮。 3、因為要使用摁鍵SW1來進行“開始”和“重啟”操作,必須處理摁鍵抖動的問題,我們嘗試了各種不同長度的延時,終于找到了合適時長,不影響操作和響應(yīng),也可以防抖。 4、我們要測試指示燈亮到摁鍵被摁下的反應(yīng)時間,就必須防止摁鍵被重復(fù)觸發(fā)。除了使用延時去除抖動的方式來防止硬件干擾,我們還必須利用在其它端口的中斷服務(wù)子程序中清除該摁鍵中斷標志的方式來防止人為錯誤操作影響測試結(jié)果的顯示。 5、我們在定時中斷服務(wù)子程序中要用到PORTE的中斷標志位,如果在PORTE_Hanlder里清除中斷,那么將不會執(zhí)行定時中斷服務(wù)子程序,也就不會有任何顯示,所以應(yīng)該把PORTE的中斷清除語句拿出來,放到PORTB_Hanlder程序中,因為SW1是復(fù)位鍵,每按下一次,表示程序初始化,需要清除所有操作。 6、當反應(yīng)時間較長時,數(shù)碼管顯示的數(shù)值不合邏輯,后來考慮到數(shù)碼管可能出現(xiàn)溢出現(xiàn)象,于是就添加了f=f%1000000。 六、實際結(jié)果(有相關(guān)照片) | file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps1C57.tmp.pngfile:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps1C58.tmp.png |
| file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps1C59.tmp.png | | file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps1C5A.tmp.png | | file:///C:/Users/ADMINI~1/AppData/Local/Temp/ksohtml/wps1C6B.tmp.png |
七、結(jié)論與改進(改進可以只有想法,沒有實現(xiàn)) 1、結(jié)果:實現(xiàn)了基本功能; 2、實現(xiàn)了兩個人比賽,分別顯示各自的反應(yīng)時間的功能; 3、實現(xiàn)了單人、雙人兩種模式且完成了單/雙人模式切換; 4、實現(xiàn)了以秒和毫秒兩種單位的數(shù)值顯示; 5、改進:將倒計時部分做成準確的3秒倒計時,而不是僅用delay函數(shù)做。 |