2011年4月10日 星期日

DIY - PIC:PIC18F4550 PWM 控制 LED 開關程式 (五十五)

DIY - PICPIC18F4550 PWM 控制 LED 開關程式 (五十五)

程式的是從 LED 光暗程式 (DIY - 電子:PIC18F4550 PWM 控制 LED 光暗程式 (五十四) ) 修改成為 LED 開關程式,當按鍵按下,LED 便會慢慢地發亮,LED 便會亮著,如果再按一下按鍵,LED 便會慢慢地暗,直至熄滅。

PIC18F4550 PWM控制LED開關程式流程圖
主程式:

void main(void)
{

    //                              1234567890123456               
    char LCD_name[] ="BWS PWM - RC1 v2";
    char LCD_name2[]="                                  ";
   
unsigned char dc;                       // Duty Cycle
unsigned char key;                     // Keyboard Status
unsigned char keyon = 0;           // Key On = 1   
   
    ADCON0 = 0x00;                     // Disable the AD converter
    ADCON1 = 0x0F;                     // Set all ports to digital
    TRISB = 0b11100000;              // Set PORTB RB5 as Key In
    TRISC = 0b11111001;              // Set PORTC C1 and C2 as PWM output
    LATC  = 0b00000000 ;             // Clear PORTC   

   
    // Initialise LCD
    OpenXLCD(FOUR_BIT&LINES_5X7);   // Init the LCD Display
    while(BusyXLCD());
    WriteCmdXLCD(BLINK_OFF & CURSOR_OFF ); 
    while(BusyXLCD());    
    stdout = _H_USER;                    // Redirect I/O to LCD
    LcdSetLine1();                            // Put cursor on start of line 1
    putsXLCD(LCD_name);             // Display text

//Configure CCP module as (PR2+1)*4*TOSC*T2_PS
    PR2            = 0b10011011;        // PWM Frequency = 152 = 2KHz = 0.5ms
    T2CON      = 0b00000111;        // 1:16
    CCP1CON = 0b00001100;        // PWM Mode P1A/P1C/P1B/P1D=H <5:4> DC
    CCP2CON = 0b00111100;        // PWM Mode P2A/P2C/P2B/P2D=H
                                                        // Duty Cycle CCP1CON<5:4>+CCPR1L
   
    while(1)
    {
        // PWM resolution is 10 bits don't use last 2 less significant bits CCPxCON,
        // so only CCPRxL have to be touched to change duty cycle
        key = 1;
          key = PORTBbits.RB5;

        if (key == 0) {
            if (keyon == 0) {
                    keyon = 1;
                   for(dc = 0 ; dc < 128 ; dc++){
                    CCPR1L = dc ;
                    CCPR2L = 128 - dc ;
                    LcdSetLine2();        // Put cursor on start of line 2
                    printf("LED ON  DC=%04i", CCPR2L);
                    }
            } else {
                    keyon = 0;
                   for(dc = 128 ; dc > 0 ; dc--){
                    CCPR1L = dc ;
                    CCPR2L = 128 - dc ;
                    LcdSetLine2();        // Put cursor on start of line 2
                    printf("LED OFF DC=%04i", CCPR2L);
                    }
            } // End if keyon
        } // End if key
    } // End While
}

▲當按一下鍵,LED 會自動慢慢變亮

▲再按一下鍵,LED 會自動慢慢變暗
LCD 顯示LED狀態及PWM Duty Cycle


2011 04 10 天氣報告
氣溫:22.3 @ 23:00 
相對濕度:百分之80%  
天氣:天色大致良好

4 則留言:

  1. 請問一下 如果我PIC16是外接一個LED Controller
    我只要透過分壓把我算出來的直(頻率) 透過SPI 丟給LED Controller
    他就會自動亮暗了嗎 還是需要設定其他東西

    回覆刪除
  2. 請問這個 LED Controller 的輸入是什麼 (用不同電壓便可調節光暗?)? PIC 的輸出主要是 Digital,祇有兩種狀態 (高電平=5V,低電平=0V),可以用不同的 PWM 寬度通過低通濾波器 (LPF) 變成不同電壓,參考DIY - PIC:PIC18F4550 PWM 正弦波原理 (五十七) :http://bugworkshop.blogspot.hk/2011/04/blog-post_20.html

    回覆刪除
    回覆
    1. 你好 沒錯 我想用分壓 改變光亮 和頻率 我的ADC暫存是12位元 所以我先將ADC轉完的值/1024
      再根據LED 控制器規格 再轉成對應的duty 然後送到對應的暫存器 這樣應該亮度就可以調整了?
      那如果我要控制LED閃10次後停 我可以怎麼設定? 是要靠PIC本身的delay time嗎 ? 感謝

      刪除
    2. 可否看看你的LED 控制器規格,電壓與光暗是否直線比例?是否電壓=0 光暗=0? 光度跟隨電壓上昇而變光? 如要LED閃10次後停,因為是閃10次的關係,最好使用 Counter。

      刪除