概要
dsPIC33CHシリーズにはAD(Analog to Digital)コンバータがマスターコアに1ch、スレーブコアに3ch搭載されており、スレーブの2chは専用入力構成となっております。本章ではマスターコア側のADコンバータを使用してポテンションの値をソフトウェアで平均化しLEDの点灯、消灯LEDを点灯させるサンプルについて説明しています。
ADコンバータとは
外部のアナログ信号をマイコンのソフトで扱えるようにデジタル信号に変換する機能です。
ハードウェア構成と制御ブロック
ハードウェアの構成として(fig.1)の青丸位置に実装されているポテンションのアナログ電圧をAN0チャンネルを介し、デジタル信号に変換します。この時にソフトウェアでサンプリングとコンバートの指令を行い、8回の移動平均の結果値が1.65V以上の場合LEDを点灯させる様にします。


レジスタ
ADモジュールのレジスタは非常に豊富で90程度有りますので、今回の記事に関連する部分だけを紹介します。
| ADレジスタ名 | 機能 | 説明 |
| ADCON1L | CADC Control Register 1 Low | 本モジュールを有効にするためのビットと、アイドル 中の本モジュールの動作を定義 |
| ADCON1H | ADC Control Register 1 High | 出力データのフォーマットと共有ADC コアの分解能 を制御 |
| ADCON2L | ADC Control Register 2 Low | 共有ADC コアのクロック分周比と早期割り込みタイ ミングなどを制御 |
| ADCON2H | ADC Control Register 2 High | 共有ADC コアのサンプリング時間などを制御 |
| ADCON3L | ADC Control Register 3 Low | 入力キャプチャおよび出力コンペア動作を制御し、 補助出力の動作を設定 |
| ADCON3H | ADC Control Register 3 High | 全てのADC コアを有効にするためのビット、モジュー ルのクロック源を選択 |
| ADCON4L | ADC Control Register 4 Low | 専用ADC コアのトリガから変換開始までの遅延有 効化と、トリガの同期有効化を制御 |
| ADCON4H | ADC Control Register 4 High | 専用ADC コアのチャンネルを選択 |
| ADCON5L | ADC Control Register 5 Low | 全てのADC コアの電源を制御 |
| ADCON5H | ADC Control Register 5 High | ADCコアが電源投入後に動作準備を完了した時に 生成する共通割り込みを制御 |
| ADSTATL | ADC Data Ready Status Register Low | AD変換完了フラグ |
| ADCBUFx (x=0~21) | ADC Buffer x Register | AD変換格納レジスタ |
ソースコード
まずはメインループ外で各種初期設定を行います。
メインループ内では以下の4つのフェーズを繰り返し行います。
①サンプリングフェーズ
- ADCON3Lbits.CNVRTCHがクリアされるまで待ちます。
- ADCON3Lbits.SHRSAMPをセットし手動でサンプリングを開始します。
- 任意のサンプリング時間を待ってから、ADCON3Lbits.SHRSAMPをクリアします。
u2_SamplingTime = 30u;
while (ADCON3Lbits.CNVRTCH == 1u){;}
ADCON3Lbits.SHRSAMP = 1u;
while(u2_SamplingTime > 0){u2_SamplingTime --;}
ADCON3Lbits.SHRSAMP = 0u;
②AD変換フェーズ
- ADCON3Lbits.CNVRTCH をセットしサンプリングを行います。
- 数クロック待機します
ADCON3Lbits.CNVRTCH = 1u;
u2_SamplingTime = 10;
while(u2_SamplingTime > 0){u2_SamplingTime --;}
③移動平均フェーズ
- AD変換完了フラグが立っていたら、ADCBUF0からデータを取り出し8回の移動平均を取ります
if ((ADSTATL & 0x0001u) == 0x0001u)
{
Pot.u2_Sum -= Pot.u2_Buffer[Pot.u2_Head];
Pot.u2_Buffer[Pot.u2_Head] = ADCBUF0;
Pot.u2_Sum += Pot.u2_Buffer[Pot.u2_Head];
Pot.u2_Head ++;
Pot.u2_Head &= 0x07;
Pot.u2_Ave = Pot.u2_Sum >> 3u;
}
④LED点灯判定フェーズ
- 移動平均の結果、ポテンションの値が1.65Vを超える場合、LED1を点灯。以下の場合LED1を点灯させます
if (Pot.u2_Ave > 2048u ){ PIN_MASTER_LED1 = 1u;}
else { PIN_MASTER_LED1 = 0u;}
コンフィグレーション設定について
コンフィグレーション設定についてはコンフィグレーション設定に記載しております。
コピーして下記のソースコードの「 //ここにコンフィグレーション設定を挿入する// 」の位置に挿入してください。
クロック設定について
クロック設定用関数 vds_Main_Init_Clock_Register(); のソースコードはクロック設定のページに記載しております。
コピーして下記のソースコードの「 //ここにクロック設定ソースをコピペする// 」の位置に挿入してください。
/*--------------------------------------------------------------------------------*/
/* @file AD_POTANTION.c */
/* @brief ポテンションの値をソフトで平均化、結果によってLEDの点灯・消灯 */
/* @details GPIO(TRIS,LAT) */
/* AD(ADCON1H,ADCON2L,ADCON2H,ADCON3L,ADCON3H,ADCON5H) */
/* AD(ANSELA,ADSTATL,ADCBUF) */
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/* コンフィグレーション設定*/
/*--------------------------------------------------------------------------------*/
//ここにコンフィグレーション設定を挿入する//
/*--------------------------------------------------------------------------------*/
/* インクルードファイル*/
/*--------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
/*--------------------------------------------------------------------------------*/
/*【CONST】定数定義*/
/*--------------------------------------------------------------------------------*/
#define ADSIZE 8u
/*--------------------------------------------------------------------------------*/
/*【VARI】変数定義*/
/*--------------------------------------------------------------------------------*/
struct
{
unsigned int u2_Sum;
unsigned int u2_Head;
unsigned int u2_Ave;
unsigned int u2_Buffer[ADSIZE];
}Pot;
unsigned int u2_SamplingTime;
/*--------------------------------------------------------------------------------*/
/* クロック設定 */
/*--------------------------------------------------------------------------------*/
//ここにクロック設定ソースを挿入する//
/*--------------------------------------------------------------------------------*/
/* Main関数 */
/*--------------------------------------------------------------------------------*/
int main(int argc, char** argv)
{
/*---------------------------------------------------------------------------*/
/* クロック初期化*/
/*---------------------------------------------------------------------------*/
vds_Main_Init_Clock_Register(); /* クロック初期化 */
/*---------------------------------------------------------------------------*/
/* GPIO初期化*/
/*---------------------------------------------------------------------------*/
TRISEbits.TRISE0 = 0u; /* LED1ピンはデジタル出力ピン */
ANSELAbits.ANSELA0 = 1u; /* RA0ピンはアナログピン*/
/*---------------------------------------------------------------------------*/
/* AD初期化*/
/*---------------------------------------------------------------------------*/
ADCON1L = 0x0000u;
ADCON1H = 0x0000u;
ADCON2L = 0x0000u;
ADCON2H = 0x0000u;
ADCON3L = 0x0000u;
ADCON3H = 0x0000u;
ADCON5H = 0x0000u;
/***** AD制御レジスタの設定 ******/
ADCON1Hbits.SHRRES = 3u; /* シェアADC分解能 (3 = 12bit) */
ADCON2Lbits.SHRADCS = 2u; /* シェアADCクロックディバイダ */
ADCON2Hbits.SHRSAMC = 4u; /* シェアADCサンプル時間 (3 = 4TAD) */
ADCON3Lbits.CNVCHSEL = 0u; /* ソフトウェアAD入力(0 =AN0入力)*/
ADCON3Hbits.CLKSEL = 2u; /* ADCクロックソース (2 = AFVCODIV) */
ADCON3Hbits.CLKDIV = 2u; /* ADCクロックディバイダ(2 = 3Clock)*/
ADCON5Hbits.WARMTIME = 15u; /* ウォームアップ時間(15 = 32768Clock) */
/***** ADの有効化 ******/
ADCON1Lbits.ADON = 1u; /* ADC全体のパワーON */
ADCON5Lbits.SHRPWR = 1u; /* シェアADCのパワーON */
while(ADCON5Lbits.SHRRDY == 0u){;}
ADCON3Hbits.SHREN = 1u; /* シェアADCの有効化 */
ADCON3Lbits.CNVCHSEL = 0u;
/*-------------------------------------------------------------------------*/
/* メインルーチン*/
/*-------------------------------------------------------------------------*/
while(1)
{
/*-----------------------------------------------------------------*/
/* ①サンプリング*/
/*-----------------------------------------------------------------*/
u2_SamplingTime = 30u;
while (ADCON3Lbits.CNVRTCH == 1u){;}
ADCON3Lbits.SHRSAMP = 1u;
while(u2_SamplingTime > 0){u2_SamplingTime --;}
ADCON3Lbits.SHRSAMP = 0u;
/*-----------------------------------------------------------------*/
/* ②AD変換*/
/*-----------------------------------------------------------------*/
ADCON3Lbits.CNVRTCH = 1u;
u2_SamplingTime = 10;
while(u2_SamplingTime > 0){u2_SamplingTime --;}
/*-----------------------------------------------------------------*/
/* ③移動平均*/
/*-----------------------------------------------------------------*/
if ((ADSTATL & 0x0001u) == 0x0001u)
{
Pot.u2_Sum -= Pot.u2_Buffer[Pot.u2_Head];
Pot.u2_Buffer[Pot.u2_Head] = ADCBUF0;
Pot.u2_Sum += Pot.u2_Buffer[Pot.u2_Head];
Pot.u2_Head ++;
Pot.u2_Head &= 0x07;
Pot.u2_Ave = Pot.u2_Sum >> 3u;
}
/*-----------------------------------------------------------------*/
/* ④LED点灯判定*/
/*-----------------------------------------------------------------*/
if (Pot.u2_Ave > 2048u ){ PIN_MASTER_LED1 = 1u;}
else { PIN_MASTER_LED1 = 0u;}
}
}


コメント