こんにちわ
としぶぅ~です。
昨日は20年来の知り合いと飲みに行ったのでお休みしました。
本日は、先日書きましたADの動作確認を行いました。
とりあえず動くように作ったソフトはこんな感じです。
”ad.c”
/*================================================================================
ADプログラム
File Name : ad.c
Target Compiler: HI-TECH C PRO(Lite MODE)
Verion : 1.0
================================================================================ */
#include ←必要
#include "ad.h" ←必要
#include "delay.h" ←必要
//AD機能とポートの設定
void adinit(unsigned char ansel)
{
/**************************************************
使用するADポートの設定を行う
ansel: bit0:ANS0(RA0)
bit1:ANS1(RA1)
bit2:ANS2(RA2)
bit3:ANS3(RA3)
bit4:ANS4(RA4)
bit5:ANS5(RB6)
bit6:ANS6(RB7)
bit7:
**************************************************/
TRISA=TRISA | 0x10; //ADポート(RA4)を入力設定にする
ANSEL=ansel; //ADコンバータの設定 ANS0-7
ADON=1; //ADコンバータ機能の許可
ADIE=0; //AD割り込み不許可
}
//ad Convert(8bit)
unsigned char ad4()
{
/*************************************************
channel:AN4
基準電圧:電源電圧を使用
AD変換clock:8MHz/16
ADFM=0 Leftjustified
変換時間:
**************************************************/
unsigned char temp = 10;
//設定
ADCON1=0x40; //0110 0000 A/D結果は左詰め,FOSC/16,A/D基準電圧:+Vdd-VSS
ADCON0=0x61; //01xx x001 FOSC/16,ANS4,A/D Status(INPUT),A/D-ON
DelayUs(50); /* Delay関数使用 : 安定待ち */
//AD変換開始
GO_DONE=1;
//変換終了待ち
while(GO_DONE==1){}
//変換結果処理
return(ADRESH);
}
次はヘッダファイル
”ad.h”
extern void adinit(unsigned char ansel);
extern unsigned char ad4();
簡単ですが。。。こんな感じです。
後、時間待ち用にDelayも追加しています。
(これは何かの書籍にあったものをそのまま使用しています。たしか・・・トラ技だっけ??)
”delay.c”
//*
//* Delay functions
//* See delay.h for details
//*
//* Make sure this code is compiled with full optimization!!!
//*
#include "delay.h"
void
DelayMs(unsigned char cnt)
{
#if XTAL_FREQ
do {
DelayUs(996);
} while(--cnt);
#endif
#if XTAL_FREQ > 2MHZ
unsigned char i;
do {
i = 4;
do {
DelayUs(250);
} while(--i);
} while(--cnt);
#endif
}
次はヘッダファイル
”delay.h”
/*
* Delay functions for HI-TECH C on the PIC
*
* Functions available:
* DelayUs(x) Delay specified number of microseconds
* DelayMs(x) Delay specified number of milliseconds
*
* Note that there are range limits: x must not exceed 255 - for xtal
* frequencies > 12MHz the range for DelayUs is even smaller.
* To use DelayUs it is only necessary to include this file; to use
* DelayMs you must include delay.c in your project.
*
*/
/* Set the crystal frequency in the CPP predefined symbols list in
HPDPIC, or on the PICC commmand line, e.g.
picc -DXTAL_FREQ=4MHZ
or
picc -DXTAL_FREQ=100KHZ
Note that this is the crystal frequency, the CPU clock is
divided by 4.
* MAKE SURE this code is compiled with full optimization!!!
*/
#ifndef XTAL_FREQ
#define XTAL_FREQ 4MHZ /* Crystal frequency in MHz */
#endif
#define MHZ *1000L /* number of kHz in a MHz */
#define KHZ *1 /* number of kHz in a kHz */
#if XTAL_FREQ >= 12MHZ
#define DelayUs(x) { unsigned char _dcnt; \
_dcnt = (x)*((XTAL_FREQ)/(12MHZ)); \
while(--_dcnt != 0) \
continue; }
#else
#define DelayUs(x) { unsigned char _dcnt; \
_dcnt = (x)/((12MHZ)/(XTAL_FREQ))|1; \
while(--_dcnt != 0) \
continue; }
#endif
extern void DelayMs(unsigned char);
次にテンプレートにも追加します。
”main.c"
/*================================================================================
Templateプログラム
タイマー割り込みを使って時間をカウントして処理を時分割させる
File Name : main.c
Target Compiler: HI-TECH C PRO(Lite MODE)
Verion : 1.0
================================================================================ */
//PIC用の定義ファイルのインクルード
//HI-TECH Cでは、必ず指定する
#include
#include "ad.h" //AD用の関数(20120908追加)
#include "delay.h" //Delay用関数(20120908追加)
//コンフィグレーションメモリの設定
__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CPD_OFF & BOREN_OFF & LVP_OFF & CP_OFF & FCMEN_OFF & IESO_OFF);
//タイマの再設定値を定義
// 2000cycle@(8MHz / 4) == 1ms
// そこからTimer1再設定に要するサイクルを引いたもの
#define WAIT_CYCLE (2000-5)
#define TMR1H_INIT ((unsigned char)(((unsigned short)(65536-WAIT_CYCLE))>>8))
#define TMR1L_INIT ((unsigned char)(((unsigned short)(65536-WAIT_CYCLE))&0x00ff))
//ビット操作命令のマクロを定義
#define clear_bit( reg, bitNumb ) ((reg) &= ~(1 << (bitNumb))) //指定されたビットをクリア
#define set_bit( reg, bitNumb ) ((reg) |= (1 << (bitNumb))) //指定されたビットをセット
#define test_bit( reg, bitNumb ) ((reg) & (1 << (bitNumb))) //指定されたビットをテスト
unsigned char tmr_1ms;
unsigned char tmr_4ms;
unsigned char tmr_4ms_up;
unsigned char tmr_cnt_up;
unsigned char ad_data; //(20120908追加)
//割り込み関数
//1/100秒の、タイマのオーバーフロー割り込みで、計測値のインクリメントと、スイッチの確認を行う
void interrupt f_int( void )
{
//タイマ割り込みかどうかをチェックして、タイマ割り込み以外の場合は、処理をしない
if(TMR1IF) {
//タイマの値を再設定し、次の割り込みが1/1000秒後に発生するように設定する
TMR1H = TMR1H_INIT;
TMR1L = TMR1L_INIT;
TMR1IF=0; //タイマ1の割り込みフラグをクリアする
tmr_4ms++; //10msごとのカウンタをインクリメント
if(tmr_4ms >= 4){
tmr_4ms = 0;
tmr_4ms_up = 1;
tmr_cnt_up++;
//PORTB 0bitをon/offして4msでtmr_cnt_upが4msになっていることを確認する。
if(test_bit(PORTB,0)){
clear_bit(PORTB,0);
}else{
set_bit(PORTB,0);
}
}
}
}
//ハードウェアの初期化
//使用する回路に合わせて、I/Oポートの方向などを設定する
void IoInit(void)
{
OSCCON = 0x70; //CLK=8MHzに設定する
//ポートの設定
TRISA = 0b00010000; //ポートAは使用しないが、出力に設定 PORTA-bit3=SW入力
TRISB = 0b00000000; //ポートBは使用しないが、出力に設定
PORTA = 0; //ポートAの初期値を0にする
PORTB = 0; //ポートBの初期値を0にする
ANSEL = 0b00000000; //アナログモードは使用しないので、0を指定
}
//タイマ1の初期化
void Tmr1Init(void)
{
T1CON = 0x00; //プリスケーラを、内部クロック、1:1に設定
TMR1H = 0; //タイマ1の初期値を0にする
TMR1L = 0;
TMR1IF = 0; //割り込みフラグをクリアする
//タイマ1割込を有効にする
TMR1IE = 1;
PEIE = 1;
//グローバルの割り込み制御ビットを有効にする
GIE = 1;
}
//メインルーチン
void main( void )
{
unsigned char ansel;
IoInit(); // I/Oポートの初期化
Tmr1Init(); // タイマ1の初期化
ansel = 0x10; // AD4を指定(20120908追加)
adinit(ansel); // RA4をAD4ポートとして初期化する(20120908追加)
//タイマ周期が1/100秒になるように、初期化する
TMR1H = TMR1H_INIT;
TMR1L = TMR1L_INIT;
//時間のカウンタの初期化
tmr_1ms = 0;
tmr_4ms = 0;
tmr_4ms_up = 0;
tmr_cnt_up = 0;
//タイマ1を開始する
TMR1ON=1;
//無限ループ
while(1){
if(tmr_4ms_up == 1){
tmr_4ms_up = 0;
switch(tmr_cnt_up){
case 0: ad_data = ad4(); //処理1 ADを実施(20120908追加)
break;
case 1: //処理2
break;
case 2: //処理3
break;
case 3: //処理4
break;
case 4: //処理5
break;
}
}
//PORTB 3bitをon/offしてプログラムの1周期がどれくらいになるかを確認する。
if(test_bit(PORTB,3)){
clear_bit(PORTB,3);
}else{
set_bit(PORTB,3);
}
}
}
赤字の部分が追加が必要なところです。
それでは下記のラインにブレイクポイントをしかけて、その時の取り込み
レジスタの状態を確認して、供給電圧に応じた取り込みができているかを
確認してみます。
case 0: ad_data = ad4(); //処理1 ADを実施(20120908追加)
※ここにブレイクポイントをしかけます
とりあえず3段階で電圧を変更します。(下記のボリュームを回して変更する)
また、A/Dの取り込み値は、MPLABとPickit2の組み合わせでデバッグモードでレジスタの内容を
確認したいと思います。
最大電圧値:4.809V
ブレイクポイントで止めてレジスタを確認
4.809V入力で、ほぼMAXのFF80H左づめなので、3FEH最下位bitは、”0”になっています。
8bitで取り込むつもりなので、下位2bitは無視するのでFFHとなりますので問題ないですね。。。
中間電圧値:2.193V
2.193V入力で、ほぼMAXの7480H左づめなので、1D2H最下位bitは、”0”になっています。
下位2bitは無視するので74Hとなります。
MAX電圧が4.8Vなので4.8V/256(8bit)→1bitあたり0.01875Vとなります。
74H=116なので、0.01875 X 116 = 2.175Vとなります。
多少誤差がありますが、こんなもんでしょうかね。。。8bitなので問題ないと思います。
※誤差とは測定器とか。。。いろいろ含めての誤差を示します。。。
最小電圧値:0.000V
ほぼ0V入力で、ほぼMAXの0000H左づめなので000H。
最低電圧は000Hで問題なし。
ADは問題なく動作しているようです。
これで温度センサを取り付けてもA/Dできるということがわかりました。
その前に、次回は、A/Dした内容をLCDに表示する関数を組み込もうと思います。
それでは今日はこの辺で
(^^)/~