[[lbed]]

#contents

2013/07/27からのアクセス回数 &counter;

** PWM(Pluse Width Modulation)を使う [#ubb85f39]
LEDの明るさを変えるには、周期的にLEDのON/OFFを繰り返し、ONの時間を変える方法がPWMです。

*** LEDとの接続 [#g862291f]
MyARMのp21からp26までのPWMにIOピンの内、PWMに使えそうなのはp21, p23, p26ですが、
p21でLPC-LinkのSWCLKで使っているので、LPC-Linkを使っている人は絶対に指定しないで下さい。
((私も試しに指定してその後、LPC-Linkが使えなくなって大変でした。シリアルからプログラムを書き込みMagicFlashで別のプログラムを書き込んで復活しました。))
また、p23はどうも上手く動作しませんでした。((詳しく調査できていません))

IOにLEDを接続する場合、IOをHighの場合のLEDを点灯する正論理と、IOがLowの場合に場合に点灯する負論理が
ありますが、どうも正論理でLEDを接続するとLEDが完全に消灯しません。((原因がよく分からないので、詳しい人に問い合わせ中です))

今回は、負論理でp26にLEDのカソードをつなぎ、アノード((線の長い方))に470Ωの抵抗を直列につなぎ、3.3Vに接続しています。

&ref(PWMSetting.png);


*** サンプルプログラム [#m6486cd2]
サンプルプログラムでは、PwmOutのインスタンスledを生成し、200m秒毎に0.05ずつ値を大きくする
(明るさを少なくする)もので、これを4秒間隔で繰り返します。

#pre{{
#include<cr_section_macros.h>
#include<NXP/crp.h>
__CRP extern const unsigned int CRP_WORD = CRP_NO_CRP ;

#include "lbed.h"

int main(void) {
    wait_init();
    PwmOut led(p26);
    led = 0.0;
    while(1) {
        led = led + 0.05;
        wait_ms(200);
        if(led >= 1.0) {
            led = 0.0;
        }
    }
}
}}

** PWMOutクラスの実装 [#y9c7050d]
サンプルプログラムのPWMを参考にPWMOutクラスを作成します。

最初、timer16.c, timer32.cのsetMatch_timer16PWM, setMatch_timer32PWM関数は、HEIGHTからLOWに変化するものと
勘違いして、pulsewidthを実装していたのですが、以下のタイマー機能の説明によるとLOWからHEIGHTになるものだと分かりました。

タイマー機能を使ってPWMを実装する場合の説明が、トラ技2012年10月号の図13にあるので、引用します。
&ref(Fig13-TRG.png);



いつものように、サンプルのtimer16.[hc], timer32.[hc]の先頭に_を付け、ヘッダファイルの先頭の__TIMER16_Hの後に、
extern文を追加し、
#pre{{
#ifndef __TIMER16_H 
#define __TIMER16_H

#ifdef __cplusplus
extern"C" {
#endif
}}


最後に
#pre{{
#ifdef __cplusplus
}
#endif

#endif/* end __TIMER16_H */

}}
を付けて、C++からCの関数が使えるようにします。

PwmOut.cppは以下の様にしました。
#pre{{
#include "platform.h"
#include "PinNames.h"
#include "PwmOut.h"

#include <LPC11xx.h>
#include "type.h"
#include "_timer16.h"
#include "_timer32.h"

#define     NULL     (0L)

PwmOut::PwmOut(PinName pin) :
     _name(NULL), _period(0.02), _pulsewidth(0.0), _value(0.0)
{
     _pin = pin;
     setup(_period);
     /* Enable AHB clock to the GPIO domain. */
     LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
}

void PwmOut::setup(float period) {
     _period = period;
     uint32_t p = (uint32_t)(SystemCoreClock*_period);
     uint32_t matchTime = (_period - _pulsewidth)*p;
     // PWMに使えるのは、p21-23, p26です。
     switch (_pin) {
     case p21:     // PIO0_10     CT16M2
          init_timer16PWM(0, p, MATCH2, 0);
          setMatch_timer16PWM (0, 2, matchTime);
          enable_timer16(0);
          break;
     case p22:     // PIO0_2     CT16B0C0
          break;
     case p23:     // PIO0_11     CT32M3
          init_timer32PWM(0, p, MATCH3);
          setMatch_timer32PWM(0, 3, matchTime);
          enable_timer32(0);
          break;
     case p25:     // PIO1_8     CT16B1C0
          break;
     case p26:     // PIO1_9     CT16M0
          init_timer16PWM(1, p, MATCH0, 0);
          setMatch_timer16PWM (1, 0, matchTime);
          enable_timer16(1);
          break;
     }
}

void PwmOut::period(float seconds) {
     setup(seconds);
}

void PwmOut::pulsewidth(float seconds) {
     _pulsewidth = seconds;
     uint32_t p = (uint32_t)(SystemCoreClock*_period);
     uint32_t matchTime = (_period - _pulsewidth)*p;
     // PWMに使えるのは、p21, 23, p26です。
     switch (_pin) {
     case p21:     // PIO0_10     CT16M2 注意)LPC-Linkを使っている場合には設定してはいけない!
          disable_timer16(0);
          setMatch_timer16PWM (0, 2, matchTime);
          enable_timer16(0);
          break;
     case p22:     // PIO0_2     CT16B0C0
          break;
     case p23:     // PIO0_11     CT32M3
          disable_timer32(0);
          setMatch_timer32PWM(0, 3, matchTime);
          enable_timer32(0);
          break;
     case p25:     // PIO1_8     CT16B1C0
          break;
     case p26:     // PIO1_9     CT16M0
          disable_timer16(1);
          setMatch_timer16PWM (1, 0, matchTime);
          enable_timer16(1);
          break;
     }
}
}}


** コメント [#c81be729]
#vote(おもしろかった,そうでもない,わかりずらい)

皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
SmartDoc