前回、Longan NanoのDACを動かすと、電圧は出力されるけれども、ディスプレイが消えてしまいました。今回そこをFIXして、ちゃんと電圧出力とディスプレイが両立できたので投稿しておきます。Longan Nano、多機能ではあるのですが、比較的小ピンのマイコン利用なので、端子機能のアサインには注意しないとなりません。
※「鳥なき里のマイコン屋」投稿順Indexはこちら
前回、データシートや回路図もよく見ずに「似た」評価ボード用のExampleを流用して動作させてみたのが、「DACを動かすと、ディスプレイが消えちゃうよ」の原因でした。DAC1の出力端子がディスプレイの制御端子の一つでもあったからです。そこで今回は「DACあたりだけ」ちゃんと資料を確認し、DACの電圧出力とディスプレイが両立するようにいたしました。
Sipeed社、Longan Nanoボードは、GigaDevice Semiconductor社のGD32VF103というマイコンを搭載しています。最低確認すべき資料は以下の3つかと思われます。
-
- GD32VF103 User Manual、GigaDevice Semiconductor Inc.
- Sipeed Longan Nano Datasheet
- Longan nano schematic
このボード、お値段の割には実に多機能です。
-
- RISC-V搭載のフラッシュマイコン
- USB(OTG)コネクタ搭載、PC接続でプログラムダウンロード可能
- 160×80 サイズのカラーLCD(ボード上面コネクタ、マイコンに両面テープで固定!)
- TFカード(microSD)スロット、ボード裏面
- 複数CHのUSART, I2C, SPI, I2S, CANインタフェース搭載
- 2Mサンプル、12ビットADコンバータ2(10ch), 12ビットDAコンバータ2
- 各種TIMER, DMA, RTC, CRC計算器など搭載
- 赤青緑、三色LEDも搭載
- JTAGデバッグ対応
ボードのお値段からGigaDevice社がいくらでマイコンを卸しているのか想像するに、恐ろしいことです。とても国内のマイコンメーカーは太刀打ちできないのではないかと。しかし、これだけの機能を小さなボードに詰め込んでいるだけあって、かなり無理もしています。
上記のGD32VF103のUser ManualのDACの項を読んでから、Longan nanoの回路図を見て、まず、疑問。
マニュアルにはVREF+という端子が書いてあったよね~、無いな~。
アナログ電源のVDDA、VSSAは一応ちゃんとある(デジタルの電源とは「フィルタ」を介しています)ものの、DAC基準電圧を与える筈のVREF+は見当たりません。でもマニュアル探したら書いてありました。1行引用させていただきましょう。
The VREF+ pin is only available on no less than 100-pin packages,
つまり、GD32VF103というマイコンには、パッケージのバラエティがあり、100ピンより小さいパッケージのバージョンではVREF+端子は内部でVDDAに接続してあるからね、ヨロシク、という感じかと。
Longan nanoに乗っているGD32VF103は48ピン版
であります。もともと100ピン以上でフル機能であるらしいGD32VF103からするとかなりバッサリとピンアサインをしていることが想像できます。
マイコンとしてもかなりバッサリな48ピン端子のうち、上記のオンボード機能
-
- LCDに5端子
- TFカードに4端子
- 3色LEDに3端子
- JTAGに4端子
が割り当てられています。自由に使える端子としてはかなり少なくなります。それでもよく考えられてアサインはされている感じです。
-
- DAC0は使用可能(DAC1は不可)、確認済
- ADCは多分端子3ch使用可能(未確認)
- UART、I2C、CANなどは最低1chは使用可能(未確認)
- SPIはTFカードを使わないことにすれば使用可能(未確認)
と思えます。ま、当初のアナログコンピュータ(モドキ)用のアナログ乗算器(モドキ)を作るという目標にはなんとかOKかと。
一応、DAC0で電圧出力しながら、ディスプレイとLEDを操作する前回プログラムのアップデート版も示しておきます。まずは、ピン類の初期化、
void initializePeriph(void) { // initialize display Lcd_Init(); LCD_Clear(BLACK); BACK_COLOR = BLACK; // Enable Peripheral clock rcu_periph_clock_enable(RCU_GPIOC); rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_DAC); // initialize GPIO // PC13 ... LED_RED // PA1 ... LED_GREEN // PA2 ... LED_BLUE // PA4 ... DAC0 // PA5 ... DAC1 <== DO NOT USE gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1 | GPIO_PIN_2); gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_4); gpio_bit_reset(GPIOC, GPIO_PIN_13); gpio_bit_reset(GPIOA, GPIO_PIN_1 | GPIO_PIN_2); }
そしてDAC0の初期化
void dac_config(uint16_t dat) { dac_deinit(); /* configure the DAC0 */ dac_trigger_disable(DAC0); dac_wave_mode_config(DAC0, DAC_WAVE_DISABLE); dac_output_buffer_enable(DAC0); dac_enable(DAC0); dac_data_set(DAC0, DAC_ALIGN_12B_R, dat); }
3秒毎に、LEDの色を変えつつ、ディスプレイに表示色を報告し、かつDAC0に約0.20Vずつ異なる電圧を出力していくメインプログラムはこちら。動いているところはアイキャッチ画像のとおり(左側に醜いお手製コネクタつながっていますが今は忘れてくだされ)
int main( void ) { uint16_t dacData = DAC_OUT_VAL0; initializePeriph(); dac_config(dacData); LCD_ShowString( 0, 0, "LED & DAC demo", WHITE); while(1) { // RED LCD_ShowString( 0, 15, "RED ", WHITE); contLED(LED_RED, (LED_GREEN | LED_BLUE)); dacData = nextDacData(dacData); dac_data_set(DAC0, DAC_ALIGN_12B_R, dacData); delay_1ms(3000); // GREEN LCD_ShowString( 0, 15, "GREEN", WHITE); contLED(LED_GREEN, (LED_RED | LED_BLUE)); dacData = nextDacData(dacData); dac_data_set(DAC0, DAC_ALIGN_12B_R, dacData); delay_1ms(3000); // BLUE LCD_ShowString( 0, 15, "BLUE ", WHITE); contLED(LED_BLUE, (LED_RED | LED_GREEN)); dacData = nextDacData(dacData); dac_data_set(DAC0, DAC_ALIGN_12B_R, dacData); delay_1ms(3000); } }
LCD_ナンチャラ()系の関数は、皆 lcd.h内で定義されているもの。delay_1msはsystick.hです。contLEDは特に掲げませんが、3色LEDの点灯と消灯を1行に書くためだけの自作関数、nextDacDataはDAC出力を3.3V / 16段階=大体0.20Vで変化させるための出力値を計算するもの。
動作させ、DAC0の出力端子の電圧をハンディマルチメータで観察しました。下のような感じ。上限は3.3V、下限は0.0V付近までちゃんとふれているように見えます。
とりあえずDAは動いた。次はどのペリフェラルを動かしてみるかい?