說明
這個實驗是使用 Microchip APP-EDF11-1 開發板完成一個 8 顆 LED 的霹靂燈。8 顆 LED 的霹靂燈
電路圖
貼出此次實驗在 APP-EDF11-1 開發板用到的相關電路。OSC 電路
板上放了一顆 12MHz 的石英晶體振盪器。MCLR Reset 電路
當 BT1 按下去,/MCLR 接地會讓 MCU Reset。LED 電路
由 8 顆綠色的 LED 搭配限流電阻接到地,MCU 控制 LED 的陽極,所以 MCU 只要對 RD 任一腳位送 1,都會讓對應的 LED 發亮。程式碼
目前有 7 種特效,分別為「左右來回」、「向左」、「向右」、「向內再向外 」、「數字累加及遞減」、「向左對齊」、「向右對齊 」等模式。編譯環境:
- MPLAB X IDE v1.30
- C18 v3.40
檔案:main.c
主程式,從狀態 1~7 循環切換,可額外設定每個功能跑的次數及每個狀態延遲的時間。
#include "main.h" #include "ConfigurationBits.h" #define DEMO_FUNS 7 // 功能數量 #define DEMO_COUNT 6 // 每個功能跑的次數 #define DEMO_DELAY 50 // 每個狀態延遲時間 unsigned char fun = 1, count = 0; unsigned char dir = 0, n = 0; void main(void) { InitIO(); while (1) { switch (fun) { case 1: Pili_1(); break; case 2: Pili_2(0); break; case 3: Pili_2(1); break; case 4: Pili_3(); break; case 5: Pili_4(); break; case 6: Pili_5(0); break; case 7: Pili_5(1); break; } // Next demo function if (count >= DEMO_COUNT) { if (++fun > DEMO_FUNS) { fun = 1; } ResetState(); } } }
PIC18F67J50 若有啟動 PLL, 在執行前必須等待致少 2ms 時間 初始設定 PORTD 全部設為輸出,點亮 bit0 的 LED。
void InitIO(void) { // On the PIC18F87J50 Family of USB microcontrollers, the PLL will not power up and be enabled // by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL). { int pll_startup_counter = 27000; // 27000 x 0.083us ~= 2.241 ms OSCTUNEbits.PLLEN = 1; //Enable the PLL and wait 2+ms until the PLL locks before enabling USB module while(pll_startup_counter--); } LATD = 0x01; TRISD = 0x00; // Initializee all PORTD(LED) as input pin RCONbits.IPEN = 0; INTCONbits.GIEH = 0; INTCONbits.GIEL = 0; }
當切換到下一個功能時,重設變數
void ResetState(void) { count = 0; dir = 0; n = 0; }
特效功能函數
// 左右來回 void Pili_1(void) { if (n == 0) { LATD = (dir ? 0x80 : 0x01); //DelayMs(DEMO_DELAY); } else { (dir == 0) ? (LATD <<= 1) : (LATD >>= 1); } DelayMs(DEMO_DELAY); if (++n == 8) { if (dir == 1) count++; dir ^= 1; n = 0; } } // 向左 或 向右 void Pili_2(unsigned char dir) { if (n == 0) { LATD = (dir ? 0x80 : 0x01); } else { (dir == 0) ? (LATD <<= 1) : (LATD >>= 1); } DelayMs(DEMO_DELAY); if (++n == 8) { count++; n = 0; } } // 向內再向外 void Pili_3(void) { if (n == 0) { LATD = (dir ? 0x18 : 0x81); } else { if (dir == 0) LATD = ((PORTD & 0xF0) >> 1) | ((PORTD & 0x0F) << 1); else LATD = ((PORTD & 0xF0) << 1) | ((PORTD & 0x0F) >> 1); } DelayMs(DEMO_DELAY); if ((++n % 4) == 0) { dir ^= 1; if (n == 8) { count++; n = 0; } } } // 數字累加及遞減 // 2012-11-14 修正數字遞減 Demo 跳過的問題 void Pili_4(void) { if (n == 0) { LATD = 0x01; n++; } else { (dir == 0) ? (LATD++) : (LATD--); } DelayMs(DEMO_DELAY); Bingo(LATD); if (LATD == 0x00 || LATD == 0xFF) { dir ^= 1; if (LATD == 0) { count += DEMO_COUNT; n = 0; } } } // 向左或向右對齊 void Pili_5(unsigned char dir) { static unsigned char data = 0x00, temp, round = 0; if (n == 0) { temp = (dir ? 0x80 : 0x01); } else { (dir == 0) ? (temp <<= 1) : (temp >>= 1); } LATD = (data | temp); DelayMs(DEMO_DELAY); n++; if (round + n == 8) { data |= temp; round++; n = 0; } Bingo(LATD); if (LATD == 0xFF) { count += DEMO_COUNT; data = 0x00; round = n = 0; } }
某些特效累積到 0xFF 或遞減到 0x00 則呼叫此函數
void Bingo(unsigned char value) { int i; switch (value) { case 0x00: DelayMs(DEMO_DELAY); DelayMs(DEMO_DELAY); break; case 0xFF: for (i = 0; i < 3; i++) { DelayMs(DEMO_DELAY); DelayMs(DEMO_DELAY); LATD = 0x00; DelayMs(DEMO_DELAY); DelayMs(DEMO_DELAY); LATD = 0xFF; } break; } }
時間延遲 (單位:ms)
// Delay ? ms void DelayMs(unsigned int ms) { unsigned int i; for (i = 0; i < ms; i++) Delay1KTCYx(12); // 12 x 0.083us = ~ 1 ms }
2012-11-14 修正數字遞減 Demo 跳過的問題
回覆刪除請問可以把這程式編譯成18f4520用的嗎?
回覆刪除如果只是單純的學習用途都可以, 這是C語言,調整一下應該就可以用了, 如:Configuration Bits 設定
回覆刪除那請問要怎麼改可以講明確一點嗎目前我只知道HS
回覆刪除因為不知道你的振盪器是多少, 我手邊也沒有此顆 IC, 在這裏假設你是使用 MCU 內部的 8MHz 高速 OSC, 不使用 PLL (PLL 依你的需求, 可將 clock 拉到 8MHz x 4 = 32 MHz)。
刪除因為 OSC 已改成 8MHz, 所以一個指令週期變成 4 / 8MHz = 0.5us, 請依底下修改
=====[ ConfigurationBits.h ]=====
將 ConfigurationBits.h 的設定換成底下內容 (相關設定請參考 C18 的 doc\hlpPIC18ConfigSet.chm 文件)
#pragma config OSC = INTIO67 // Internal oscillator block, port function on RA6 and RA7
#pragma config BOREN = OFF // Brown-out Reset disabled in hardware and software
#pragma config WDT = OFF // WDT disabled (control is placed on the SWDTEN bit)
#pragma config MCLRE = ON // MCLR pin enabled; RE3 input pin disabled
=====[ main.c ]=====
函式 InitIO 內的第一個大括號程式碼, 以底下置換掉
OSCCON = 0x01110011; // INTOSC 8 MHz as system clock
OSCTUNEbits.PLLEN = 0; // PLL disabled
函式 DelayMs 的 Delay 改成底下
Delay1KTCYx(2); // 2k x 0.5us = ~ 1 ms
~~~祝你成功~~~
請問如果只要讓八顆LED閃爍的話如何寫會比較迅速方便?? 謝謝!!
回覆刪除hi, 你好
刪除我的做法會直接呼叫 Bingo(0xFF)
for(;;) /* main event loop */
刪除{
if(led_index == 0x03)
led_index = 0x20;
else
led_index = led_index << 1 ;
led_index = !led_index;
outputByte(led_index); //LED狀態
outputControl(0x20); //LATCH
outputControl(0x0);
_delay_ms(500);
}
return 0;
我的主要程式是這個!! 但是有一個題目是說要交替亮與暗變成是4顆暗4顆亮!!這樣的話要怎麼修改!!謝謝你
完整專案檔下載:Pili_LED.zip (6 KB)無法下載,是否願意分享,謝謝!!! kevin.122759@yahoo.com.tw
回覆刪除Hi le kevin, 連結已更新了, 可以下載了
刪除#include
回覆刪除#include
請問main.h中的這兩個.h檔該從哪裡取得呢?
謝謝
p18f67j50.h
刪除delays.h