スッピンのCPU(LPC1114)をそのまま操作。
ULINK2エミュレータを直結して開発・デバッグを行います(ソフトはMbed)。
接続は僅か5本のラインだけでOK。
はじめに
mbedのインターフェース(USBでパソコンと接続するタイプ)を使わずに、CPUに直接エミュレータを接続して動作させます。
敢えてmbedのインターフェースを使わないことで、マイコンをゼロから動かす醍醐味を味わえます。
この記事では、素のCPUである LPC1114FN28/102 を使ってます(パソコンとUSB接続して開発を行うmbed LPC1114ではない)。
ただしこのCPUは、現在では販売終了しています。
代わりに、秋月の LPC1114FDH28 440円と、DIP変換基板 50円を利用してください。
これでブレッドボードで使えるDIP28ピンのCortex-M0マイコンと同等になります。
スイッチサイエンス社から、mbedのインターフェース付きの mbed LPC1114FN28 2200円を購入し、CPUだけ外して同じように使うこともできます。
CPUについて
NXP社のLPCシリーズで、CPUコアはARM社のCortex-M0。
電源電圧はMAX3.6Vなので気を付けてください。
・電源電圧min.:1.8V
・電源電圧max.:3.6V
・コア:Cortex-M0
・コアサイズ:32bit
・クロック:50MHz
・ROM:32kB
・プログラムメモリ[B]:32kB
・RAM:4kB
・GPIO:22
・ADコンバータ:6
・UART/USART:1
・I2C:1
・SPI:1
・タイマ:4
・オシレータ:内蔵/外付
データシートはこちら(英語)・・・要するに 50MHz ROM32K+RAM4K。
μVision+ULINK2+mbedプロジェクトの組み合わせで動作させる。
※dp23(RESET)をGPIOとして使う場合は、μVisionのデバッグ設定を少し変える(下図を参照)。
※dp24をPullDownするとISPモードに入ってしまうので要注意。
※DigitalOut宣言時のPullUp/Down指定は効かないので、10K程度の抵抗を外付けして対処する。
※dp5とdp27(I2Cのピン)はオープンドレインなので注意(GPIOとしては使わずI2C用に空けておけば便利)。
ハード
μVision+ULINK2でSWD接続して焼き込みとデバッグをする。
ULINK2のコネクタ配置は下図参照、CPUのPINは下図を参照。
Blinky用に青色の抵抗入りLEDをCPUの14PINに接続した。
ソフト
ソフトは当然mbedからExportしたのを使う。 1114の基礎解説
オンラインコンパイラのターゲットを1114にしておいてBlinkyプログラムを生成してからExportする。
μVisionはV4.73を使ってる(ISP書き込みなどをするならこちらのページが詳しい)。
V5.10だとLIBのパスが合わずリンクでエラーになる(これはスキャッターファイルの” *(InRoot$$Sections)”を修正すれば良いんだと思うけど、現時点ではV4.73を使ってる)。
mbedのExportがV5には完全対応してないようだから、mbed環境のプロジェクトではV4.73を使う方が手間無しで良いのかも。
オンラインコンパイラでターゲットを生成中。
ブレッドボード+電池駆動。
ソースはこれだけ・・・
#include "mbed.h"
DigitalOut myled(dp14);
int main() {
while(1) {
myled = 1;
wait(0.1);
myled = 0;
wait(0.1);
}
}
エミュレーターとの接続図
毎回SWDの配線をするのが面倒くさいんで、ULINK2との接続用コネクタをくっつけた。
手前はFN28、奥はQFP48+エクステンダ。
1114のRESETピン(dp23)をGPIOとして使う場合は、以下の部分を変更する(変更しないとデバッグ時のリセットが上手くかからない)。
I2Cのスレーブ
マスタ側のプログラムのデバッグ用にスレーブを作成。
ここではマスタとしてLPC1768mbedを使い、スレーブはLPC1114(mbedではないただのCPU)を7bitアドレスモードの 0x20<<1 で使ってる。
<I2Cバスの電圧レベル変換>
両方とも3.3Vで動いてるのでバス直結で構わないんだけど、マスタVCCを5Vにする予定があるんで秋月のPCA9306(150円)を間にかましてる。
こちらのページを参考にさせてもらいました。
<mbedAPI>
I2CのAPIはデフォルトのままで使用した。
例によって恐ろしいほど簡単。
しみじみとmbedの有り難みを実感…mbed最高
//1114スレーブ側のプログラム
#include "mbed.h"
#define SLVADRS (0x20<<1)
//I2CSlave slave(p9, p10); // 1768 SDA,SCL
I2CSlave slave(dp5, dp27); // 1114 SDA,SCL
DigitalOut led(LED1);
int main()
{
char buf[10];
char msg[] = "Slave!";
slave.address(SLVADRS);
while (1) {
int i = slave.receive();
switch (i) {
case I2CSlave::ReadAddressed:
slave.write(msg, strlen(msg) + 1); // Includes null char
break;
case I2CSlave::WriteGeneral:
slave.read(buf, 10);
printf("Read G: %s\n", buf);
break;
case I2CSlave::WriteAddressed:
slave.read(buf, 1);
//printf("Read A: %s\n", buf);
if (buf[0] == 0) led=0; // 0を受信したらLED OFF
else led=1; // それ以外ならLED ON
break;
}
for(int i = 0; i < 10; i++) buf[i] = 0; // Clear buffer
}
}
//1768マスタ側のプログラム
// スレーブに0x3-0x0を0.5秒ごとに送信する
#include "mbed.h"
I2C i2c(p9 , p10 );
const int addr = 0x20 << 1; // I2C address
int main() {
char cmd[2];
while (1) {
cmd[0] = 0x03;
i2c.write(addr, cmd, 1);
wait(0.5);
cmd[0] = 0x00;
i2c.write(addr, cmd, 1);
wait(0.5);
}
}
LAP-Cで確認中。
順調です。
コメント