說明
這個實驗是使用 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