Skip to content

ADC_Template

askn37 edited this page Sep 21, 2026 · 5 revisions

ADC 設定テンプレート

ADC を搭載した AVR には VDD 電圧や、MPUシリコン温度を測定する機能がある。しかし ADC の回路設計は MPU 毎に異なるため、同じ目的を果たすのでも 応用記述には互換性がないのが普通だ。本稿では できるだけ多くの品種での、設定例を考察する。

共通事項

ADC 変換の起動と完了

単発での測定開始には ADC*_COMMAND に直接開始コマンドを書くか、EVSYS の事象イベントを使う方法がある。一方で、測定完了を知るには ループ検査で調べるか、ADC*_RESRDY_vect 割込で受ける方法がある。

  • ADC*_RES または ADC*_RESULT を読むと、ADC*_INTFLAGS の ADC_RESRDY_bpビットは自動解除される。

初期化時間

データシートでは INITDLY 等と表記される。内部参照基準電圧を使用する場合、そのバンドギャップ出力が安定するまで待つのに必要。0 us から 40 us の自動的に挿入される初期化時間と、手動で設定する追加の初期化時間との合算からなる。

入力採取持続時間

データシートでは SAMPDUR あるいは SAMPDLY+SAMPLEN 等と表記される。入力されたアナログ電圧で内部コンデンサをチャージするための待ち時間。最小限必要な時間は回路のインピーダンス特性に依存する。

CLK_ADC 分周比換算

CLK_ADC は、0.5 us から 8.0 us の範囲になるよう、ADC0_CTRLB = ADC_PRESC_DIV*_gc で調整する。短すぎると自身の発生するノイズで採取値が擾乱され、長すぎると自己放電で採取値が低くあらわれる。以下は F_CPU(CLK_PER)に分周比 DIV* を掛けた us 粒度への換算表。これを見ると DIV12 か DIV16 で、2 MHz 〜 24 Mhz の周波数範囲をカバーできることがわかる。おおむね 1.0 us 〜 2.0 us になる分周比を選べば間違いはない。

F_CPU Mhz 2 4 6 8 10 12 16 20 24
DIV2 1.00 0.50 - - - - - - -
DIV4 2.00 1.00 0.50 - - - - - -
DIV6 3.00 1.50 1.00 0.75 0.60 0.50 - - -
DIV8 4.00 2.00 1.33 1.00 0.80 0.66 0.50 - -
DIV10 5.00 2.50 1.66 1.25 1.00 0.83 0.62 0.50 -
DIV12 6.00 3.00 2.00 1.50 1.20 1.00 0.75 0.60 0.50
DIV16 8.00 4.00 2.66 2.00 1.60 1.33 1.00 0.80 0.66
DIV20 - 5.00 3.33 2.50 2.00 1.66 1.25 1.00 0.83
DIV24 - 6.00 4.00 3.00 2.40 2.00 1.50 1.20 1.00
DIV28 - 7.00 4.66 3.50 2.80 2.33 1.75 1.40 1.16
DIV32 - 8.00 5.33 4.00 3.20 2.66 2.00 1.60 1.33
DIV40 - - 6.66 5.00 4.00 3.33 2.50 2.00 1.66
DIV48 - - 8.00 6.00 4.80 4.00 3.00 2.40 2.00
DIV56 - - - 7.00 5.60 4.66 3.50 2.80 2.33
DIV64 - - - 8.00 6.40 5.33 4.00 3.20 2.66
  • CLK_ADC は最短 x2 CLK_PER(=DIV2)であるため、1 MHz 動作では自ずと 0.5 us が最速となる。
  • tinyAVR-0/1/2、megaAVR-0 世代の CLK_ADC は、0.5 us から 5.0 us が有効範囲。
  • 必然的に ADC 動作可能範囲での F_CPU 最低周波数は 250 kHz(1 MHz の 4分周)となるので、OSC32K、OSC1K 主クロック動作は正常動作範囲外になる。

AVR_DU/SD Famiry

この系統は、10 bit 分解能で最大 170 ksps の変換速度を有する、シングルエンド変換機能を持っている。

  • この系統は CLKCTRL_MCLKTIMEBASE で CLK_ADC の時間基準を指定する。1〜31 us が指定でき、端数は切り上げすべき(0は不正)。これが ADC*_CTRLE で指定する SAMPDUR 起動遅延時間値の粒度になる。外部発振器 32 MHz 以上で動作させる場合は、TIMEBASE を半減し、ADC*_CTRLE の値を倍にする。
  • 必要に応じて自動挿入される初期化時間は ADC*_CTRLA に ADC_LOWLAT_bm ビットを立てると、次回以降の初期化時間を取り除くことができる。(いちど ON にした内部参照電圧を OFF にしない)

温度測定 - AVR_DU/SD

  • 採取結果からは "温度感知器校正値" を適用すると "ケルビン" が取得される。
  • 基準電圧は 2.048V を使用する。このため VDD は最低 2.6V 以上が必要。
  • 追加の初期化時間は 35 us 以上が必要。
  • 採取値は(符号付整数の)温度校正変位SIGROW_TEMPSENSE1から減算する。
/* Temperature Measurement for AVR_DU/SD Famiry */
void adc_setup_temperature (void) {
  CLKCTRL_MCLKTIMEBASE = F_CPU / 1e6;     /* CLK_ADC 基準 : us */
  ADC0_MUXPOS = ADC_MUXPOS_TEMPSENSE_gc;  /* 正入力選択 : 温度感知器 */
  ADC0_CTRLF = ADC_SAMPNUM_NONE_gc;       /* 累積変換なし */
  ADC0_CTRLE = 35;                        /* 追加の遅延 : 35 us */
  ADC0_CTRLC = ADC_REFSEL_2V048_gc;       /* 基準電圧 */
  ADC0_CTRLB = ADC_PRESC_DIV12_gc;        /* 分周比 */
  ADC0_CTRLA = ADC_ENABLE_bm;
}

float get_temperature (void) {
  ADC0_COMMAND = ADC_MODE_SINGLE_10BIT_gc | ADC_START_IMMEDIATE_gc;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RESULT;    /* 10 bit 採取値 */
  float _temp = ((float)((int)SIGROW_TEMPSENSE1)) - _res;
  _temp *= (int)SIGROW_TEMPSENSE0;
  _temp += 1024 / 2 - (273.15 * 1024);  /* 摂氏に補正 */
  _temp /= 1024;
  return _temp;
}

自己電圧測定 - AVR_DU/SD

  • VDD 電圧を測定するには、VDD/10 入力を 基準電圧 1.024V で測定する。このため VDD は最低 1.6V 以上が必要。
  • 追加の初期化時間は 40 usec 程度が必要。
  • CLK_ADC は 1.0 us 以上にする。
/* Self Voltage Measurement for AVR_DU/LA/SD Famiry */
void adc_setup_voltage (void) {
  CLKCTRL_MCLKTIMEBASE = F_CPU / 1e6;   /* CLK_ADC 基準 : us */
  ADC0_MUXPOS = ADC_MUXPOS_VDDDIV10_gc; /* 正入力選択 : VDD/10 */
  ADC0_CTRLF = ADC_SAMPNUM_NONE_gc;
  ADC0_CTRLE = 40;
  ADC0_CTRLC = ADC_REFSEL_1V024_gc;
  ADC0_CTRLB = ADC_PRESC_DIV24_gc;
  ADC0_CTRLA = ADC_ENABLE_bm;
}

float get_voltage (void) {
  ADC0_COMMAND = ADC_MODE_SINGLE_10BIT_gc | ADC_START_IMMEDIATE_gc;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RESULT;    /* 10 bit 採取値 */
  return map_double((double)_res, 0.0, 1023.0, 0.0, 10.23);
}

AVR_LA Famiry

この系統は、10 bit 分解能で最大 170 ksps の変換速度を有する、シングルエンド変換機能を持っている。

  • 仕様は AVR_DU/SD 系統と同じだが、温度測定の仕様が異なる。(自己電圧測定応用記述は共通)

温度測定 - AVR_LA

  • 採取結果からは "温度感知器校正値" を適用すると "ケルビン" が取得される。
  • 基準電圧は 1.024V を使用する。このため VDD は最低 1.6V 以上が必要。
  • 追加の初期化時間は 60 usec 以上が必要。
  • 採取値に 符号付整数の SIGROW_TEMPSENSE1 変位を加算し、符号付整数の SIGROW_TEMPSENSE0 傾斜値を掛けて "1024" で割る。
  • ・・・とデータシートには記述されているが、実機を用いた検証では、採取値を 4倍して(つまり 12 bit化して)変位を加算し、傾斜値を掛けて "4096" で割らないと正しい結果が得られない。
  • おそらく工場製造時の試験+SIGROW 書き込みを "12 bit ADC" で行ったことによる Errata ではないかと思われる。(AVR32LA32 REVID=B1)
/* Temperature Measurement for AVR_LA Famiry */
void adc_setup_temperature (void) {
  CLKCTRL_MCLKTIMEBASE = F_CPU / 1e6;     /* CLK_ADC 基準 : us */
  ADC0_MUXPOS = ADC_MUXPOS_TEMPSENSE_gc;  /* 正入力選択 : 温度感知器 */
  ADC0_CTRLF = ADC_SAMPNUM_NONE_gc;       /* 累積変換なし */
  ADC0_CTRLE = 60;                        /* 追加の遅延 : 60 us */
  ADC0_CTRLC = ADC_REFSEL_1V024_gc;       /* 基準電圧 */
  ADC0_CTRLB = ADC_PRESC_DIV24_gc;        /* 分周比 */
  ADC0_CTRLA = ADC_ENABLE_bm;
}

float get_temperature (void) {
  ADC0_COMMAND = ADC_MODE_SINGLE_10BIT_gc | ADC_START_IMMEDIATE_gc;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RESULT;    /* 10 bit 採取値 */
  float _temp = (float)((int)SIGROW_TEMPSENSE1) + (_res << 2);
  _temp *= (int)SIGROW_TEMPSENSE0;
  _temp += 4096 / 2 - (273.15 * 4096);  /* 摂氏に補正 */
  _temp /= 4096;
  return _temp;
}

自己電圧測定 - AVR_LA

AVR_DA/DB/DD Famiry

この系統は、12 bit 分解能で最大 130 ksps の変換速度を有する、差動およびシングルエンド変換機能を持っている。

  • つまり AVR_DU/LA/SD は後発なのに分解能は退化した格好。
  • バンドギャップ基準電圧は VREF 周辺機能から供給される。
  • AVR_DA 系統は ADC とは排他的に機能する PTC 周辺機能を持っている。その関係からか MUXPOS の選択肢が後発と異なる。

温度測定 - AVR_DA/DB/DD

  • 温度感知器からの採取は、シングルエンド変換を用いる。ADC0_MUXNEG は差動変換用なので参照されない。
  • 採取結果からは "温度感知器校正値" を適用すると "ケルビン" が取得される。
  • 基準電圧は 2.048V を使用する。このため VDD は最低 2.6V 以上が必要。
  • 追加の起動遅延時間 SAMPDUR は 25 us 以上が必要。
  • 採取持続時間 SAMPLEN は 28 us 以上が必要。
/* Temperature Measurement for AVR_DA/DB/DD Famiry */
void adc_setup_temperature (void) {
  VREF_ADC0REF = VREF_REFSEL_2V048_gc;      /* 基準電圧 2.048V */
  ADC0_MUXPOS = ADC_MUXPOS_TEMPSENSE_gc;    /* 正入力選択 : 温度感知器 */
  ADC0_CTRLD = ADC_INITDLY_DLY64_gc;        /* 25 us 以上になる分周比 */
  ADC0_CTRLC = ADC_PRESC_DIV12_gc;          /* CLK_ADC を決める分周比 */
  ADC0_SAMPCTRL = (F_CPU / 1e6 / 12) * 28;  /* 28 us 以上 */
  ADC0_CTRLA = ADC_ENABLE_bm
             | ADC_RESSEL_12BIT_gc
             | ADC_CONVMODE_SINGLEENDED_gc;
}

float get_temperature (void) {
  ADC0_COMMAND = ADC_STCONV_bm;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RES;   /* 12 bit 採取値 */
  float _temp = ((float)((int)SIGROW_TEMPSENSE1)) - _res;
  _temp *= (int)SIGROW_TEMPSENSE0;
  _temp += 4096 / 2 - (273.15 * 4096);  /* 摂氏に補正 */
  _temp /= 4096;
  return _temp;
}

自己電圧測定 - AVR_DB/DD

  • VDD 電圧を測定するには、VDD/10 入力を 基準電圧 1.024V で測定する。このため VDD は最低 1.6V 以上が必要。
/* Self Voltage Measurement for AVR_DB/DD Famiry */
void adc_setup_voltage (void) {
  VREF_ADC0REF = VREF_REFSEL_1V024_gc;
  ADC0_MUXPOS = ADC_MUXPOS_VDDDIV10_gc;
  ADC0_CTRLD = ADC_INITDLY_DLY64_gc;
  ADC0_CTRLC = ADC_PRESC_DIV12_gc;
  ADC0_SAMPCTRL = (F_CPU / 1e6 / 12) * 40;  /* 目安で 40 us */
  ADC0_CTRLA = ADC_ENABLE_bm
             | ADC_RESSEL_12BIT_gc
             | ADC_CONVMODE_SINGLEENDED_gc;
}

float get_voltage (void) {
  ADC0_COMMAND = ADC_STCONV_bm;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RES;   /* 12 bit 採取値 */
  return map_double((double)_res, 0.0, 4095.0, 0.0, 10.23);
}

自己電圧測定 - AVR_DA

  • この系統には ADC_MUXPOS_VDDDIV10_gc がないため、VREF から DAC0 を経由して VDD/10 を生成し、MUXPOS に与えなければならない。
/* Self Voltage Measurement for AVR_DA Famiry */
void adc_setup_voltage (void) {
  VREF_ADC0REF = VREF_REFSEL_1V024_gc;  /* 負入力選択 は 基準電圧 1.024V を参照 */
  VREF_DAC0REF = VREF_REFSEL_VDD_gc;    /* VREF から DAC0 に VDD を与える */
  DAC0_DATA = (1023U / 10) << 6;        /* DAC0 で VDD/10 を生成 */
  DAC0_CTRLA = DAC_ENABLE_bm;           /* DAC0 活性化 */
  ADC0_MUXPOS = ADC_MUXPOS_DAC0_gc;     /* 正入力選択 は DAC0 を参照 */
  ADC0_CTRLD = ADC_INITDLY_DLY64_gc;
  ADC0_CTRLC = ADC_PRESC_DIV12_gc;
  ADC0_SAMPCTRL = (F_CPU / 1e6 / 12) * 40;  /* 目安で 40 us */
  ADC0_CTRLA = ADC_ENABLE_bm
             | ADC_RESSEL_12BIT_gc
             | ADC_CONVMODE_SINGLEENDED_gc;
}

float get_voltage (void) {
  ADC0_COMMAND = ADC_STCONV_bm;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RES;  /* 12 bit 採取値 */
  return map_double((double)_res, 0.0, 4095.0, 0.0, 10.23);
}

AVR_EA/EB Famiry

この系統は、12 bit 分解能で最大 300 ksps の変換速度を有する、差動およびシングルエンド変換機能を持っている。

  • この系統には CLKCTRL_MCLKTIMEBASE がある。→ AVR_DU/LA/SD
  • この系統は利得増幅器(PGA: Programmable Gain Amplifier)を備えている。

温度測定 - AVR_EA/EB

  • 採取結果からは "温度感知器校正値" を適用すると "ケルビン" が取得される。
  • 基準電圧は 1.024V を使用する。このため VDD は最低 1.6V 以上が必要。
  • 追加の初期化時間は 32 usec 以上が必要。
/* Temperature Measurement for AVR_EA/EB Famiry */
void adc_setup_temperature (void) {
  CLKCTRL_MCLKTIMEBASE = F_CPU / 1e6;     /* CLK_ADC 基準 : us */
  ADC0_MUXPOS = ADC_MUXPOS_TEMPSENSE_gc;  /* 正入力選択 : 温度感知器 */
  ADC0_CTRLF = ADC_SAMPNUM_NONE_gc;
  ADC0_CTRLE = 32;                        /* 32 us */
  ADC0_CTRLC = ADC_REFSEL_1V024_gc;       /* 基準電圧 */
  ADC0_CTRLB = ADC_PRESC_DIV20_gc;
  ADC0_CTRLA = ADC_ENABLE_bm;
}

float get_temperature (void) {
  ADC0_COMMAND = ADC_MODE_SINGLE_12BIT_gc | ADC_START_IMMEDIATE_gc;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RESULT;            /* 12 bit 採取値 */
  float _temp = ((float)((int)SIGROW_TEMPSENSE1)) + _res;
  _temp *= (int)SIGROW_TEMPSENSE0;
  _temp += 4096 / 2 - (273.15 * 4096);    /* 摂氏に補正 */
  _temp /= 4096;
  return _temp;
}

自己電圧測定 - AVR_EA/EB

  • VDD 電圧を測定するには、VDD/10 入力を 基準電圧 1.024V で測定する。このため VDD は最低 1.6V 以上が必要。
/* Self Voltage Measurement for AVR_EA/EB Famiry */
void adc_setup_voltage (void) {
  CLKCTRL_MCLKTIMEBASE = F_CPU / 1e6;   /* CLK_ADC 基準 : us */
  ADC0_MUXPOS = ADC_MUXPOS_VDD10_gc;    /* 正入力は VDD/10 */
  ADC0_CTRLF = ADC_SAMPNUM_NONE_gc;
  ADC0_CTRLE = 60;                      /* 目安で 60 us */
  ADC0_CTRLC = ADC_REFSEL_1V024_gc;
  ADC0_CTRLB = ADC_PRESC_DIV20_gc;
  ADC0_CTRLA = ADC_ENABLE_bm;
}

float get_voltage (void) {
  ADC0_COMMAND = ADC_MODE_SINGLE_12BIT_gc | ADC_START_IMMEDIATE_gc;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);  /* 採取完了待ち */
  uint16_t _res = ADC0_RESULT;          /* 12 bit 採取値 */
  return map_double((double)_res, 0.0, 4095.0, 0.0, 10.23);
}

tinyAVR-2 Famiry

この系統は、12 bit 分解能で最大 375 ksps の変換速度を有する、差動およびシングルエンド変換機能を持っている。

  • この系統は利得増幅器(PGA: Programmable Gain Amplifier)を備えている。
  • この系統は VREF 周辺機能を持っているが、ADC はそちらを参照しない。
  • この系統の ADC0_RESULT は、32 bit 幅である。
  • CTRLC の 上位 5 bit で TIMEBASE を定義する。

温度測定 - tinyAVR-2

  • 採取結果からは "温度感知器校正値" を適用すると "ケルビン" が取得される。
  • 基準電圧は 1.1V を使用する。このため VDD は最低 1.6V 以上が必要。
  • 追加の初期化時間は 言及無し。
  • 採取持続時間は 32 usec 以上が必要。
  • SIGROW_TEMPSENSE0は符号無し整数、SIGROW_TEMPSENSE1は符号付整数。
  • 採取値は 12 bit 精度だが上記補正値を 2 bit 増しで評価するため、最後の除数は 1024 になる。
/* Temperature Measurement for tinyAVR-2 Famiry */
void adc_setup_temperature (void) {
  ADC0_MUXPOS = ADC_MUXPOS_TEMPSENSE_gc;
  ADC0_CTRLF = ADC_SAMPNUM_NONE_gc;
  ADC0_CTRLE = 20;
  ADC0_CTRLC = (((uint8_t)(F_CPU / 1e6)) << 3) | VREF_AC0REFSEL_1V024_gc;
  ADC0_CTRLB = ADC_PRESC_DIV40_gc;
  ADC0_CTRLA = ADC_ENABLE_bm;
}

float get_temperature (void) {
  ADC0_COMMAND = ADC_MODE_SINGLE_12BIT_gc | ADC_START_IMMEDIATE_gc;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = (uint16_t)ADC0_RESULT;
  float _temp = (float)_res - ((float)(((int8_t)SIGROW_TEMPSENSE1)));
  _temp *= (uint8_t)SIGROW_TEMPSENSE0;
  _temp += 1024 / 2 - (273.15 * 1024);  /* 摂氏に補正 */
  _temp /= 1024;
  return _temp;
}

自己電圧測定 - tinyAVR-2

/* Self Voltage Measurement for tinyAVR-2 Famiry */
void adc_setup_voltage (void) {
  ADC0_MUXPOS = ADC_MUXPOS_VDDDIV10_gc;
  ADC0_CTRLF = ADC_SAMPNUM_NONE_gc;
  ADC0_CTRLE = 40;  /* 目安 */
  ADC0_CTRLC = (((uint8_t)(F_CPU / 1e6)) << 3) | ADC_REFSEL_1024MV_gc;
  ADC0_CTRLB = ADC_PRESC_DIV40_gc;
  ADC0_CTRLA = ADC_ENABLE_bm;
}

float get_voltage (void) {
  ADC0_COMMAND = ADC_MODE_SINGLE_12BIT_gc | ADC_START_IMMEDIATE_gc;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = (uint16_t)ADC0_RESULT;
  return map_double((double)_res, 0.0, 4095.0, 0.0, 10.23);
}

tinyAVR-1 Famiry

この系統は、10 bit 分解能で最大 350 ksps の変換速度を有する、シングルエンド変換機能を持っている。

  • CLK_ADC は、0.5 us から 5.0 us の範囲でなければならない。
  • バンドギャップ基準電圧は VREF 周辺機能から供給される。
  • この系統は ADC とは排他的に機能する PTC 周辺機能を持っている。

温度測定 - tinyAVR-1

  • 採取結果からは "温度感知器校正値" を適用すると "ケルビン" が取得される。
  • 基準電圧は 1.1V を使用する。このため VDD は最低 1.6V 以上が必要。
  • 追加の初期化時間は 32 usec 以上が必要。
  • 採取持続時間は 32 usec 以上が必要。
  • SIGROW_TEMPSENSE0は符号無し整数、SIGROW_TEMPSENSE1は符号付整数。
  • 採取値は 10 bit だが上記補正値は 8-bit で評価するため、最後の除数は 256 になる。
/* Temperature Measurement for tinyAVR-1, megaAVR-0 Famiry */
void adc_setup_temperature (void) {
  VREF_CTRLA = VREF_ADC0REFSEL_1V1_gc;    /* バンドギャップ 1.1V */
  ADC0_MUXPOS = ADC_MUXPOS_TEMPSENSE_gc;  /* 正入力選択 : 温度感知器 */
  ADC0_CTRLD = ADC_INITDLY_DLY32_gc;
  ADC0_CTRLC = ADC_SAMPCAP_bm | ADC_REFSEL_INTREF_gc | ADC_PRESC_DIV32_gc;
  ADC0_CTRLB = ADC_SAMPNUM_ACC1_gc;
  ADC0_CTRLA = ADC_ENABLE_bm | ADC_RESSEL_10BIT_gc;
}

float get_temperature (void) {
  ADC0_COMMAND = ADC_STCONV_bm;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RES;
  float _temp = _res - ((float)((int8_t)SIGROW_TEMPSENSE1));
  _temp *= (uint8_t)SIGROW_TEMPSENSE0;
  _temp += 256 / 2 - (273.15 * 256);
  _temp /= 256;
  return _temp;
}

自己電圧測定 - tinyAVR-1

  • VDD 電圧を測定するには バンドギャップ入力電圧 1.1V を、VDD で測定する。このため VDD は最低 1.6V 以上が必要。
  • この系統ではMUXPOS側が固定電圧(バンドギャップ)、比較側が可変電圧になる点が他と異なる。(採取値の逆数を取る)
/* Self Voltage Measurement for tinyAVR-1 Famiry */
void adc_setup_voltage (void) {
  VREF_CTRLA = VREF_ADC0REFSEL_1V1_gc;  /* バンドギャップ 1.1V */
  ADC0_MUXPOS = ADC_MUXPOS_INTREF_gc;
  ADC0_CTRLD = ADC_INITDLY_DLY32_gc;
  ADC0_CTRLC = ADC_SAMPCAP_bm | ADC_REFSEL_VDDREF_gc | ADC_PRESC_DIV32_gc;
  ADC0_CTRLB = ADC_SAMPNUM_ACC1_gc;
  ADC0_CTRLA = ADC_ENABLE_bm | ADC_RESSEL_10BIT_gc;
}

float get_voltage (void) {
  ADC0_COMMAND = ADC_STCONV_bm;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RES;
  return map_double(1023.0 / (double)_res, 1.0, 2.0, 1.1, 2.2);
}

megaAVR-0 Famiry

この系統は、10 bit 分解能で最大 350 ksps の変換速度を有する、シングルエンド変換機能を持っている。 tinyAVR-1 とほとんど同じだが、MUXPOS や CTRLC に指定できる選択肢に違いがある。

温度測定 - megaAVR-0

自己電圧測定 - megaAVR-0

  • MUXPOS に直接 VDD/10 等を指定する手段がない。このため VREF から AC0_DACREF を経由し、AVDD/5 電圧を得て MUXPOS に供給する。
/* Self Voltage Measurement for megaAVR-0 Famiry */
void adc_setup_voltage (void) {
  VREF_CTRLA = VREF_AC0REFSEL_AVDD_gc | VREF_ADC0REFSEL_1V1_gc;
  AC0_DACREF = 255 / 5;  /* AVDD/5 */
  ADC0_MUXPOS = ADC_MUXPOS_DACREF_gc;
  ADC0_CTRLD = ADC_INITDLY_DLY32_gc;
  ADC0_CTRLC = ADC_SAMPCAP_bm | ADC_REFSEL_INTREF_gc | ADC_PRESC_DIV32_gc;
  ADC0_CTRLB = ADC_SAMPNUM_ACC1_gc;
  ADC0_CTRLA = ADC_ENABLE_bm | ADC_RESSEL_10BIT_gc;
}

float get_voltage (void) {
  ADC0_COMMAND = ADC_STCONV_bm;
  loop_until_bit_is_set(ADC0_INTFLAGS, ADC_RESRDY_bp);
  uint16_t _res = ADC0_RES;
  return map_double((double)_res, 0.0, 1023.0, 0.0, 5.5);
}

LINKS

multix.jp/てくにかるむ(休眠中)
Multix Zinnia Product SDK [*AVR]
AVR.JP(日本語訳)
AVR-LIBC(日本語訳)

Clone this wiki locally