ARM学習基板の実験に必要なクラス †ARM学習基板の実験に必要なクラスについて、ページを分けて説明することにします。 DigitalInクラス †汎用入力クラスがまだ出来ていませんが、ほとんどDigitalOutクラスと同じなので DigitalOutをDigitalInのサブクラスにすることにします。 まずは、mbedのDigitalInのAPIを以下のURLで調べます。 DigitalOut.cppをコピーして作りました。 クラス定義のDigitalIn.cppは、ほとんどDigitalOut.cppと同じです。 #include "platform.h" #include "PinNames.h" #include "AnalogIn.h" #define ADC_CLK 4400000 /* set to 4.4Mhz */ AnalogIn::AnalogIn() : _channel(-1) { } AnalogIn::AnalogIn(PinName pin, const char* name) : _channel(-1) { setup(pin, name); } void AnalogIn::setup(PinName pin, const char* name) { DigitalIn::setup(pin, name); /* Disable Power down bit to the ADC block. */ LPC_SYSCON->PDRUNCFG &= ~(0x1<<4); /* Enable AHB clock to the ADC. */ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<13); switch(pin) { case P0_11: _channel = 0; break; case P1_0: _channel = 1; break; case P1_1: _channel = 2; break; case P1_2: _channel = 3; break; case P1_3: _channel = 4; break; case P1_4: _channel = 5; break; case P1_10: _channel = 6; break; case P1_11: _channel = 7; break; } if (_channel >= 0) { *_io &= ~0x8F; /* ADC I/O config */ if (_channel < 5) *_io |= 0x02; /* ADC IN0~IN4 */ else *_io |= 0x01; /* ADC IN5~IN7 */ LPC_ADC->CR = ( 0x01 << 0 ) | /* SEL=1,select channel 0~7 on ADC0 */ ( ( SystemCoreClock / ADC_CLK - 1 ) << 8 ) | /* CLKDIV = Fpclk / 1000000 - 1 */ ( 0 << 16 ) | /* BURST = 0, no BURST, software controlled */ ( 0 << 17 ) | /* CLKS = 0, 11 clocks/10 bits */ ( 0 << 24 ) | /* START = 0 A/D conversion stops */ ( 0 << 27 ); /* EDGE = 0 (CAP/MAT singal falling,trigger A/D conversion) */ } } float AnalogIn::read() { return (float)read_u16()/(float)(0xFFFF); } unsigned short AnalogIn::read_u16() { if (_channel >= 0) { unsigned int dat; LPC_ADC->CR = 0x01000f00 | (1 << _channel); do { dat = LPC_ADC->GDR; } while (!(dat & 0x80000000)); return ((dat >> 6) &0x3ff); } else return 0; } 何かたくさんの定義をしたように思えるかも知れませんが、これによってDigitalOut.cppはとても簡単になります。 #include "platform.h" #include "PinNames.h" #include "DigitalOut.h" #include "DigitalIn.h" DigitalOut::DigitalOut() { } DigitalOut::DigitalOut(PinName pin, const char* name) { setup(pin, name); } void DigitalOut::setup(PinName pin, const char* name) { DigitalIn::setup(pin, name); if (_gpio) { _gpio->DIR |= _mask; } } SerialCDCクラス †LPC1343は、USBのCDCクラスをサポートしているので、Serialクラスを拡張して CDC対応のSerialCDCを作成しました。 ARMパーエフェクト学習基板の例題USBADCの例題のソースを使わせてもらいました。 SerialCDCのソース †SerialCDCのソースは、以下の様にしました。 #include "SerialCDC.h" #include "PinNames.h" #include "LPC13xx.h" #include "_usb.h" #include "_cdc_usbcfg.h" #include "_usbhw.h" #include "_usbcore.h" #include "_cdc.h" #include "_cdcuser.h" SerialCDC::SerialCDC() : _tx(-1) , _rx(-1) { setup(USBTX, USBRX, "default"); } SerialCDC::SerialCDC(PinName tx, PinName rx, const char *name) : _tx(-1) , _rx(-1) { setup(tx, rx, name); } void SerialCDC::setup(PinName tx, PinName rx, const char *name) { _tx = tx; _rx = rx; _available = false; USBIOClkConfig(); CDC_Init (); // CDC Initialization USB_Init(); // USB Initialization USB_Connect(1); // USB Connect while (!USB_Configuration) continue; // wait until USB is configured } int SerialCDC::write(const char c) { unsigned int i; unsigned char cbuf; cbuf = c; while(!CDC_DepInEmpty) ; USB_WriteEP (CDC_DEP_IN, (unsigned char *)&cbuf, 1); for (i=0; i<10000; i++) { if (!CDC_DepInEmpty) break; } return (1); } int SerialCDC::read() { int numAvailByte = 0; char c; CheckSerialState(); do { CDC_OutBufAvailChar (&numAvailByte); if (numAvailByte > 0) { int numBytesToRead = 1; int numBytesRead = CDC_RdOutBuf (&c, &numBytesToRead); } } while (numAvailByte <= 0); return (c); } void SerialCDC::CheckSerialState (void) { unsigned short temp = CDC_GetSerialState(); if (_serialState != temp) { _serialState = temp; CDC_NotificationIn(); // send SERIAL_STATE notification } } なぞの現象 †最初、どうしてもUSBとして認識してくれないので、とても悩みまして、 例題のUSB関連のソースをMAINのソースと同じ場所に置いたところ、 うまく認識できるようになりました。 試行錯誤の結果、USBADCの例題のusbhw.cがアーカイブからのリンクでは 上手く動作しないことがわかり、暫定処置としてForSerialCDC_usbhw.cとして LBED_LPC13xx_MAINのsrcに置くことにしました。 *1 コメント †Tweet |