0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EFM8開発 - A/D変換

0
Last updated at Posted at 2025-09-15

目次

1. 初めに
2. A/D設定
3. A/D処理
4. Generate Source、Build Project 注意点
5. ビルド・実行
6. 終わりに

1. 初めに

今回のテーマはA/D変換です。Exampleの EFM8BB3 ADC Lib Polled プロジェクトを教材としていろいろやって行きます。このプロジェクトのインストール方法はEFM8開発 - Simplicity Studioを使ってみる - Example編EFM8BB3 Blinkey と同様で、プロジェクトの選択で EFM8BB3 ADC Lib Polled を選択します。
1-1_EFM8BB3_ADC_Lib_Polled.png
プロジェクトを作成し終えるとこの画面になります。
1-2_プロジェクト作成完了.png

2. A/D設定

Hardware Configurator を用いてA/D変換に関わる設定を確認します。
EFM8B3_ADC_Lib_Polled.hwconf を右クリックし、 Open を選択します。
2-1_ハードウェア構成ファイルオープン.png

DefaultMode Port I/O をクリックしてポート設定画面を表示します。
2-2_ポート設定.png

18/P1.7 をクリックします。
2-3_P1_7選択.png

ポートP1.7のプロパティを表示します。
2-4_プロパティ.png

Property Value 備考
IOMode Analog I/O アナログポートとして使用する
Skip Skipped クロスバー でのアサイン対象から除外する

Port I/O をクリックします。
2-5_PortIO選択.png

Port I/Oのプロパティを表示します。
2-6_PortIOプロパティ.png

Property Value 備考
Enable Crossbar Enabled クロスバー 動作を許可する

先のポートP1.7のプロパティ「クロスバー でのアサイン対象から外す」、Port I/Oのプロパティ「クロスバー 機能を許可する」とは、マイコンの機能としてのクロスバー動作は許可するけれど、ポートP1.7はそのアサイン対象から除外 ポートP.7はクロスバー 動作とは無関係、ということです。

ここで クロスバー という言葉が登場しましたが、これは、ペリフェラル入出力のピンアサインをユーザが設定できる機能です。これについては今後別の記事で説明する予定です。
尚、Enable Crossbar が Disabled 設定の場合、ポート出力動作が禁止となります。なので、クロスバー機能を使わない場合でも Enable Crossbar 設定は Enabled とします。

DefaultMode Peripherals をクリックします。ペリフェラル設定画面を表示します。更に ADC0 をクリックします。
2-7_ペリフェラル設定_ADC0選択.png

ADC0のプロパティ設定値を表示します。
2-8_ADC0設定.png

主なものは

Property Value 備考
Enable ADC Enabled A/Dコンバータを有効にする
Start of Conversion Write to 1 of ADBUSY A/D変換開始モード:ADBUSYビットへ1を書き込むとA/D変換を開始する
Resolution 12-Bit mode A/D分解能:12bit
Positive Input Selection ADC0.13(P1.7) A/D入力チャンネル ADC0.13を設定する(Pin名:P1.7)
Select Voltage Reference Internal VREF A/D基準電圧:内部基準電圧
Reference Voltage 1.65 A/D基準電圧が1.65Vであることを表している
Gain Control 0.5x gain ゲイン設定0.5倍モード
Full Scale Voltage 3.300 フルスケール入力電圧が3.3Vであることを表している (1.65 / 0.5)
Select ADC Clock SYSCLK ADCクロックはシステムクロックを使用する

Clock Control をクリックします。
2-9_ペリフェラル設定_ClockControl選択.png

Clock Controlのプロパティ設定値を表示します。
2-10_ClockControl設定.png

Property Value 備考
SYSCLK 24.500 MHz システムクロックが24.5MHzであることを表している
Select Clock Source Internal High Frequency Oscillator 0 システムクロックは内部オシレータHFOSC0を設定する
Clock Source Divider SYSCLK / 1 クロック分周設定は1:1

3. A/D処理

A/D処理はコードの中でどのようになっているのか main()から見て行きます。

src/EFM8BB3_ADC_Lib_Polled.c
void main (void)
{
  uint16_t mV;
  uint8_t joystickDir;
  enter_DefaultMode_from_RESET();

  DISP_EN = DISP_BC_DRIVEN;           // Display not driven by EFM8

  while (1)
  {
    //Start conversion
    ADC0_startConversion();

    // Wait for conversion to complete
    while (!ADC0_isConversionComplete());

    // Convert sample to mV
    mV = ADC0_convertSampleToMillivolts(ADC0_getResult());

    // Get joystick direction from ADC sample
    joystickDir = JOYSTICK_convert_mv_to_direction(mV);

    // Convert joystick direction to LED color
    ConvertDirectionToColor(joystickDir);

  }
}

enter_DefaultMode_from_RESET();
A/D変換、マイコンポート、その他初期設定を行います。

ADC0_startConversion();
A/D変換を開始します。

while (!ADC0_isConversionComplete());
A/D変換が終わるのを待ちます。

mV = ADC0_convertSampleToMillivolts(ADC0_getResult());
ADC0_getResult() でA/D値を取得し、その値を電圧値(単位mV)へ換算します。

ADC0_convertSampleToMillivolts() のソースコードです。

src/EFM8BB3_ADC_Lib_Polled.c
//-----------------------------------------------------------------------------
// ADC0_convertSampleToMillivolts
//-----------------------------------------------------------------------------
//
// Converts a raw ADC sample to millivolts.
// sample - the raw sample from the ADC
//
// returns - a two byte number representing the adc sample in millivolts
//  e.g. 1.65V would equal 1650.
//
uint16_t ADC0_convertSampleToMillivolts(uint16_t sample)
{
  // The measured voltage applied to P1.7 is given by:
  //
  //                           Vref (mV)
  //   measurement (mV) =   --------------- * result (bits)
  //                       (2^12)-1 (bits)
  return ((uint32_t)sample * VREF_MV) / ADC_MAX_RESULT;
}

定数定義は

EFM8BB3_ADC_Lib_Polled.c
#define VREF_MV         (3300UL)
#define ADC_MAX_RESULT  ((1 << 12)-1) // 12 bit ADC

A/D値から電圧値への換算はコメント部分に記述してある通りですね。
VREF_MV は 3300、ADC_MAX_RESULT は 2^12-1 = 4095 を定義していますので、A/D値から電圧値を換算する計算式は

電圧値(mV) = \frac{3300}{4095}\times(A/D値)

となります。

マイコン基板写真赤枠がジョイスティックです。
3-1_マイコン基板s.jpg

ジョイスティック周辺の回路です(実際の回路図を一部省略しています)。
3-2_Joystick回路図.png

ジョイスティックは上下左右と中立状態で押下の5つのスイッチから成っています。スイッチON毎に異なる電圧値となるように各スイッチに抵抗器を接続しています。

スイッチ Vad(mV) Vad 計算式
Left 1980 3300 * 15 / (10 + 15)
Down 1650 3300 * 10 / (10 + 10)
Right 2533 3300 * 33 / (10 + 33)
Up 2831 3300 * 60.4 / (10 + 60.4)
Center 33 3300 * 0.1 / (10 + 0.1)
Left + Down 33 15kと10kの合成抵抗 (15*10)/(15+10)=6
3300 * 6 / (10 + 6)
Right + Down 1433 33kと10kの合成抵抗 (33*10)/(33+10)=7.67
3300 * 7.67 / (10 + 7.67)
Left + Up 1801 15kと60.4kの合成抵抗 (15*60.4)/(15+60.4)=12.01
3300 * 12.01 / (10 + 12.01)
Right + Up 2247 33kと60.4kの合成抵抗 (33*60.4)/(33+60.4)=21.34
3300 * 21.34 / (10 + 21.34)

joystickDir = JOYSTICK_convert_mv_to_direction(mV);
電圧値からジョイスティックの位置を計算します。
JOYSTICK_convert_mv_to_direction() のソースコードです。関連する箇所を抜粋します。

lib/bsp/efm8_joystick/joystick.c
uint8_t JOYSTICK_convert_mv_to_direction(uint32_t mV)
{
    uint8_t joystickDirection;

    // determine which direction pad was pressed
    if ((mV <= JOYSTICK_MV_C + JOYSTICK_MV_ERROR))
    {
      joystickDirection = JOYSTICK_C;
    }
    else if ((mV >= JOYSTICK_MV_N - JOYSTICK_MV_ERROR) && \
             (mV <= JOYSTICK_MV_N + JOYSTICK_MV_ERROR))
    {
      joystickDirection = JOYSTICK_N;
    }
    else if ((mV >= JOYSTICK_MV_E - JOYSTICK_MV_ERROR) && \
             (mV <= JOYSTICK_MV_E + JOYSTICK_MV_ERROR))
    {
      joystickDirection = JOYSTICK_E;
    }
    else if ((mV >= JOYSTICK_MV_S - JOYSTICK_MV_ERROR) && \
             (mV <= JOYSTICK_MV_S + JOYSTICK_MV_ERROR))
    {
      joystickDirection = JOYSTICK_S;
    }
    else if ((mV >= JOYSTICK_MV_W - JOYSTICK_MV_ERROR) && \
             (mV <= JOYSTICK_MV_W + JOYSTICK_MV_ERROR))
    {
      joystickDirection = JOYSTICK_W;
    }
    else
    {
      joystickDirection = JOYSTICK_NONE;
    }

    return joystickDirection;
}

定数定義は

lib/bsp/efm8_joystick/joystick.h
#define JOYSTICK_NONE          0       ///< not pressed
#define JOYSTICK_C             1       ///< center
#define JOYSTICK_N             2       ///< north
#define JOYSTICK_E             3       ///< east
#define JOYSTICK_S             4       ///< south
#define JOYSTICK_W             5       ///< west

#define JOYSTICK_MV_C          3       ///< center position in mV
#define JOYSTICK_MV_N          2831    ///< north position in mV
#define JOYSTICK_MV_E          2533    ///< east position in mV
#define JOYSTICK_MV_S          1650    ///< south position in mV
#define JOYSTICK_MV_W          1980    ///< west position in mV

#define JOYSTICK_MV_ERROR      150     ///< tolerance in mV for cardinal

コード内では方向を

  • north : Up
  • west : Left
  • south : Down
  • east : Right

で表しています。各方向別に電圧上下範囲を設定しており、電圧値がその範囲に納まった場合方向が決まる仕組みです。例えば mV=2831 の場合、この分岐に至ることとなります。

    else if ((mV >= JOYSTICK_MV_N - JOYSTICK_MV_ERROR) && \
             (mV <= JOYSTICK_MV_N + JOYSTICK_MV_ERROR))
    {
      joystickDirection = JOYSTICK_N;
    }

ConvertDirectionToColor(joystickDir);
ジョイスティックの位置に対応した色でLEDを点灯します。
ConvertDirectionToColor() のソースコードです。

src/EFM8BB3_ADC_Lib_Polled.c
//-----------------------------------------------------------------------------
// ConvertDirectionToColor
//-----------------------------------------------------------------------------
//
// Turns on LEDs depending on the joystick direction given
//
// dir -  JOYSTICK_N = White
//        JOYSTICK_E = Red
//        JOYSTICK_S = Green
//        JOYSTICK_W = Blue
//        Any other direction = Off
//
void ConvertDirectionToColor(uint8_t dir)
{
  GREEN_LED = LED_OFF;
  BLUE_LED  = LED_OFF;
  RED_LED   = LED_OFF;

  switch (dir)
  {
  case JOYSTICK_N:
    GREEN_LED = LED_ON;
    BLUE_LED  = LED_ON;
    RED_LED   = LED_ON;
    break;

  case JOYSTICK_E:
    RED_LED   = LED_ON;
    break;

  case JOYSTICK_S:
    GREEN_LED = LED_ON;
    break;

  case JOYSTICK_W:
    BLUE_LED  = LED_ON;
    break;

  default:
    break;
  }
}

LED出力に関する定義です。

src/EFM8BB3_ADC_Lib_Polled.c
SI_SBIT(GREEN_LED, SFR_P1, 4);        // Green LED
SI_SBIT(BLUE_LED, SFR_P1, 5);         // Blue LED
SI_SBIT(RED_LED, SFR_P1, 6);          // Red LED

#define LED_ON  (0)
#define LED_OFF (1)

LED周辺の回路です。
3-3_マイコン基板LED回路.png
Green、Blue、Redを同時ONでWhite(白)点灯となります。

4. Generate Source、Build Project 注意点

Generate Sourceを実行、その後ビルドすると・・・ 4-1_Generate Source.png

4-2_Build Project.png

ビルドに失敗します。
4-3_Build Failed.png

Consoleのメッセージを見ると、 'ADC0CF1_ADLPM__LP_ENABLED'は未定義の識別子 と表示しています。
C:\Users\burni\SimplicityStudio\v5_workspace\EFM8BB3_ADC_Lib_Polled\src\InitDevice.c: 'ADC0CF1_ADLPM__LP_ENABLED': undefined identifier

そこで、エラーが発生している IntDevide.c を開いてエラー発生箇所を見ます。
4-4_IntDevice_cエラー箇所.png

ADC0CF1_ADLPM__LP_ENABLEDをプロジェクト内で定義してないのにこの行で使用しています。この行は Generate Source時に生成するので、どうやら Hardware Configurator 不具合の様な気がします(断言はしませんが)。
とりあえず対応策を示します。公式発表されているものではないです。
#define ADC0CF1_ADLPM__LP_ENABLED 0InitDevice.c へ追加します。

src/InitDevice.c
//=========================================================
// src/InitDevice.c: generated by Hardware Configurator
//
// This file will be regenerated when saving a document.
// leave the sections inside the "$[...]" comment tags alone
// or they will be overwritten!
//=========================================================

// USER INCLUDES
#include <SI_EFM8BB3_Register_Enums.h>
#include "InitDevice.h"

// USER PROTOTYPES
// USER FUNCTIONS
+ #define ADC0CF1_ADLPM__LP_ENABLED 0    //定義を追加

// $[Library Includes]
// [Library Includes]$

ビルドを行うと正常完了します。
4-5_Build Pass.png

尚、この現象は他のA/D変換を用いているExample ADC_Lib_Interrupt でも発生しました。
4-6_ADC_Lib_Interruptビルド.png

5. ビルド・実行

以前の記事
5. プロジェクトのビルド
6. 実行(デバッグ)
と同様です。

実行時の様子は
Up
LED-W_UpBs.jpg

Left
LED-B_LeftBs.jpg

Down
LED-G_DownBs.jpg

Right
LED-R_RightBs.jpg

6. 終わりに

マイコン基板に合ったExampleが多数用意されており、他のハードウェアを用意せずともマイコン学習をすぐに始められるのは助かります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?