lbed

2013/08/11からのアクセス回数 6622

LPC1343学習基板に戻って

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

実験に使用するのは、以下の3つです。

汎用入出力GPIOの使い方編

lbedにはまだ汎用入力クラスがありませんので、この機会に作成しました。 詳しくは、lbed/08a-ARM学習基板用追加クラスを参照してください。

実験開始

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

タッチセンサーPCF8883の出力オープン・ドレインHigth *1 なので、LPC1343の入力ピンは、プルダウンモードにセットする必要があります。 *2

TouchSensor.png

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

#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);
    while(1) {
         myled = sw;
    }
}

USB仮想シリアルポートを使う

LPC1343では、USBをサポートしており、例題にもCDC(USB仮想シリアルポート) を使っています。

そこで、SerialクラスのサブクラスとしてSerialCDCを作ってUSB CDCを使えるように しました。 *3

USBの実験にはトランジスタが必要

当初、ARM学習基板のトランジスタを付けないでUSB CDCのテストをしたら、 上手く動作しませんでした。本を調べて見るとUSB D+ラインのプルアップ制御に トランジスタ2SA1015が必要だと分かり、急遽取り付けました。

Add_TRG.png

テスト用のソース

テスト用のプログラムとしてTestCDC.cppを以下の様に作成しました。 USB CDCが認識されるまで、少し時間がかかるため、最初にキー入力 を待つことにしました。 *4

#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);

     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;
}

Arduinoのシリアルモニターに出力した様子を以下に示します。 &ref(): File not found: "CDC_Screen.png" at page "lbed/08-ARM学習基板で実験";

アナログ入力を試す

アナログ入力クラスAnalogInも追加しました。 *5

ジャンパ線の設定

ARM学習基板は、いろんなチップのてんこ盛りなので、実験をするにはジャンパ線で 接続しなくてはなりません。 *6

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

Fig8_1.png

P3には、U2から取った基準電圧1.25Vと電圧測定用のOPアンプU3を使って、電圧が供給されています。

に接続されています。

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

Fig8_2.png

アナログ回路の動作確認

P3の3番ピンCh6に安定電源1.8Vを半固定抵抗で1.308Vに減圧して入力としました。 $$ V = (1.308 - 1.25)*11 + 1.25 = 1.888 $$ が、Ch6の予想結果です。

ADC_Test.png

テストプログラムTestADC.cppは、Printクラスの#if文を有効にして使いました。*8

#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);
     SerialCDC pc(USBTX, USBRX);
     pc.baud(9600);
     // キー入力を待つ
     pc.read();

    AnalogIn     agnd(P1_2);
    AnalogIn     dc(P1_10);
    while(1) {
         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と予想と近い結果が出ています。

ADC_Screen.png

温度センサーIC LM75Bを使ってみる

ARM学習基板には、I2Cのテストをするために温度センサーLM75Bが付いています。 これを使って、温度を取得してみます。

LM75Bのアドレスは、A2, A1, A0の接続によってユーザが変えることができるようになっています。 *9

本の11章の図4は、大きなミスプリがあります。

Fig11_4.pngFig0_2.png

右がプロローグの図2から引用したものです。この図からLM75Bのアドレスは、1001001(0x49)となります。

LM75Bクラス

次にLM75BのクラスをLBED_LPC13xx_USERLIB/src/LM75B.cppに実装します。

本当に驚くくらい簡単でしょう!

#include "lbed.h"
#include "LM75B.h"

LM75B::LM75B(PinName sda, PinName scl) : i2c(sda, scl)
{
     char cmd[2];
     // LM73設定
     cmd[0]    = 0x00;     // register 0
     cmd[1]    = 0x28;   // 温度レジスタを選択
     i2c.write( LM75_ADDR, cmd, 2);
}

LM75B::~LM75B()
{
}

float LM75B::read()
{
     char cmd[2];

     i2c.read( LM75_ADDR, cmd, 2); // Send command string
     unsigned int int_val = cmd[0] <<3 | cmd[1]>>5;
     return float(int_val*125/1000.0);
}

LCDとの接続

アナログ入力の例では、USB CDCを使ったので、今回はLCDを使います。

ARM学習基板のP4とStar OrangeボードのPinとLPC1343ボードピンの対応は、以下の様になります。

P4StarOrangePC1343機能
1p1p1GND
39p40p403.3V
33p24p26rs
31p26p22e
23p27p14d4
21p28p6d5
19p29p5d6
17p30p25d7

LM75B.png

テストプログラムと結果

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

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

#include"lbed.h"
#include "TextLCD.h"
#include "LM75B.h"

int main(void) {
     wait_init();
     DigitalOut myled(LED2);
    TextLCD lcd(p26, p22, p14, p6, p5, p25);     // rs, e, d4-7
     LM75B lm75b(p28, p27);
     lcd.print("Hello World");

     while (1) {
          float t = lm75b.read();
          lcd.locate(0, 1);
          lcd.print("Temp:");
          lcd.print(t);
          myled = !myled;
          wait_ms(1000);
     }
     return 0;
}

時計に付いてきた温度計を結果を比べてみました。時計が27.0度、LM75Bが27.50度でした。

Temp.png

リアルタイムクロック(SPI接続)を使う

リアルタイムクロックのテストには苦労しました。 *10

ジャンパ線の設定は以下の様になります。

RTC_setting.png

リアルタイムクロックのクラス

リアルタイムクロックPCF2123のクラスは、 Linux Kernel Doxygen を参考にしました。

#include "lbed.h"
#include "PCF2123.h"

PCF2123::PCF2123(PinName mosi, PinName miso, PinName sclk, PinName sel)
     : _spi(mosi, miso, sclk)
     , _sel(sel)
{
     _sel = 0;
     _spi.frequency(SPI_FREQUENCY);
    wait_ms( 1 );
    // initialize RTC
     command((WRITE_BIT|SUBADDR|REG_CTRL1),RESET);     // Send a software reset command
     wait_us(1);
     command((WRITE_BIT|SUBADDR|REG_CTRL1), 0x20);     // Stop the counter first
     wait_us(1);
     _sel = 1;
     int ret = read((READ_BIT|SUBADDR|REG_CTRL1));
     _sel = 0;
     command((WRITE_BIT|SUBADDR|REG_CTRL1), 0x00);     // Start the counter
     wait_us(1);
}

PCF2123::~PCF2123()
{
}

unsigned char PCF2123::read(unsigned char reg)
{
     int val = _spi.write(reg);
     return val;
}

void PCF2123::command(unsigned char reg, unsigned char dat)
{
     _sel = 1;
     _spi.write(reg);
     _spi.write(dat);
     _sel = 0;
}

void PCF2123::read_rtc()
{
     _sel = 1;
     read((READ_BIT|SUBADDR|REG_SC));
     S = read(READ_NEXT);
     M = read(READ_NEXT);
     H = read(READ_NEXT);
     D = read(READ_NEXT);
     W = read(READ_NEXT);
     N = read(READ_NEXT);
     Y = read(READ_NEXT);
     _sel = 0;
}

void      PCF2123::set_alarm(
          unsigned char s,
          unsigned char m,
          unsigned char h,
          unsigned char d,
          unsigned char w,
          unsigned char n,
          unsigned char y)
{
     command((WRITE_BIT|SUBADDR|REG_CTRL1), 0x20);     // Stop the counter first
     wait_us(1);
     _sel = 1;
     read((WRITE_BIT|SUBADDR|REG_SC));
     read(s);
     read(m);
     read(h);
     read(d);
     read(w);
     read(n);
     read(y);
     _sel = 0;
     wait_us(1);
     command((WRITE_BIT|SUBADDR|REG_CTRL1), 0x00);     // Start the counter
     wait_us(1);
}

動作確認

シリアルCDCでリアルタイムクロックの値を表示するテストプログラムで動作を確認しました。

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

#include"lbed.h"
#include "PCF2123.h"

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

     SerialCDC pc(USBTX, USBRX);
     pc.baud(9600);
     // キー入力を待つ
     pc.read();
     pc.println("Real Time Clock Test.");

     PCF2123     rtc(MOSI, MISO, SCKL, P0_2);
     rtc.set_alarm(0x45, 0x59, 0x23, 0x31, 0x06, 0x12, 0x10);

     int     pS = 0xff;
     while (1) {
          rtc.read_rtc();
          if (pS != rtc.S) {
               pc.printf("%d%d/%d%d/%d%d[%d] ", (rtc.Y>>4)&0xf, rtc.Y&0xf, (rtc.N>>4)&0xf, rtc.N&0xf,(rtc.D>>4)&0xf, rtc.D&0xf, rtc.W&0x7);
               pc.printf("%d%d:%d%d:%d%d\r\n",(rtc.H>>4)&0xf, rtc.H&0xf, (rtc.M>>4)&0xf, rtc.M&0xf,(rtc.S>>4)&0xf, rtc.S&0xf);
               myled = !myled;
               pS = rtc.S;
          }
          wait_ms(100);
     }
     return 0;
}

出力結果は、以下の様になります。

RTC_screen.png

最新のソース

最新のソースは、Githubの以下のURLからダウンロードできます。

コメント


(Input image string)

*1 ON時にHightレベルが出力され、OFF時にはハイ・インピーダンスになります
*2 あるいは、プルダウン抵抗を付ける方法もあります
*3 詳しくは、lbed/08a-ARM学習基板用追加クラスを参照してください。
*4 コンパイルには、ForSerialCDC_usbhw.cをTestCDC.cppと同じディレクトリ入れて下さい
*5 詳しくは、lbed/08a-ARM学習基板用追加クラスを参照してください。
*6 その分、各チップを別の実験に使うことができるようにCPUと切り離されています
*7 トラ技2013/8号のエレキ数式も便利です
*8 サイズが大きくなりますので、注意してください
*9 '1001 + A2, A1, A0がアドレスになります。
*10 ssp.cのSSP_IOConfigでPIO2_11を使うように#if文を変更しなくてはなりません。

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