[[lbed]]


#contents




2013/08/11からのアクセス回数 &counter;




** LPC1343学習基板に戻って [#dfe6450c]
cortex-m3の勉強のために買った「ARMマイコンパーフェクト学習基板の使い方」をlbedを使うとどのくらい簡単に
なるかを試してみます。




実験に使用するのは、以下の3つです。
- ARMマイコンパーフェクト学習基板
- LPC-LINK
- Star Orangeボードと3.3Vで動作するLCD




** 汎用入出力GPIOの使い方編 [#i15ae2a5]
lbedにはまだ汎用入力クラスがありませんので、この機に作ってみます。


まずは、mbedのDigitalInのAPIを以下のURLで調べます。
- http://mbed.org/handbook/DigitalIn
lbedにはまだ汎用入力クラスがありませんので、この機会に作成しました。
詳しくは、[[lbed/08a-ARM学習基板用追加クラス]]を参照してください。


DigitalOut.cppをコピーして作りました。


クラス定義のDigitalIn.cppは、ほとんどDigitalOut.cppと同じです。


*** 実験開始 [#be68aa6f]
ジャンパP4の3と4、31と32にジャンパーをセットし、タッチエリアに触れるとLEDが点灯するテストプログラムを作ります。


タッチセンサーPCF8883の出力オープン・ドレインHigth
((ON時にHightレベルが出力され、OFF時にはハイ・インピーダンスになります))
なので、LPC1343の入力ピンは、プルダウンモードにセットする必要があります。
((あるいは、プルダウン抵抗を付ける方法もあります))




&ref(TouchSensor.png);




テストプログラムTestSwitch.cppは、以下の様になります。
タッチセンサーに触れるとLEDが点灯し、離すとLEDが消えれば成功です。


#pre{{
#include "platform.h"
#include "PinNames.h"
#include "DigitalIn.h"
#include <cr_section_macros.h>
#include <NXP/crp.h>

DigitalIn::DigitalIn()
     : _pin(-1)
     , _gpio(0)
     , _mask(0)
{
}
// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP extern const unsigned int CRP_WORD = CRP_NO_CRP ;

DigitalIn::DigitalIn(PinName pin, const char* name)
     : _pin(-1)
     , _gpio(0)
     , _mask(0)
{
     setup(pin, name);
}
#include "lbed.h"

void DigitalIn::setup(PinName pin, const char* name)
{
     _pin = pin;
     _gpio = 0;
     _mask = 0;
     _io = 0;
     if (_pin >= P0_0 && _pin <= P0_31) {
          _gpio = LPC_GPIO0;
          _mask = 1 << (_pin - P0_0);
          switch(_pin - P0_0) {
          case 1: _io = &LPC_IOCON->PIO0_1; *_io = 0xd0; break;
          case 2: _io = &LPC_IOCON->PIO0_2; *_io = 0xd0; break;
          case 3: _io = &LPC_IOCON->PIO0_3; *_io = 0xd0; break;
          case 4: _io = &LPC_IOCON->PIO0_4; *_io = 0xd0; break;
          case 5: _io = &LPC_IOCON->PIO0_5; *_io = 0xd0; break;
          case 6: _io = &LPC_IOCON->PIO0_6; *_io = 0xd0; break;
          case 7: _io = &LPC_IOCON->PIO0_7; *_io = 0xd0; break;
          case 8: _io = &LPC_IOCON->PIO0_8; *_io = 0xd0; break;
          case 9: _io = &LPC_IOCON->PIO0_9; *_io = 0xd0; break;
          case 10: _io = &LPC_IOCON->SWCLK_PIO0_10; *_io = 0xd0; break;
          case 11: _io = &LPC_IOCON->R_PIO0_11; *_io = 0xd0; break;
          }
     } else if (_pin >= P1_0 && _pin <= P1_31) {
          _gpio = LPC_GPIO1;
          _mask = 1 << (_pin - P1_0);
          switch(_pin - P1_0) {
          case 0: _io = &LPC_IOCON->R_PIO1_0; *_io = 0xd0; break;
          case 1: _io = &LPC_IOCON->R_PIO1_1; *_io = 0xd0; break;
          case 2: _io = &LPC_IOCON->R_PIO1_2; *_io = 0xd0; break;
          case 3: _io = &LPC_IOCON->SWDIO_PIO1_3; *_io = 0xd0; break;
          case 4: _io = &LPC_IOCON->PIO1_4; *_io = 0xd0; break;
          case 5: _io = &LPC_IOCON->PIO1_5; *_io = 0xd0; break;
          case 6: _io = &LPC_IOCON->PIO1_6; *_io = 0xd0; break;
          case 7: _io = &LPC_IOCON->PIO1_7; *_io = 0xd0; break;
          case 8: _io = &LPC_IOCON->PIO1_8; *_io = 0xd0; break;
          case 9: _io = &LPC_IOCON->PIO1_9; *_io = 0xd0; break;
          }
     } else if (_pin >= P2_0 && _pin <= P2_31) {
          _gpio = LPC_GPIO2;
          _mask = 1 << (_pin - P2_0);
          switch(_pin - P2_0) {
          case 0: _io = &LPC_IOCON->PIO2_0; *_io = 0xd0; break;
          case 1: _io = &LPC_IOCON->PIO2_1; *_io = 0xd0; break;
          case 2: _io = &LPC_IOCON->PIO2_2; *_io = 0xd0; break;
          case 3: _io = &LPC_IOCON->PIO2_3; *_io = 0xd0; break;
          case 4: _io = &LPC_IOCON->PIO2_4; *_io = 0xd0; break;
          case 5: _io = &LPC_IOCON->PIO2_5; *_io = 0xd0; break;
          }
     } else if (_pin >= P3_0 && _pin <= P3_31) {
          _gpio = LPC_GPIO3;
          _mask = 1 << (_pin - P3_0);
     }
     if (_gpio) {
          _gpio->DIR &= ~_mask;
     }
int main(void) {
    wait_init();
    DigitalOut     myled(LED2);
    DigitalIn     sw(P2_4);
    sw.mode(PullDown);
    while(1) {
         myled = sw;
    }
}
}}

void DigitalIn::mode(PinMode mode) {
     switch (mode) {
     case PullUp:
          *_io = 0xd0;     // MODE = 10
          break;
     case PullDown:
          *_io = 0xc8;     // MODE = 01 マニュアルだと0xc8になりそうなのだが、パーフェクト基板本では0x48とある
          break;
     case PullNone:          // MODE = 00
          *_io = 0xc0;
          break;
     case OpenDrain:          // TODO 未実装
          break;
     default:
          *_io = 0xd0;
     }
}
** USB仮想シリアルポートを使う [#p96d779c]
LPC1343では、USBをサポートしており、例題にもCDC(USB仮想シリアルポート)
を使っています。

int DigitalIn::read()
{
     return _gpio && (_gpio->DATA & _mask) ? 1 : 0;
}
そこで、SerialクラスのサブクラスとしてSerialCDCを作ってUSB CDCを使えるように
しました。
((詳しくは、[[lbed/08a-ARM学習基板用追加クラス]]を参照してください。))

}}


何かたくさんの定義をしたように思えるかも知れませんが、これによってDigitalOut.cppはとても簡単になります。
*** USBの実験にはトランジスタが必要 [#f870441a]
当初、ARM学習基板のトランジスタを付けないでUSB CDCのテストをしたら、
上手く動作しませんでした。本を調べて見るとUSB D+ラインのプルアップ制御に
トランジスタ2SA1015が必要だと分かり、急遽取り付けました。

&ref(Add_TRG.png);


*** テスト用のソース [#od04912d]
テスト用のプログラムとしてTestCDC.cppを以下の様に作成しました。
USB CDCが認識されるまで、少し時間がかかるため、最初にキー入力
を待つことにしました。
((コンパイルには、ForSerialCDC_usbhw.cをTestCDC.cppと同じディレクトリ入れて下さい))


#pre{{
#include "platform.h"
#include "PinNames.h"
#include "DigitalOut.h"
#include "DigitalIn.h"
#include <cr_section_macros.h>
#include <NXP/crp.h>

DigitalOut::DigitalOut()
{
}
// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP extern const unsigned int CRP_WORD = CRP_NO_CRP ;

DigitalOut::DigitalOut(PinName pin, const char* name)
{
     setup(pin, name);
}
#include "lbed.h"

void DigitalOut::setup(PinName pin, const char* name)
{
     DigitalIn::setup(pin, name);
     if (_gpio) {
          _gpio->DIR |= _mask;

int main(void) {
     wait_init();
     DigitalOut myled( LED2);

     SerialCDC pc(USBTX, USBRX);
     pc.baud(9600);
     // キー入力を待つ
     pc.read();

     pc.println("Hello");
     while (1) {
          char c = pc.read();
          pc.write(c + 1);
          myled = !myled;
     }
     return 0;
}
}}

*** 実験開始 [#eb8744bc]
ジャンパP4の3と4、31と32にジャンパーをセットし、タッチエリアに触れるとLEDが点灯するテストプログラムを作ります。
Arduinoのシリアルモニターに出力した様子を以下に示します。
&ref(CDC_Screen.png);

タッチセンサーPCF8883の出力オープン・ドレインHigth
((ON時にHightレベルが出力され、OFF時にはハイ・インピーダンスになります))
なので、LPC1343の入力ピンは、プルダウンモードにセットする必要があります。
((あるいは、プルダウン抵抗を付ける方法もあります))

** アナログ入力を試す [#z0651bc6]
アナログ入力クラスAnalogInも追加しました。
((詳しくは、[[lbed/08a-ARM学習基板用追加クラス]]を参照してください。))

&ref(TouchSensor.png);
*** ジャンパ線の設定 [#c44d4f43]
ARM学習基板は、いろんなチップのてんこ盛りなので、実験をするにはジャンパ線で
接続しなくてはなりません。
((その分、各チップを別の実験に使うことができるようにCPUと切り離されています))

本の8章、図1からピンの設定の図を引用します。

&ref(Fig8_1.png);

テストプログラムTestSwitch.cppは、以下の様になります。


P3には、U2から取った基準電圧1.25Vと電圧測定用のOPアンプU3を使って、電圧が供給されています。
- P3の3は、AD6(PIO1_10)
- P3の4は、AD7(PIO1_11)
- P3の5は、AD3(PIO1_2)

に接続されています。

次に、P3とLPC1343の接続について、本の8章、図2を引用します。
OPアンプは、非反転増幅回路となっており、ゲインGは、
\( G_{NI} = \frac{R_1 + R_2}{R_1}\)
となることから、P3のCh6, Ch7に入力された電圧は、AGNDとの差が
11倍に増幅された値にAGNDを加算された値がADコンバータの入力電圧
となります。
((トラ技2013/8号のエレキ数式も便利です))


&ref(Fig8_2.png);



*** アナログ回路の動作確認 [#w55a20d9]
P3の3番ピンCh6に安定電源1.8Vを半固定抵抗で1.308Vに減圧して入力としました。
$$
V = (1.308 - 1.25)*11 + 1.25 = 1.888
$$
が、Ch6の予想結果です。

&ref(ADC_Test.png);


テストプログラムTestADC.cppは、Printクラスの#if文を有効にして使いました。((サイズが大きくなりますので、注意してください))


#pre{{
#include <cr_section_macros.h>
#include <NXP/crp.h>

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP extern const unsigned int CRP_WORD = CRP_NO_CRP ;

#include "lbed.h"

int main(void) {
    wait_init();
    DigitalOut     myled(LED2);
    DigitalIn     sw(P2_4);
    sw.mode(PullDown);
    DigitalOut myled(LED2);
     SerialCDC pc(USBTX, USBRX);
     pc.baud(9600);
     // キー入力を待つ
     pc.read();

    AnalogIn     agnd(P1_2);
    AnalogIn     dc(P1_10);
    while(1) {
         myled = sw;
         int     d0 = agnd.read_u16();
         int v0 = 1250*1024/d0;
         int     d1 = dc.read_u16();
         int v1 = v0*d1/1024;
         pc.printf("Ch3:%04d[VDD=%04dmV]  Ch6:%04d[%04dmV]\n", d0, v0, d1, v1);
        myled = ! myled;
        wait_ms(1000);
    }
}
}}

出力結果は、以下の様になっています。1.896mVと予想と近い結果が出ています。

&ref(ADC_Screen.png);


** まだ途中です! [#t45303f7]

** コメント [#r9e6c373]
#comment_kcaptcha


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