16-channel Fm+ I2C-bus 57 mA/20 V constant current LED driver

Dependencies:   mbed

Revision:
0:a872e4dd8ec3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCA9955A.cpp	Wed Feb 04 06:09:08 2015 +0000
@@ -0,0 +1,180 @@
+#include "mbed.h"
+#include "PCA9955A.h"
+ 
+I2C i2c(p28,p27);        // sda, scl
+Serial pc(USBTX, USBRX); // tx, rx
+char cmd[32];
+int i, j, k;
+int sw;
+ 
+void set_ch(char sel)
+{    // PCA9541のサンプル
+        // MST_0側の自分にスレーブ側の制御権を得る場合
+    cmd[0] = 1;                     // PCA9541 コマンドコード Cont Reg
+    i2c.write( 0xe2, cmd, 1);       // Cont Regを指定
+    i2c.read( 0xe2, cmd, 1);        // Cont Regを読込み
+    wait(0.1);                      // 0.1s待つ
+    switch(cmd[0] & 0xf)
+    {
+    case 0:                         // bus off, has control
+    case 1:                         // bus off, no control
+    case 5:                         // bus on, no control
+        cmd[0] = 1;                 // PCA9541 コマンドコード Cont Reg
+        cmd[1] = 4;                 // bus on, has control
+        i2c.write( 0xe2, cmd, 2);   // Cont Regにcmd[1]を書込み
+        i2c.read( 0xe2, cmd, 1);    // Cont Regを読込み
+        break;
+    case 2:                         // bus off, no control
+    case 3:                         // bus off, has control
+    case 6:                         // bus on, no control
+        cmd[0] = 1;                 // PCA9541 コマンドコード Cont Reg
+        cmd[1] = 5;                 // bus on, has control
+        i2c.write( 0xe2, cmd, 2);   // Cont Regにcmd[1]を書込み
+        i2c.read( 0xe2, cmd, 1);    // Cont Regを読込み
+        break;
+    case 9:                         // bus on, no control
+    case 0xc:                       // bus on, no control
+    case 0xd:                       // bus off, no control
+        cmd[0] = 1;                 // PCA9541 コマンドコード Cont Reg
+        cmd[1] = 0;                 // bus on, has control
+        i2c.write( 0xe2, cmd, 2);   // Cont Regにcmd[1]を書込み
+        i2c.read( 0xe2, cmd, 1);    // Cont Regを読込み
+        break;
+    case 0xa:                       // bus on, no control
+    case 0xe:                       // bus off, no control
+    case 0xf:                       // bus on, has control
+        cmd[0] = 1;                 // PCA9541 コマンドコード Cont Reg
+        cmd[1] = 1;                 // bus on, has control
+        i2c.write( 0xe2, cmd, 2);   // Cont Regにcmd[1]を書込み
+        i2c.read( 0xe2, cmd, 1);    // Cont Regを読込み
+        break;
+    default:
+        break;
+    }
+
+    cmd[0] = sel;                   // PCA9546 Cont Reg sel channel enabled
+    i2c.write( 0xe8, cmd, 1);       // Send command string
+}
+
+int main ()
+{
+    i2c.frequency(100000);
+    pc.printf("PCA9955A Sample Program\r\n");
+    
+    set_ch(1);              // PCA9955Aはch0に接続
+    
+  // PCA9955A
+    while(1)
+    {
+        pc.printf("シーケンシャル … 1, グラデーション … 2 ? \r\n");
+        pc.scanf("%d", &sw);
+        pc.printf("%d\r\n", sw);
+        switch (sw)
+        {
+        case 1:
+            pc.printf("シーケンシャル Sample Start\r\n");
+
+            cmd[0] = MODE1;
+            cmd[1] = 0x0;           // SLEEP = 0
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            cmd[0] = LEDOUT0 + 0x80;   // LEDOUT0, Auto incriment
+            cmd[1] = 0xaa;          // LED3,2,1,0 10= PWM
+            cmd[2] = 0xaa;          // LED7,6,5,4 10= PWM
+            cmd[3] = 0xaa;          // LED11,10,9,8 10= PWM
+            cmd[4] = 0xaa;          // LED15,14,13,12 10= PWM
+            i2c.write(PCA9955A_ADDR, cmd, 5);   // cmd[0]Regにcmd[1-4]を書込み
+
+            cmd[0] = IREF0 + 0x80;           // IREF0, Auto incriment
+            for(i=0; i<16; i++)  cmd[i+1] = 0x80;   // all IREF = 50%
+            i2c.write(PCA9955A_ADDR, cmd, 17);   // cmd[0]Regにcmd[1-16]を書込み
+
+            for(k=0; k<3; k++)      // 3回繰返す
+            {
+                for(i=0; i<16; i++) // チャネル0~15まで一つずつ点灯
+                {
+                    cmd[0] = PWM0 + 0x80;           // PWM0, Auto incriment
+                    for(j=0; j<16; j++)  cmd[j+1] = 0x0;   // all LED PWM = 0%
+                    cmd[i+1] = 0xff;   // iチャネルのLED PWM = 99.6%
+                    i2c.write(PCA9955A_ADDR, cmd, 17);   // cmd[0]Regにcmd[1-16]を書込み
+                    wait(0.5);
+                }
+            }
+            pc.printf("シーケンシャル Sample End\r\n");
+            break;
+        case 2:
+            pc.printf("グラデーション Sample Start\r\n");
+
+            cmd[0] = MODE1;
+            cmd[1] = 0x0;           // SLEEP = 0
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            cmd[0] = LEDOUT0 + 0x80;   // LEDOUT0, Auto incriment
+            cmd[1] = 0x55;          // LED3,2,1,0 01= ON
+            cmd[2] = 0x05;          // LED7,6 00= OFF  LED5,4 01= ON 
+            cmd[3] = 0x00;          // LED11,10,9,8 00= OFF
+            cmd[4] = 0x00;          // LED15,14,13,12 00= OFF
+            i2c.write(PCA9955A_ADDR, cmd, 5);   // cmd[0]Regにcmd[1-4]を書込み
+
+/*            cmd[0] = PWMALL;
+            cmd[1] = 0xFF;           // PWM = 99.6%
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+*/
+            cmd[0] = GRAD_GRP_SEL1;
+            cmd[1] = 0x50;           // LED3, 4 = GRP0
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            cmd[0] = IREFALL;         //
+            cmd[1] = 0x1;           // あとでIREF_GRP0で設定するので1以上であればよい
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+/*            cmd[0] = IREF4;         //
+            cmd[1] = 0x1;           // Idrv = 240 * 40uA(Rext = 5.6k)=9.6mA
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+*/
+            cmd[0] = GRAD_MODE_SEL0;
+            cmd[1] = 0x31;           // LED0, 4, 5 = Gradation
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            cmd[0] = GRAD_GRP_SEL0;
+            cmd[1] = 0x0;           // LED0, 1, 2, 3 = GRP0
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+
+            cmd[0] = IREF_GRP0;
+            cmd[1] = 0xF0;           // Idrv = 240 * 40uA(Rext = 5.6k)=9.6mA
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            cmd[0] = STEP_TIME_GRP0;
+            cmd[1] = 0x3F;           // 0.5ms * 64 = 32ms
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            cmd[0] = RAMP_RATE_GRP0;
+            cmd[1] = 0xc0 + 0x31;    // Ramp up/down ON, Ramp rate = 50
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            cmd[0] = HOLD_CNTL_GRP0;
+            cmd[1] = 0xc0 + (0x1 << 3) + 0x2;   // Hold ON/OFF ON, ON = 0.25s, OFF = 0.5s
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            cmd[0] = GRAD_CNTL;
+            cmd[1] = 0x3;           // Gradation ON, Continuous
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            wait(15);               // 15s 待つ
+
+            cmd[0] = GRAD_CNTL;
+            cmd[1] = 0x0;           // Gradation OFF
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            cmd[0] = GRAD_MODE_SEL0;
+            cmd[1] = 0x0;           // LED0, 4, 5 = Normal
+            i2c.write(PCA9955A_ADDR, cmd, 2);   // cmd[0]Regにcmd[1]を書込み
+
+            pc.printf("グラデーション Sample End\r\n");
+            break;
+        default:
+            break;
+        }    
+    }
+}
+