続いてアナログ関連のペリフェラル設定をしていきましょう。
ADC
制御器としてマイコンを使う上で必須の機能です。このマイコンの型番は GD32VF103 ですが、STM32F103 と似たような機能です。STM32F303 を使っている人はコンバート開始の方法に戸惑うかも。
取り敢えずコードです。1つのチャネルを変換するという動作の実装です。 adc_init
ではチャネル0を想定して初期化をしてしまいました。
void adc_init(void) {
rcu_periph_clock_enable(RCU_GPIOA);
gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
RCU_CFG0 |= (0b10 << 14) | (1 << 28); // ADC clock = 108MHz / 8 = 13.5MHz(14MHz max.)
rcu_periph_clock_enable(RCU_ADC0);
ADC_CTL1(ADC0) |= ADC_CTL1_ADCON;
}
uint16_t get_adc(int ch) {
ADC_RSQ2(ADC0) = 0;
ADC_RSQ2(ADC0) = ch;
ADC_CTL1(ADC0) |= ADC_CTL1_ADCON;
while( !(ADC_STAT(ADC0) & ADC_STAT_EOC) );
uint16_t ret = ADC_RDATA(ADC0) & 0xFFFF;
ADC_STAT(ADC0) &= ~ADC_STAT_EOC;
return ret;
}
STM32F303 では ADSTART
というビットがレジスタに用意されているのですが、F103 ではADON
を立てて ADC 自体を有効化した状態で、チャネルを設定した後に更にもう一度 ADON
に対して1を代入しなければならないという仕様です。このマイコンは後者の仕様を受け継いでいるため、初期化と A/D 値を get するのに両方の操作が必要になるということに注意です。
DAC
実はメチャクチャ簡単。DAC です。
GPIO の CTLx
レジスタを見ると「アナログの出力設定が無いじゃないか」と思われるかも知れませんが、実は DAC を有効化すると、指定したチャネルのピンが自動的にアナログ出力になるという、昔の 8bit マイコンを彷彿とさせる仕様なのです。これは STM32F303 と共通の仕様です。
void dac_init(void) {
rcu_periph_clock_enable(RCU_DAC);
rcu_periph_clock_enable(RCU_GPIOA);
// No need for pin setting because the function is automatically enabled when DACx is enabled.
DAC_CTL = DAC_CTL_DEN0;
}
void dac_write(int i) {
DAC0_R12DH = i;
}
ちなみにこうするとLEDボヤァができます。でもまあLEDの電圧-電流特性が線形ではないので少し微妙ですがね。
while(1) {
for(int i = 0; i < (1 << 12); i++) {
dac_write(i++);
}
}