lbed/11-LM4F120の実験
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[lbed]]
#contents
2013/11/02からのアクセス回数 &counter;
ここでは、LM4F120 LaunchPadを使っていろいろな実験をして、...
** シリアル通信の実験 [#n8e82a75]
LM4F120 LaunchPadには、2個のLM4F120が搭載されており、1つ...
もう一つがターゲットのLM4F120と豪勢な構成となっています。
このようにデバッグと通信に専用にCPUが割り当てられていると...
パソコンの通信ソフトに接続できるので、CDCのようにシリアル...
てしまうようなことがなく、とても自然に通信とデバッグがで...
&ref(LM4F120_LaunchPad2.png);
*** Serialクラスの実装 [#u2dd559a]
LM4F120 LaunchPadのStellarisWareライブラリとサンプルプロ...
実装することができます。
Serial.cppは次のようになっています。
#pre{{
#include "Serial.h"
#include "PinNames.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/gpio.h"
Serial::Serial()
: _tx(-1)
, _rx(-1)
{
setup(PA_1, PA_0, "default");
}
Serial::Serial(PinName tx, PinName rx, const char *name)
: _tx(-1)
, _rx(-1)
{
setup(tx, rx, name);
}
void Serial::setup(PinName tx, PinName rx, const char *na...
{
_tx = tx;
_rx = rx;
_available = false;
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_P...
}
void Serial::baud(unsigned int baudrate) {
unsigned long sysclock = SysCtlClockGet();
UARTConfigSetExpClk(UART0_BASE, sysclock, baudrate,
(UART_CONFIG_WLEN_8 | UART_CONFIG...
UART_CONFIG_PAR_NONE));
_available = true; ...
void Serial::begin(unsigned int baudrate) {
baud(baudrate);
}
int Serial::write(const char c) {
UARTCharPut(UART0_BASE, c);
return 1;
}
int Serial::read() {
return UARTCharGet(UART0_BASE);
}
int Serial::available() {
return _available ? 1 : 0;
}
}}
*** 動作確認 [#o4f0da11]
実際にSerialクラスを使ってシリアル通信を行ってみます。
テストプログラムは、以下の様になります。
#pre{{
#include"lbed.h"
DigitalOut myled(LEDG);
int main(void) {
Serial pc(PA_1, PA_0);
pc.baud(19200);
pc.println("Hello");
while (1) {
char c = pc.read();
pc.write(c + 1);
myled = !myled;
}
return 0;
}
}}
シリアル通信には、やはりArduinoのシリアルモニターを使いま...
これなら、どんなPCでも同じように使えるので、便利です。
最初にHelloと出力して入力を待ちます。
ここで、abcと入力すると一つ後の文字bcdを出力します。
&ref(Serial_out.png);
** スイッチ入力の実験 [#ie1da269]
DegialInのクラスを使ってSW1を押したときに、LEDBが点灯する...
ポイントは以下の2つです。
- SW1のモードをPullUpにセットする
((LM4F120 LaunchPadのユーザマニュアルのAppendix Aに出てい...
- スイッチを押すと0になるので、NOT !を使って1にする
プログラムは、とても簡単です。
#pre{{
#include "lbed.h"
int main(void) {
DigitalIn sw1(SW1);
sw1.mode(PullUp);
DigitalOut myled(LEDG);
while(1) {
myled = !sw1; // SW1を押すとLow=0になるので、...
wait_ms(200);
}
}
}}
*** 動作確認 [#w5835807]
デバッガを起動して、プログラムをLM4F120 LaunchPadに書き込...
ここで、もう一度Resumeを実行して、SW1を押したり、離したり...
&ref(SW_out.png);
** 温度を測る [#uf74ea5d]
I2Cインターフェースを持った温度センサーLM73B((エレキジャ...
LM73は、白の三角がついたところが、1番ピンで反時計回りにピ...
- 1: ADDR I2Cのslave addressを決めるpin: オープンで0x4Cに...
- 2: GND
- 3: VDD 3.3V(2.7~5.5Vに対応)
- 4: SCL(4.7KΩでプルアップ)
- 5: 未接続
- 6: SDA(4.7KΩでプルアップ)
となっています。SCL, SDAは、プルアップ抵抗が必要で、ここ...
LM4F120 LaunchPadの接続は、以下の4本を使用します。
- J1_1: 3.3V
- J3_2: GND
- J4_3: PB3(SDA)
- J2_2: PB2(SCL)
&ref(LM73_setting.png);
*** テストプログラム [#j327e69e]
テストプログラムTestLM73.cppは、以下の様になります。
((自作のprintfは、floatに対応していないので、少数点以下2...
どうもDegitalOutは、シリアルクラスの影響を受けるみたいで...
#pre{{
#include"lbed.h"
#include "LM73.h"
int main(void) {
LM73 lm73(PB_3, PB_2);
Serial pc(PA_1, PA_0);
pc.baud(19200);
// 注意)Serialの影響を受けるので、最後にLEDを生成した
DigitalOut myled(LEDG);
while (1) {
float t = lm73.read();
pc.printf("temp=%d.%02d\n", int(t), (int(t*100)...
myled = !myled;
wait_ms(1000);
}
}
}}
実際に動かしてシリアルモニターに出力させてみました。
&ref(LM73_out.png);
*** I2Cクラスの実装 [#c2ced26d]
StellarisWareライブラリで、I2Cを利用する例題はいくつか見...
LM4F120 LaunchPad特有のI2C初期設定が分からず、動作するま...
((GPIOPinTypeI2CSCLが他のMPUと異なります))
I2Cクラスは、以下の様に作成しました。
#pre{{
#include "platform.h"
#include "PinNames.h"
#include "I2C.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_i2c.h"
#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
I2C::I2C(PinName sda, PinName scl, const char *name) {
_name = (char *) name;
// The I2C0 peripheral must be enabled before use.
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
// For this example I2C0 is used with PortB[3:2].
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
// Select the I2C function for these pins.
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2); ...
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3); // ...
// Enable and initialize the I2C0 master module. Tru...
I2CMasterInitExpClk(I2C0_MASTER_BASE, SysCtlClockGet...
}
int I2C::read(int address, char *data, int length, bool r...
unsigned char addr = (unsigned char)address>>1;
I2CMasterSlaveAddrSet( I2C0_MASTER_BASE, addr, true)...
if (length == 1) {
I2CMasterControl( I2C0_MASTER_BASE, I2C_MASTER_C...
// Wait until done transmitting
while( I2CMasterBusy(I2C0_MASTER_BASE));
*data = I2CMasterDataGet(I2C0_MASTER_BASE);
}
else {
for (int i = 0; i < length; i++) {
if (i == 0)
I2CMasterControl( I2C0_MASTER_BASE, I2...
else if (i == length-1)
I2CMasterControl( I2C0_MASTER_BASE, I2...
else
I2CMasterControl( I2C0_MASTER_BASE, I2...
// Wait until done transmitting
while( I2CMasterBusy(I2C0_MASTER_BASE));
*data++ = I2CMasterDataGet(I2C0_MASTER_BASE);
}
}
return length;
}
int I2C::write(int address, const char *data, int length,...
unsigned char addr = (unsigned char)address>>1;
I2CMasterSlaveAddrSet( I2C0_MASTER_BASE, addr, false...
if (length == 1) {
I2CMasterDataPut( I2C0_MASTER_BASE, *data);
I2CMasterControl( I2C0_MASTER_BASE, I2C_MASTER_C...
// Wait until done transmitting
while( I2CMasterBusy(I2C0_MASTER_BASE));
}
else {
for (int i = 0; i < length; i++) {
I2CMasterDataPut( I2C0_MASTER_BASE, *data++);
if (i == 0)
I2CMasterControl( I2C0_MASTER_BASE, I2...
else if (i == length-1)
I2CMasterControl( I2C0_MASTER_BASE, I2...
else
I2CMasterControl( I2C0_MASTER_BASE, I2...
// Wait until done transmitting
while( I2CMasterBusy(I2C0_MASTER_BASE));
}
}
return length;
}
// これらの関数の使い方がよく分からないので、ダミー関数
int I2C::read(int ack) {
return -1;
}
int I2C::write(int ack) {
return -1;
}
}}
** 既存のmbedのライブラリの移植 [#n482170b]
これまで自分が作ってきたユーザライブラリを使っていました...
ライブラリをlbedに移植した場合の変更点と問題点を整理しま...
- C++のスタートアップルーチンが自前なので、C++内部で配列...
- ユーザクラスの中で、SerialやI2Cのメンバー変数を持つ場合...
- wait関数が使えない((doubleからfloatへの変換でハードフォ...
- mbed.hをlbed.hに変更する
*** I2cLCD.cppの移植 [#h5b132aa]
勝純一さんが公開されている[[I2cLCD>http://mbed.org/users/...
&ref(I2cLCD_setting.png);
wait関数の変更は、wait_msとwait_usを使って置き換えます。
#pre{{
wait_ms(1); wait_us(640); //wait(0.00164f); // This c...
}}
I2cLCD.hとI2cLCD.cppのメンバー変数の順序を以下の様に変更...
#pre{{
// DigitalOut, I2Cの順で宣言されているのをI2C, Digita...
// DigitalOut _rs;
// I2C _i2c;
I2C _i2c;
DigitalOut _rs;
}}
#pre{{
// _rs, _i2cの順に初期化しているのを_i2c, _rsに変更
// I2cLCD::I2cLCD(PinName sda, PinName scl, PinName rp) :...
I2cLCD::I2cLCD(PinName sda, PinName scl, PinName rp) : _...
}}
staticな配列icon_dataの初期化をauto変数に変更します。
#pre{{
static unsigned char icon_data[]=
{
0x00, 0x10,
途中省略
0x0F, 0x10,
};
}}
をputiconメンバ関数のなかで設定するように変更
((今回は使用している場所が一カ所だったので、このような変...
#pre{{
void I2cLCD::puticon(int flg)
{
unsigned char icon_data[] = {
0x00, 0x10,
途中省略
0x0F, 0x10,
};
}}
このように手順が分かれば、ある程度スムーズに移植できると...
((まだまだ、アドホックな実装ですが、使いにくいStellarisWa...
** アナログ入力の実験 [#o5ae9ca3]
アナログ入力は、StellarisWareのライブラリを使用するため、
[[StellarisLaunchPadWorkbook>http://software-dl.ti.com/tr...
を参考にAnalogInクラスを作成してみます。
LM4F120には、12bit 1MサンプリングのADCモジュール((ADC0, A...
LM4F120 LaunchPad UserManual Table 2-5によると、12個のア...
&ref(analog_pin_assign.png);
*** 電圧を測る [#s1dc99c0]
アナログ入力クラスAnalogInを使って可変抵抗の電圧を測って...
可変抵抗の両端を3.3VとGNDに接続し、真ん中のピンをJ3の9番...
&ref(analogin_setting.png);
テストプログラムTestAnalogIn.cppは、以下の様にします。
#pre{{
#include"lbed.h"
int main(void) {
Serial pc(PA_1, PA_0);
AnalogIn in(PE_3);
DigitalOut myled(LEDG);
pc.baud(19200);
pc.println("Hello");
while (1) {
unsigned short val = in.read_u16();
pc.printf("Sensor = %d\n", (int)val);
myled = !myled;
wait_ms(1000);
}
return 0;
}
}}
いつものようにArudino IDEのシリアルモニターを起動して実行...
1から4095の範囲の値が表示されます。
&ref(analogin_out.png);
*** AnalogInクラスの実装 [#c30b22da]
AnalogInのsetupをPE_3に対してのみ表すと以下の様になります。
#pre{{
void AnalogIn::setup(PinName pin, const char* name)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlADCSpeedSet(SAMPLE_SPS);
ADCSequenceDisable(ADC0_BASE, SEQUENCE_NUM);
if (pin >= PE_0 && pin <= PE_5) {
_gpio = GPIO_PORTE_BASE;
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
switch (pin) {
case PE_3:
_channel = ADC_CTL_CH0;
_pin = 3;
break;
// 他のピンも同様に設定
}
AnalogIn::_e_mask |= 1 << _pin;
// ピンタイプをADCにセット
GPIOPinTypeADC(_gpio, AnalogIn::_e_mask);
}
// PB, PDは省略
// ADC0をシーケンス3を割り込み不可にする
ADCSequenceDisable(ADC0_BASE, SEQUENCE_NUM);
// ADC0のシーケンスを最大優先にセット
ADCSequenceConfigure(ADC0_BASE, SEQUENCE_NUM, ADC_TR...
// 1ステップで1サンプリングにセット
ADCSequenceStepConfigure(ADC0_BASE, SEQUENCE_NUM, 0,...
// ADC0をシーケンス3を割り込み可能にする
ADCSequenceEnable(ADC0_BASE, SEQUENCE_NUM);
// ADC0をシーケンス3の割り込みフラグをクリア
ADCIntClear(ADC0_BASE, SEQUENCE_NUM);
}
}}
アナログ値の読み込みは、以下の様にしました。
#pre{{
unsigned short AnalogIn::read_u16()
{
if (_gpio) {
ADCIntClear(ADC0_BASE, SEQUENCE_NUM);
ADCProcessorTrigger(ADC0_BASE, SEQUENCE_NUM);
while(!ADCIntStatus(ADC0_BASE, SEQUENCE_NUM, fa...
}
ADCSequenceDataGet(ADC0_BASE, SEQUENCE_NUM, &_v...
return ((short)(_value&0x0FFF));
}
else
return 0;
}
}}
** LEDの明るさを変える [#x3519295]
LM4F120には、ドライバーで使われているPWMモジュールが付属...
((http://e2e.ti.com/support/microcontrollers/stellaris_ar...
ため、StellarisライブラリーのPWMは使えず、タイマー機能を...
PWMのピン割り当ては、以下の様になっています。
((一部のピンがカラーLEDとタイマーが同じため、同時にはPWM...
&ref(PWM_pin.png);
*** LEDとの接続 [#s3dd863c]
PWMピンの一つJ3_10(LEDRと兼用)をLEDのアノード(線の長い...
カソードをGND(J3_2)に接続します。
&ref(PWM_setting.png);
*** テストプログラム [#t98b0c3c]
動作を確認するテストプログラムは、PwmOutのインスタンスled...
#pre{{
#include "lbed.h"
int main(void) {
PwmOut led(LEDR);
led = 0.5;
while(1) {
led = led + 0.02;
if(led >= 1.0) {
led = 0.0;
}
wait_ms(80);
}
}
}}
*** PwmOutクラスの実装 [#f9772472]
PwmOutのsetupをLEDRに対してのみ表すと以下の様になります。
(( Stellarisのライブラリを使っているので、実装はいたって...
#pre{{
void PwmOut::setup(float period) {
_period = period;
unsigned long p = (uint32_t)(SystemCoreClock*_period);
// 16bitの範囲内で制御できるようにprescaleを変更する
if (p > (unsigned long)0xFFFF)
_scale = p/0x10000 + 1;
else
_scale = 1;
unsigned long matchTime = (unsigned long)((_period -...
switch (_pin) {
case LEDR: // T0CCP1
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinConfigure(GPIO_PF1_T0CCP1);
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
_base = TIMER0_BASE;
_timer = TIMER_B;
TimerConfigure(_base, TIMER_CFG_SPLIT_PAIR|TIME...
break;
// 他のピンは、省略
}
TimerPrescaleSet(_base, _timer, _scale -1); ...
TimerPrescaleMatchSet(_base, _timer, _scale -1);
TimerLoadSet(_base, _timer, p/_scale -1); /...
TimerMatchSet(_base, _timer, matchTime);
TimerEnable(_base, _timer);
}
}}
** PWMで音を出してみる [#z6ec77e1]
PWMを使ってArduinoのToneクラスを作ってみます。
*** 圧電スピーカとの接続 [#r54633ec]
圧電スピーカは、直接PWDの出力ピント接続します。
今回は、PB5をPWDの出力ピンに使用します。
LaunchPadとの接続は、J1_2(PB5)とJ3_2(GND)を圧電スピー...
&ref(Tone_setting.png);
*** 動かしてみる [#m165ba75]
テストプログラムTestTone.cppは、PCから入力された1から5に...
ド、レ、ミ、ソ、ラを出力します。
TestTone.cppは、以下の通りです。
#pre{{
#include "lbed.h"
#include "Tone.h"
int main(void) {
int tones[]={262,294,330,392,440}; // C, D, E, G, A
int toneDuration = 500;
Serial pc(PA_1, PA_0);
Tone tone(PB_5); // T1CCP1
DigitalOut myled(LEDR);
pc.baud(19200);
tone.noTone();
pc.println("Input number");
while (1) {
char c = pc.read();
myled = !myled;
if (c >= '1' && c <= '5') {
int index = c - '1';
tone.tone(tones[index], toneDuration);
}
}
return 0;
}
}}
*** Toneクラスの実装 [#e1bba43b]
Toneクラスは、PwmOutクラスを使ってとても簡単に作成できま...
Tone.cppは、以下の通りです。
#pre{{
#include "Tone.h"
#include "lbed.h"
Tone::Tone(PinName pin) : _out(pin)
{
}
void Tone::tone(unsigned int frequency)
{
float period = 1.0/frequency;
noTone();
_out.period(period);
_out.write(0.5);
}
void Tone::tone(unsigned int frequency, unsigned long dur...
{
noTone();
tone(frequency);
wait_ms(duration);
noTone();
}
void Tone::noTone(void)
{
_out.disable();
}
}}
** SPI通信 [#nc76ca7a]
[[SPIのテストプログラム>arm/LM4F120F LaunchPad SPI通信に...
が動作したので、SPIクラスを作りました。
| 機能 | レジスター | ピン番号 |h
| ssi0Rx | PA_4 | J2_8 |
| ssi0Tx | PA_5 | J1_8 |
| ssi0clk | PA_2 | J2_10 |
| ssi1Rx | PD_2 | J3_5 |
| ssi1Tx | PD_3 | J3_6 |
| ssi1clk | PD_0 | J3_3 |
| ssi2Rx | PB_6 | J2_7 |
| ssi2Tx | PB_7 | J2_6 |
| ssi2clk | PB_4 | J1_7 |
*** Arduinoとの接続 [#xdf0539b]
Arduinoとの接続は、SPIのテストプログラムと同じで以下の様...
LaunchPadのピンは、以下のピンを使用します。
- J3_6 (PD3) ssi1Tx (MOSIに相当)
- J3_5 (PD2) ssi1Rx (MISOに相当)
- J3_3 (PD0) ssi1Clk (SCKL)
- J3_2 (GND)
Arduinoのピンは、以下のピンを使用します。
- D11 (MOSI)
- D12 (MISO)
- D13 (CLK)
- GND
AdruinoとLaunchPadの結線は、以下の様になっています。
&ref(SPI_setting.png);
*** 動作確認用プログラム [#fd22a215]
SPIをクラスを使うと、Hello Worldのテストプログラムの以下...
#pre{{
#include "lbed.h"
int main(void) {
SPI spi(PD_3, PD_2, PD_0);
char *pcChars = "Hello World!\n";
char c;
while((c = *pcChars++)) {
spi.write(c);
}
}
}}
シリアルモニターに以下の様に出力されます。
&ref(TestSPI_out.png);
** OLEDに接続 [#b4cb05e2]
SPIの動作が確認できましたので、最大の目標であるMARMEX_OB...
今回使用するのは、
[[MARY-OB基板(OLED Board)>http://www.marutsu.co.jp/imag...
です。
今回も、mbedのサイトから
[[MARMEX_OB基板OLEDライブラリ (MARMEX_OB_oled)>http://mbe...
を使わせてもらいました。
*** MARY-OB基板(OLED Board)との接続 [#q2f4e2f3]
MARY-OB基板(OLED Board)のコネクターとピンの定義は以下の...
&ref(oled_connector.png);
LaunchPadとの接続は、以下のようにします。
- J3_2(GND)をCN1の1番に接続
- J3_1(5V)をCN1の2番に接続
- J1_1(3.3V)をCN1の3番に接続
- J2_6(PD_3 ssi1Tx)をCN4の4番(OLED_SDIN)に接続
- J2_3(PD_0 ssi1clk)をCN4の2番(OLED_SCLK)に接続
- J1_8をCN3の2番(OLED_CSN)に接続
- J1_9をCN3の1番(OLED_RESN)に接続
- J1_10をCN2の1番(OLED_VCC_ON)に接続
*** テストプログラム [#k80467b4]
テストプログラムTestOLED.cppは以下の様にします。
#pre{{
#include <math.h>
#include "lbed.h"
#include "MARMEX_OB_oled.h"
int main(void) {
MARMEX_OB_oled oled(PD_3, PD_0, J1_8, J1_9, J1_10); ...
oled.background( 0x000000 );
oled.cls();
int colorbar_width = MARMEX_OB_oled::WIDTH / 8;
for ( int i = 0; i < 8; i++ )
oled.fill( colorbar_width * i, 0, colorbar_width,...
((i & 0x4) ? 0xFF0000 : 0x000000) | ((i...
oled.fill( 50, 50, 64, 64, 0xCCCCCC );;
oled.locate(0, 3);
oled.print("Hello World!");
for (int i = 0; i < MARMEX_OB_oled::WIDTH; i++ ) {
oled.pixel( i, 80 + sinf( (float)i / 5.0 ) * 10,...
}
while(1) {
}
}
}}
*** 動作確認 [#kf397e6b]
無事動いて、MARY-OB基板(OLED Board)に以下の様に表示され...
&ref(OLED_out.png);
** キーパッドを使う [#f8f64615]
テンキーは入力デバイスとして便利です。そこでArduinoのKeyp...
ポイントは以下の2点です
- インタフェースは変えずに、ピン番号指定の処理をDegitalOu...
- pinMode, mille等のlbedにない、関数を追加する
*** キーパッドとの接続 [#xacc1730]
今回は、スイッチサイエンスの
[[3x4のマトリックス式ボタンパッド>http://www.switch-sc...
を使用しました。
マトリックス式ボタンパッドのコネクタは、左から1番とし、以...
| キーパッドのピン | LaunchPadのピン|
| 1:1行目 | J1_9 |
| 2:2行目 | J1_8 |
| 3:3行目 | J1_7 |
| 4:4行目 | J1_6 |
| 5:1列目 | J1_5 |
| 6:2列目 | J1_4 |
| 7:3列目 | J1_3 |
&ref(keypad_setting.png);
*** テストプログラムと動作確認 [#m951b06c]
テストプログラムは、以下の様になります。
#pre{{
#include "lbed.h"
#include "Keypad.h"
int main(void) {
const byte rows = 4; //four rows
const byte cols = 3; //three columns
char keys[rows][cols] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
byte rowPins[rows] = {J1_9, J1_8, J1_7, J1_6}; ...
byte colPins[cols] = {J1_5, J1_4, J1_3}; ...
Serial pc(PA_1, PA_0);
Keypad keypad = Keypad( makeKeymap(keys), rowPin...
pc.baud(19200);
pc.println("Input number");
wait_ms(500);
while (1) {
char c = keypad.getKey();
if (c)
pc.write(c);
}
}
}}
** Keypad移植のポイント [#sf375270]
Arduinoのライブラリをlbedに移植するときのポイントは、でき...
*** lbedに存在しない関数の追加 [#waeb9de9]
lbedに存在しない関数の内、
- pinMode: 入力・出力を切り替える
- mille: ミリ秒のカウントを返す
pinModeは、DigitalOut.hに以下の様に追加しました。
#pre{{
// Arduinoのライブラリコンバートのため、pinModeを追加
void pinMode(int mode) {
switch (mode) {
case Arduino_INPUT:
_gpio->DIR &= ~_mask;
DigitalIn::mode(PullNone);
break;
case Arduino_OUTPUT:
DigitalIn::mode(PullNone);
_gpio->DIR |= _mask;
break;
case Arduino_INPUT_PULLUP:
_gpio->DIR &= ~_mask;
DigitalIn::mode(PullUp);
break;
}
}
}}
*** Keypadの修正 [#a2c60f18]
Keypad内部で保持している行(rowPins)と列(columPins)をb...
((今回は4 x 4 の固定としました))
#pre{{
//byte *rowPins;
//byte *columnPins;
DigitalOut rowPins[4];
DigitalOut columnPins[4];
}}
そしてこれからが、今回の移植のメインイベントで、以下のdef...
#pre{{
#define pin_mode(pinNum, mode) (pinNum).pinMode(...
#define pin_write(pinNum, level) (pinNum) = level ? 1...
#define pin_read(pinNum) (pinNum)
#define bitWrite(b, c, bit) b = bit ? (b | ...
#define bitRead(b, c) ((b & (1<<c)) >>c)
}}
最後に、Keypadのコンストラクターでピン番号からDigitalOut...
#pre{{
// rowPins = row;
// columnPins = col;
for (int i = 0; i < numRows; i++) {
rowPins[i].setup(row[i], NULL);
}
for (int j = 0; j < numCols; j++) {
columnPins[j].setup(col[j], NULL);
}
}}
** 最新版のソース [#d00a002a]
Githubにlbedを登録しました。
- https://github.com/take-pwave/lbed
** コメント [#xddd351a]
#vote(おもしろかった,そうでもない,わかりずらい)
皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha
終了行:
[[lbed]]
#contents
2013/11/02からのアクセス回数 &counter;
ここでは、LM4F120 LaunchPadを使っていろいろな実験をして、...
** シリアル通信の実験 [#n8e82a75]
LM4F120 LaunchPadには、2個のLM4F120が搭載されており、1つ...
もう一つがターゲットのLM4F120と豪勢な構成となっています。
このようにデバッグと通信に専用にCPUが割り当てられていると...
パソコンの通信ソフトに接続できるので、CDCのようにシリアル...
てしまうようなことがなく、とても自然に通信とデバッグがで...
&ref(LM4F120_LaunchPad2.png);
*** Serialクラスの実装 [#u2dd559a]
LM4F120 LaunchPadのStellarisWareライブラリとサンプルプロ...
実装することができます。
Serial.cppは次のようになっています。
#pre{{
#include "Serial.h"
#include "PinNames.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/gpio.h"
Serial::Serial()
: _tx(-1)
, _rx(-1)
{
setup(PA_1, PA_0, "default");
}
Serial::Serial(PinName tx, PinName rx, const char *name)
: _tx(-1)
, _rx(-1)
{
setup(tx, rx, name);
}
void Serial::setup(PinName tx, PinName rx, const char *na...
{
_tx = tx;
_rx = rx;
_available = false;
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_P...
}
void Serial::baud(unsigned int baudrate) {
unsigned long sysclock = SysCtlClockGet();
UARTConfigSetExpClk(UART0_BASE, sysclock, baudrate,
(UART_CONFIG_WLEN_8 | UART_CONFIG...
UART_CONFIG_PAR_NONE));
_available = true; ...
void Serial::begin(unsigned int baudrate) {
baud(baudrate);
}
int Serial::write(const char c) {
UARTCharPut(UART0_BASE, c);
return 1;
}
int Serial::read() {
return UARTCharGet(UART0_BASE);
}
int Serial::available() {
return _available ? 1 : 0;
}
}}
*** 動作確認 [#o4f0da11]
実際にSerialクラスを使ってシリアル通信を行ってみます。
テストプログラムは、以下の様になります。
#pre{{
#include"lbed.h"
DigitalOut myled(LEDG);
int main(void) {
Serial pc(PA_1, PA_0);
pc.baud(19200);
pc.println("Hello");
while (1) {
char c = pc.read();
pc.write(c + 1);
myled = !myled;
}
return 0;
}
}}
シリアル通信には、やはりArduinoのシリアルモニターを使いま...
これなら、どんなPCでも同じように使えるので、便利です。
最初にHelloと出力して入力を待ちます。
ここで、abcと入力すると一つ後の文字bcdを出力します。
&ref(Serial_out.png);
** スイッチ入力の実験 [#ie1da269]
DegialInのクラスを使ってSW1を押したときに、LEDBが点灯する...
ポイントは以下の2つです。
- SW1のモードをPullUpにセットする
((LM4F120 LaunchPadのユーザマニュアルのAppendix Aに出てい...
- スイッチを押すと0になるので、NOT !を使って1にする
プログラムは、とても簡単です。
#pre{{
#include "lbed.h"
int main(void) {
DigitalIn sw1(SW1);
sw1.mode(PullUp);
DigitalOut myled(LEDG);
while(1) {
myled = !sw1; // SW1を押すとLow=0になるので、...
wait_ms(200);
}
}
}}
*** 動作確認 [#w5835807]
デバッガを起動して、プログラムをLM4F120 LaunchPadに書き込...
ここで、もう一度Resumeを実行して、SW1を押したり、離したり...
&ref(SW_out.png);
** 温度を測る [#uf74ea5d]
I2Cインターフェースを持った温度センサーLM73B((エレキジャ...
LM73は、白の三角がついたところが、1番ピンで反時計回りにピ...
- 1: ADDR I2Cのslave addressを決めるpin: オープンで0x4Cに...
- 2: GND
- 3: VDD 3.3V(2.7~5.5Vに対応)
- 4: SCL(4.7KΩでプルアップ)
- 5: 未接続
- 6: SDA(4.7KΩでプルアップ)
となっています。SCL, SDAは、プルアップ抵抗が必要で、ここ...
LM4F120 LaunchPadの接続は、以下の4本を使用します。
- J1_1: 3.3V
- J3_2: GND
- J4_3: PB3(SDA)
- J2_2: PB2(SCL)
&ref(LM73_setting.png);
*** テストプログラム [#j327e69e]
テストプログラムTestLM73.cppは、以下の様になります。
((自作のprintfは、floatに対応していないので、少数点以下2...
どうもDegitalOutは、シリアルクラスの影響を受けるみたいで...
#pre{{
#include"lbed.h"
#include "LM73.h"
int main(void) {
LM73 lm73(PB_3, PB_2);
Serial pc(PA_1, PA_0);
pc.baud(19200);
// 注意)Serialの影響を受けるので、最後にLEDを生成した
DigitalOut myled(LEDG);
while (1) {
float t = lm73.read();
pc.printf("temp=%d.%02d\n", int(t), (int(t*100)...
myled = !myled;
wait_ms(1000);
}
}
}}
実際に動かしてシリアルモニターに出力させてみました。
&ref(LM73_out.png);
*** I2Cクラスの実装 [#c2ced26d]
StellarisWareライブラリで、I2Cを利用する例題はいくつか見...
LM4F120 LaunchPad特有のI2C初期設定が分からず、動作するま...
((GPIOPinTypeI2CSCLが他のMPUと異なります))
I2Cクラスは、以下の様に作成しました。
#pre{{
#include "platform.h"
#include "PinNames.h"
#include "I2C.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_i2c.h"
#include "driverlib/i2c.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
I2C::I2C(PinName sda, PinName scl, const char *name) {
_name = (char *) name;
// The I2C0 peripheral must be enabled before use.
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
// For this example I2C0 is used with PortB[3:2].
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
// Select the I2C function for these pins.
GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2); ...
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3); // ...
// Enable and initialize the I2C0 master module. Tru...
I2CMasterInitExpClk(I2C0_MASTER_BASE, SysCtlClockGet...
}
int I2C::read(int address, char *data, int length, bool r...
unsigned char addr = (unsigned char)address>>1;
I2CMasterSlaveAddrSet( I2C0_MASTER_BASE, addr, true)...
if (length == 1) {
I2CMasterControl( I2C0_MASTER_BASE, I2C_MASTER_C...
// Wait until done transmitting
while( I2CMasterBusy(I2C0_MASTER_BASE));
*data = I2CMasterDataGet(I2C0_MASTER_BASE);
}
else {
for (int i = 0; i < length; i++) {
if (i == 0)
I2CMasterControl( I2C0_MASTER_BASE, I2...
else if (i == length-1)
I2CMasterControl( I2C0_MASTER_BASE, I2...
else
I2CMasterControl( I2C0_MASTER_BASE, I2...
// Wait until done transmitting
while( I2CMasterBusy(I2C0_MASTER_BASE));
*data++ = I2CMasterDataGet(I2C0_MASTER_BASE);
}
}
return length;
}
int I2C::write(int address, const char *data, int length,...
unsigned char addr = (unsigned char)address>>1;
I2CMasterSlaveAddrSet( I2C0_MASTER_BASE, addr, false...
if (length == 1) {
I2CMasterDataPut( I2C0_MASTER_BASE, *data);
I2CMasterControl( I2C0_MASTER_BASE, I2C_MASTER_C...
// Wait until done transmitting
while( I2CMasterBusy(I2C0_MASTER_BASE));
}
else {
for (int i = 0; i < length; i++) {
I2CMasterDataPut( I2C0_MASTER_BASE, *data++);
if (i == 0)
I2CMasterControl( I2C0_MASTER_BASE, I2...
else if (i == length-1)
I2CMasterControl( I2C0_MASTER_BASE, I2...
else
I2CMasterControl( I2C0_MASTER_BASE, I2...
// Wait until done transmitting
while( I2CMasterBusy(I2C0_MASTER_BASE));
}
}
return length;
}
// これらの関数の使い方がよく分からないので、ダミー関数
int I2C::read(int ack) {
return -1;
}
int I2C::write(int ack) {
return -1;
}
}}
** 既存のmbedのライブラリの移植 [#n482170b]
これまで自分が作ってきたユーザライブラリを使っていました...
ライブラリをlbedに移植した場合の変更点と問題点を整理しま...
- C++のスタートアップルーチンが自前なので、C++内部で配列...
- ユーザクラスの中で、SerialやI2Cのメンバー変数を持つ場合...
- wait関数が使えない((doubleからfloatへの変換でハードフォ...
- mbed.hをlbed.hに変更する
*** I2cLCD.cppの移植 [#h5b132aa]
勝純一さんが公開されている[[I2cLCD>http://mbed.org/users/...
&ref(I2cLCD_setting.png);
wait関数の変更は、wait_msとwait_usを使って置き換えます。
#pre{{
wait_ms(1); wait_us(640); //wait(0.00164f); // This c...
}}
I2cLCD.hとI2cLCD.cppのメンバー変数の順序を以下の様に変更...
#pre{{
// DigitalOut, I2Cの順で宣言されているのをI2C, Digita...
// DigitalOut _rs;
// I2C _i2c;
I2C _i2c;
DigitalOut _rs;
}}
#pre{{
// _rs, _i2cの順に初期化しているのを_i2c, _rsに変更
// I2cLCD::I2cLCD(PinName sda, PinName scl, PinName rp) :...
I2cLCD::I2cLCD(PinName sda, PinName scl, PinName rp) : _...
}}
staticな配列icon_dataの初期化をauto変数に変更します。
#pre{{
static unsigned char icon_data[]=
{
0x00, 0x10,
途中省略
0x0F, 0x10,
};
}}
をputiconメンバ関数のなかで設定するように変更
((今回は使用している場所が一カ所だったので、このような変...
#pre{{
void I2cLCD::puticon(int flg)
{
unsigned char icon_data[] = {
0x00, 0x10,
途中省略
0x0F, 0x10,
};
}}
このように手順が分かれば、ある程度スムーズに移植できると...
((まだまだ、アドホックな実装ですが、使いにくいStellarisWa...
** アナログ入力の実験 [#o5ae9ca3]
アナログ入力は、StellarisWareのライブラリを使用するため、
[[StellarisLaunchPadWorkbook>http://software-dl.ti.com/tr...
を参考にAnalogInクラスを作成してみます。
LM4F120には、12bit 1MサンプリングのADCモジュール((ADC0, A...
LM4F120 LaunchPad UserManual Table 2-5によると、12個のア...
&ref(analog_pin_assign.png);
*** 電圧を測る [#s1dc99c0]
アナログ入力クラスAnalogInを使って可変抵抗の電圧を測って...
可変抵抗の両端を3.3VとGNDに接続し、真ん中のピンをJ3の9番...
&ref(analogin_setting.png);
テストプログラムTestAnalogIn.cppは、以下の様にします。
#pre{{
#include"lbed.h"
int main(void) {
Serial pc(PA_1, PA_0);
AnalogIn in(PE_3);
DigitalOut myled(LEDG);
pc.baud(19200);
pc.println("Hello");
while (1) {
unsigned short val = in.read_u16();
pc.printf("Sensor = %d\n", (int)val);
myled = !myled;
wait_ms(1000);
}
return 0;
}
}}
いつものようにArudino IDEのシリアルモニターを起動して実行...
1から4095の範囲の値が表示されます。
&ref(analogin_out.png);
*** AnalogInクラスの実装 [#c30b22da]
AnalogInのsetupをPE_3に対してのみ表すと以下の様になります。
#pre{{
void AnalogIn::setup(PinName pin, const char* name)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlADCSpeedSet(SAMPLE_SPS);
ADCSequenceDisable(ADC0_BASE, SEQUENCE_NUM);
if (pin >= PE_0 && pin <= PE_5) {
_gpio = GPIO_PORTE_BASE;
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
switch (pin) {
case PE_3:
_channel = ADC_CTL_CH0;
_pin = 3;
break;
// 他のピンも同様に設定
}
AnalogIn::_e_mask |= 1 << _pin;
// ピンタイプをADCにセット
GPIOPinTypeADC(_gpio, AnalogIn::_e_mask);
}
// PB, PDは省略
// ADC0をシーケンス3を割り込み不可にする
ADCSequenceDisable(ADC0_BASE, SEQUENCE_NUM);
// ADC0のシーケンスを最大優先にセット
ADCSequenceConfigure(ADC0_BASE, SEQUENCE_NUM, ADC_TR...
// 1ステップで1サンプリングにセット
ADCSequenceStepConfigure(ADC0_BASE, SEQUENCE_NUM, 0,...
// ADC0をシーケンス3を割り込み可能にする
ADCSequenceEnable(ADC0_BASE, SEQUENCE_NUM);
// ADC0をシーケンス3の割り込みフラグをクリア
ADCIntClear(ADC0_BASE, SEQUENCE_NUM);
}
}}
アナログ値の読み込みは、以下の様にしました。
#pre{{
unsigned short AnalogIn::read_u16()
{
if (_gpio) {
ADCIntClear(ADC0_BASE, SEQUENCE_NUM);
ADCProcessorTrigger(ADC0_BASE, SEQUENCE_NUM);
while(!ADCIntStatus(ADC0_BASE, SEQUENCE_NUM, fa...
}
ADCSequenceDataGet(ADC0_BASE, SEQUENCE_NUM, &_v...
return ((short)(_value&0x0FFF));
}
else
return 0;
}
}}
** LEDの明るさを変える [#x3519295]
LM4F120には、ドライバーで使われているPWMモジュールが付属...
((http://e2e.ti.com/support/microcontrollers/stellaris_ar...
ため、StellarisライブラリーのPWMは使えず、タイマー機能を...
PWMのピン割り当ては、以下の様になっています。
((一部のピンがカラーLEDとタイマーが同じため、同時にはPWM...
&ref(PWM_pin.png);
*** LEDとの接続 [#s3dd863c]
PWMピンの一つJ3_10(LEDRと兼用)をLEDのアノード(線の長い...
カソードをGND(J3_2)に接続します。
&ref(PWM_setting.png);
*** テストプログラム [#t98b0c3c]
動作を確認するテストプログラムは、PwmOutのインスタンスled...
#pre{{
#include "lbed.h"
int main(void) {
PwmOut led(LEDR);
led = 0.5;
while(1) {
led = led + 0.02;
if(led >= 1.0) {
led = 0.0;
}
wait_ms(80);
}
}
}}
*** PwmOutクラスの実装 [#f9772472]
PwmOutのsetupをLEDRに対してのみ表すと以下の様になります。
(( Stellarisのライブラリを使っているので、実装はいたって...
#pre{{
void PwmOut::setup(float period) {
_period = period;
unsigned long p = (uint32_t)(SystemCoreClock*_period);
// 16bitの範囲内で制御できるようにprescaleを変更する
if (p > (unsigned long)0xFFFF)
_scale = p/0x10000 + 1;
else
_scale = 1;
unsigned long matchTime = (unsigned long)((_period -...
switch (_pin) {
case LEDR: // T0CCP1
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinConfigure(GPIO_PF1_T0CCP1);
GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
_base = TIMER0_BASE;
_timer = TIMER_B;
TimerConfigure(_base, TIMER_CFG_SPLIT_PAIR|TIME...
break;
// 他のピンは、省略
}
TimerPrescaleSet(_base, _timer, _scale -1); ...
TimerPrescaleMatchSet(_base, _timer, _scale -1);
TimerLoadSet(_base, _timer, p/_scale -1); /...
TimerMatchSet(_base, _timer, matchTime);
TimerEnable(_base, _timer);
}
}}
** PWMで音を出してみる [#z6ec77e1]
PWMを使ってArduinoのToneクラスを作ってみます。
*** 圧電スピーカとの接続 [#r54633ec]
圧電スピーカは、直接PWDの出力ピント接続します。
今回は、PB5をPWDの出力ピンに使用します。
LaunchPadとの接続は、J1_2(PB5)とJ3_2(GND)を圧電スピー...
&ref(Tone_setting.png);
*** 動かしてみる [#m165ba75]
テストプログラムTestTone.cppは、PCから入力された1から5に...
ド、レ、ミ、ソ、ラを出力します。
TestTone.cppは、以下の通りです。
#pre{{
#include "lbed.h"
#include "Tone.h"
int main(void) {
int tones[]={262,294,330,392,440}; // C, D, E, G, A
int toneDuration = 500;
Serial pc(PA_1, PA_0);
Tone tone(PB_5); // T1CCP1
DigitalOut myled(LEDR);
pc.baud(19200);
tone.noTone();
pc.println("Input number");
while (1) {
char c = pc.read();
myled = !myled;
if (c >= '1' && c <= '5') {
int index = c - '1';
tone.tone(tones[index], toneDuration);
}
}
return 0;
}
}}
*** Toneクラスの実装 [#e1bba43b]
Toneクラスは、PwmOutクラスを使ってとても簡単に作成できま...
Tone.cppは、以下の通りです。
#pre{{
#include "Tone.h"
#include "lbed.h"
Tone::Tone(PinName pin) : _out(pin)
{
}
void Tone::tone(unsigned int frequency)
{
float period = 1.0/frequency;
noTone();
_out.period(period);
_out.write(0.5);
}
void Tone::tone(unsigned int frequency, unsigned long dur...
{
noTone();
tone(frequency);
wait_ms(duration);
noTone();
}
void Tone::noTone(void)
{
_out.disable();
}
}}
** SPI通信 [#nc76ca7a]
[[SPIのテストプログラム>arm/LM4F120F LaunchPad SPI通信に...
が動作したので、SPIクラスを作りました。
| 機能 | レジスター | ピン番号 |h
| ssi0Rx | PA_4 | J2_8 |
| ssi0Tx | PA_5 | J1_8 |
| ssi0clk | PA_2 | J2_10 |
| ssi1Rx | PD_2 | J3_5 |
| ssi1Tx | PD_3 | J3_6 |
| ssi1clk | PD_0 | J3_3 |
| ssi2Rx | PB_6 | J2_7 |
| ssi2Tx | PB_7 | J2_6 |
| ssi2clk | PB_4 | J1_7 |
*** Arduinoとの接続 [#xdf0539b]
Arduinoとの接続は、SPIのテストプログラムと同じで以下の様...
LaunchPadのピンは、以下のピンを使用します。
- J3_6 (PD3) ssi1Tx (MOSIに相当)
- J3_5 (PD2) ssi1Rx (MISOに相当)
- J3_3 (PD0) ssi1Clk (SCKL)
- J3_2 (GND)
Arduinoのピンは、以下のピンを使用します。
- D11 (MOSI)
- D12 (MISO)
- D13 (CLK)
- GND
AdruinoとLaunchPadの結線は、以下の様になっています。
&ref(SPI_setting.png);
*** 動作確認用プログラム [#fd22a215]
SPIをクラスを使うと、Hello Worldのテストプログラムの以下...
#pre{{
#include "lbed.h"
int main(void) {
SPI spi(PD_3, PD_2, PD_0);
char *pcChars = "Hello World!\n";
char c;
while((c = *pcChars++)) {
spi.write(c);
}
}
}}
シリアルモニターに以下の様に出力されます。
&ref(TestSPI_out.png);
** OLEDに接続 [#b4cb05e2]
SPIの動作が確認できましたので、最大の目標であるMARMEX_OB...
今回使用するのは、
[[MARY-OB基板(OLED Board)>http://www.marutsu.co.jp/imag...
です。
今回も、mbedのサイトから
[[MARMEX_OB基板OLEDライブラリ (MARMEX_OB_oled)>http://mbe...
を使わせてもらいました。
*** MARY-OB基板(OLED Board)との接続 [#q2f4e2f3]
MARY-OB基板(OLED Board)のコネクターとピンの定義は以下の...
&ref(oled_connector.png);
LaunchPadとの接続は、以下のようにします。
- J3_2(GND)をCN1の1番に接続
- J3_1(5V)をCN1の2番に接続
- J1_1(3.3V)をCN1の3番に接続
- J2_6(PD_3 ssi1Tx)をCN4の4番(OLED_SDIN)に接続
- J2_3(PD_0 ssi1clk)をCN4の2番(OLED_SCLK)に接続
- J1_8をCN3の2番(OLED_CSN)に接続
- J1_9をCN3の1番(OLED_RESN)に接続
- J1_10をCN2の1番(OLED_VCC_ON)に接続
*** テストプログラム [#k80467b4]
テストプログラムTestOLED.cppは以下の様にします。
#pre{{
#include <math.h>
#include "lbed.h"
#include "MARMEX_OB_oled.h"
int main(void) {
MARMEX_OB_oled oled(PD_3, PD_0, J1_8, J1_9, J1_10); ...
oled.background( 0x000000 );
oled.cls();
int colorbar_width = MARMEX_OB_oled::WIDTH / 8;
for ( int i = 0; i < 8; i++ )
oled.fill( colorbar_width * i, 0, colorbar_width,...
((i & 0x4) ? 0xFF0000 : 0x000000) | ((i...
oled.fill( 50, 50, 64, 64, 0xCCCCCC );;
oled.locate(0, 3);
oled.print("Hello World!");
for (int i = 0; i < MARMEX_OB_oled::WIDTH; i++ ) {
oled.pixel( i, 80 + sinf( (float)i / 5.0 ) * 10,...
}
while(1) {
}
}
}}
*** 動作確認 [#kf397e6b]
無事動いて、MARY-OB基板(OLED Board)に以下の様に表示され...
&ref(OLED_out.png);
** キーパッドを使う [#f8f64615]
テンキーは入力デバイスとして便利です。そこでArduinoのKeyp...
ポイントは以下の2点です
- インタフェースは変えずに、ピン番号指定の処理をDegitalOu...
- pinMode, mille等のlbedにない、関数を追加する
*** キーパッドとの接続 [#xacc1730]
今回は、スイッチサイエンスの
[[3x4のマトリックス式ボタンパッド>http://www.switch-sc...
を使用しました。
マトリックス式ボタンパッドのコネクタは、左から1番とし、以...
| キーパッドのピン | LaunchPadのピン|
| 1:1行目 | J1_9 |
| 2:2行目 | J1_8 |
| 3:3行目 | J1_7 |
| 4:4行目 | J1_6 |
| 5:1列目 | J1_5 |
| 6:2列目 | J1_4 |
| 7:3列目 | J1_3 |
&ref(keypad_setting.png);
*** テストプログラムと動作確認 [#m951b06c]
テストプログラムは、以下の様になります。
#pre{{
#include "lbed.h"
#include "Keypad.h"
int main(void) {
const byte rows = 4; //four rows
const byte cols = 3; //three columns
char keys[rows][cols] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
byte rowPins[rows] = {J1_9, J1_8, J1_7, J1_6}; ...
byte colPins[cols] = {J1_5, J1_4, J1_3}; ...
Serial pc(PA_1, PA_0);
Keypad keypad = Keypad( makeKeymap(keys), rowPin...
pc.baud(19200);
pc.println("Input number");
wait_ms(500);
while (1) {
char c = keypad.getKey();
if (c)
pc.write(c);
}
}
}}
** Keypad移植のポイント [#sf375270]
Arduinoのライブラリをlbedに移植するときのポイントは、でき...
*** lbedに存在しない関数の追加 [#waeb9de9]
lbedに存在しない関数の内、
- pinMode: 入力・出力を切り替える
- mille: ミリ秒のカウントを返す
pinModeは、DigitalOut.hに以下の様に追加しました。
#pre{{
// Arduinoのライブラリコンバートのため、pinModeを追加
void pinMode(int mode) {
switch (mode) {
case Arduino_INPUT:
_gpio->DIR &= ~_mask;
DigitalIn::mode(PullNone);
break;
case Arduino_OUTPUT:
DigitalIn::mode(PullNone);
_gpio->DIR |= _mask;
break;
case Arduino_INPUT_PULLUP:
_gpio->DIR &= ~_mask;
DigitalIn::mode(PullUp);
break;
}
}
}}
*** Keypadの修正 [#a2c60f18]
Keypad内部で保持している行(rowPins)と列(columPins)をb...
((今回は4 x 4 の固定としました))
#pre{{
//byte *rowPins;
//byte *columnPins;
DigitalOut rowPins[4];
DigitalOut columnPins[4];
}}
そしてこれからが、今回の移植のメインイベントで、以下のdef...
#pre{{
#define pin_mode(pinNum, mode) (pinNum).pinMode(...
#define pin_write(pinNum, level) (pinNum) = level ? 1...
#define pin_read(pinNum) (pinNum)
#define bitWrite(b, c, bit) b = bit ? (b | ...
#define bitRead(b, c) ((b & (1<<c)) >>c)
}}
最後に、Keypadのコンストラクターでピン番号からDigitalOut...
#pre{{
// rowPins = row;
// columnPins = col;
for (int i = 0; i < numRows; i++) {
rowPins[i].setup(row[i], NULL);
}
for (int j = 0; j < numCols; j++) {
columnPins[j].setup(col[j], NULL);
}
}}
** 最新版のソース [#d00a002a]
Githubにlbedを登録しました。
- https://github.com/take-pwave/lbed
** コメント [#xddd351a]
#vote(おもしろかった,そうでもない,わかりずらい)
皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha
ページ名:
SmartDoc