<V.3版>
1ch 1ADC変換
(→プロジェクトファイル(Harmony Ver.3版 MHC v3.6.0) ダウンロード)
PIC32MXのAD変換モジュールと比較すると分解能が10ビットから12ビットに変わっただけでなく、ADCモジュールの構成が大きく変わりました。一言で云うと PIC32MXは1つの共通ADCを入力チャンネルを切り替えてつかっていましが、PIC32MZでは5個の専用ADCと1つの共通ADCという構成になりました。 これら合計6個のADCはサンプル時間、変換時間がお互いに独立なので複数の入力を並列に処理できることから高速処理が可能となっています。(→ PIC32MZのADC構成 ) ここでは基本となる シングルエンドの1チャンネルAD変換の例を紹介します。 2チャンネル並列高速処理の例は 2ch 2ADC同時変換を 参照願います。 |
<仕様>
・アナログ入力ポートから 0 ~ 3.3v(Vdd)のアナログ電圧を入力する。
・アナログ入力ポートは、AN4(RB4)とし入力方式はシングルエンドとする。
・入力電圧読み込み値を以下の要領でキャラクタ液晶に表示する。
1行目: 入力アナログ電圧のADC変換整数値
2行目: 上記整数値を電圧に換算して表示する。
・AD変換は250msec毎にタイマ割り込みを行い、これを液晶に表示する。
・タイマはスタティクタイマを使用する。
・割り込み動作確認用として、250msec毎にLEDのON/OFFを行う。
・起動後、液晶に以下を表示する。
1行目: "From Now"
2行目: "AD Start !!"
<回路図> (→ PDFファイル)
<外観> PIC32MZ評価ボード(→購入方法)を使った実験品の外観です。
汎用モジュール評価ボード(段積みボード)には本テーマと関係ない部品が多々実装されています。また、グラフィック液晶は
本テーマと関係ないのではずしています。
<動作結果> (→ 動画) (備考:1080pのHD動画を見ることができます。)
起動直後 | アナログ入力電圧(AN4/RB4) 1行目: ADCの変換整数値 2行目: 電圧換算表示 |
||
約 0.01v | 約 1.00v | 約 3.26v | |
<解説>(以下に、記載してある内容は要点だけです。 詳細はプロジェクトファイルを精読願います)
★プロジェクトをコンパイルして、コンパイラエラー "error: unknown type name 'uintptr_t'"が出た場合( → URL)
■ MHC設定
■ キャラクタ液晶表示のライブラリ 1lcd_lib_XC32.h と 1lcd_lib_XC32.cを main.cと同じフォルダにコピーして、プロジェクトに追加します。
(詳細→ キャラクタ液晶表示方法 参照)
■ main.cに、青字部分を追加します。
① 1lcd_lib_XC32.hのインクルード、及び変数の定義、宣言をします。
#include "stdio.h"
#include "1lcd_lib_XC32.h"
bool LED = 0;
……
……
② NOPを利用した μsec、msecの遅延関数 delay_us( )、delay_ms( )を定義します。
void delay_us(volatile unsigned int usec) //1μsec遅延
{
volatile int count;
……
……
③ AdcFunc( ) で 入力のAD変換を行い、液晶に表示します。
1. ADCHS_ChannelConversionStart() でグローバルソフトウェアエッジトリガをかけAD変換を開始します。
何故か引数がないとコンパイルエラーがでてしまいます。 バグ?
2. while(!ADCHS_ChannelResultIsReady(ADCHS_CH4));でAD変換の終了を待ちます。
3. AdcValue = ADCHS_ChannelResultGet(ADCHS_CH4);で 結果を取り出します。
void AdcFunc(void) //AD変換、表示
{
unsigned int AdcValue;
……
……
④ タイマ9のコールバック関数です。 10msec毎に呼び出されます。 25回呼び出されれると(250msec毎に)
フラグTimer_Triggreのフラグをたてて AD変換を実行しています。
void TMR9_Callback_Fn(uint32_t status, uintptr_t context) //コールバック関数 //1秒毎に呼び出される
{
Count_10msec++;
if(Count_10msec >= 25) //250msec 経過
{
Count_10msec = 0;
Timer_Trigger = true;
}
}
⑤ レジスタ直接設定の例です。 この部分を使えばMHCのAD変換ドライバー部分の設定をしなくとも所要の結果が得られます。
/*
//レジスタ直接設定の場合
// Configure ADCCON1
ADCCON1 = 0; // No ADCCON1 features are enabled including: Stop-in-Idle,
turbo,
ADCCON1bits.STRGSRC = 1; //スキャン開始を グローバルソフトウェアエッジトリガに設定 //ADCCON1bits.STRGSRC
= 0; でも可
……
……
*/
⑥ AD変換出力のフォーマットを unsigned shortに設定しています。
//★出力フォーマット: unsigned data format
ADCIMCON1bits.SIGN4 = 0; //出力フォーマット: unsigned short int // unsigned
data format
⑦ 起動時の液晶表示部分です。
lcd_init(); // LCD初期化
lcd_cmd(0b00001100); // カーソル:OFF ブリンク:OFF
lcd_cmd(0x80); //1目の先頭へ
……
……
⑧ インターバルタイマのタイマ9のインターバル時間 及びコールバック関数の設定と有効化です。
TMR9_PeriodSet(3907); //50 nsec x2 x 3907 x 256 = 1000192μsec = 10.00192msec
//クロック:100MHz
TMR9_Start(); //タイマ1 スタート
//T1CONbits.ON = 1; //レジスタ直接制御
TMR9_CallbackRegister(TMR9_Callback_Fn, NULL); //コールバック関数設定
//void TMR1_CallbackRegister(TMR_CALLBACK callback_fn, uintptr_t context);
⑨ ここに若干の遅れがないと Timer_Triggerが while ( true )内でグローバル関数として認識されません。
Harmony V2.04ではこのようなことはありませんでした。
delay_us(1); //必須
⑩ AD変換のタイミングのフラグTimer_Triggerが立った場合の処理を記述します。
すなわち、250msec毎にAD変換を行い、キャラクタ液晶に表示します。
if(Timer_Trigger == 1) //AD変換、表示のタイミング
{
AdcFunc(); //AD変換、表示
Timer_Trigger = 0;
……
……
以下、main.c