PICでのプログラミングについて教えて下さい。
現在電圧計を製作していて4桁の7セグダイナミック点灯で行き詰っております(超初心者です)。
PICは16F873Aを使用、コンパイラはCCS、書き込みはピックライタ、あとシリアルデバッカを使用しています。
外部から電圧をかけそれをAD変換し、AD変換結果(0~5V)を7セグに表示させようとしています。
一応今の状態でも電圧表示はできていることはできているのですが一桁目から4桁目まで目で追えるくらい遅いスピードでこれを改善したいです。ソースは下記のソースを製作しました。この状態で3日間悩んでおります...知恵をお貸しいただけないでしょうか。
よろしくお願いします。
#include <16F873a.h>
#device ADC=10 //A/D変換10bitモード
#use fast_io(A) /* TRISレジスタの設定が必要 */
#use fast_io(B)
#use fast_io(C)
#use delay (clock=10000000) //10MHz
#use RS232( BAUD = 9600, XMIT = PIN_C6, RCV = PIN_C7, PARITY = N, BITS = 8 )
#fuses HS,NOWDT,PUT,NOPROTECT,NOBROWNOUT,NOLVP
#define VOLTAGE PIN_A0 // (in)
#define CORRENT PIN_A1 // (in)
#define VREF1 PIN_A2 // (in)
#define VREF2 PIN_A3 // (in)
#define RESERVE1 PIN_A4 // (out)
#define RESERVE2 PIN_A5 // (out)
#define LED_DP PIN_B0 // (out)
#define LED_A PIN_B1 // (out)
#define LED_B PIN_B2 // (out)
#define LED_C PIN_B3 // (out)
#define LED_D PIN_B4 // (out)
#define LED_E PIN_B5 // (out)
#define LED_F PIN_B6 // (out)
#define LED_G PIN_B7 // (out)
#define DIG_0 PIN_C0 // (out)
#define DIG_1 PIN_C1 // (out)
#define DIG_2 PIN_C2 // (out)
#define DIG_3 PIN_C3 // (out)
#define INI_TRIS_A_VAL 0x0F // 7:x 6:x 5:out 4:out 3in 2:in 1:in 0:in
#define INI_TRIS_B_VAL 0x00 // 7:out 6:out 5:out 4:out 3out 2:out 1:out 0:out
#define INI_TRIS_C_VAL 0x80 // 7:in 6:out 5:out 4:out 3:out 2:out 1:out 0:out
int ct;//数字の更新間隔
long val;//表示する数字
int digit;//表示する桁
//表示パターン
int segment_data[]={0x81,0xF3,0x49,0x61,0x33,0x25,0x05,0xF1,0x01,0x31};
char st[4];
void main()
{
float ata1,data2,data3,data4;
long data5;
long val;
SET_TRIS_A( INI_TRIS_A_VAL );
SET_TRIS_B( INI_TRIS_B_VAL );
SET_TRIS_C( INI_TRIS_C_VAL );
setup_adc_ports(AN0_AN1_VSS_VREF);
setup_adc(ADC_CLOCK_DIV_32); //Fosc/32 最高速度
digit=0;
ct=1;//数字を更新する周期
val=0;//表示する値
while(1)
{
output_low(RESERVE2); //動作ランプ
//////////////////////電圧測定/////////////////////////////////
set_adc_channel(0);
delay_us(50); //アクイジションタイム待ち(マイクロ秒)
data1 = read_adc(); //AD変換結果読み込み
printf("ADC V %9.3f \r\n", data1 ); //AD変換データ表示
data2 = (data1 * 4.959695) / 1024; //BCDに変換
printf("Volt %6.3f \r\n", data2 ); //変換データ表示
data5 = data2 * 1000 ; //data2を整数に変換
val = data5 ;
printf("val %ld \r\n", val); //整数にし表示
/////////////////////7SEG表示//////////////////////////////////
ct --;
if(ct == 0){//数字の更新
st[3]=val/1000; //4桁目数値取り出し
st[2]=val/100-st[3]*10;//3桁目数値取り出し
st[1]=val/10-((st[3]*100)+(st[2]*10));//2桁目数値取り出し
st[0]=val%10;//あまり
val++;
if(val==1000) val=0;
ct=20;
}
if(digit== 3){//第4桁の表示
output_b( segment_data[st[3]]);
output_bit(DIG_0,1); //4桁表示開始
output_low(LED_DP); //小数点表示
delay_us (5); //表示期間(ミリ秒)
output_bit(DIG_0,0); //表示を消す
output_high(LED_DP); //小数点を消す
delay_us(50); //待ち(マイクロ秒)
}
if(digit== 2){
output_b( segment_data[st[2]]);
output_bit(DIG_1,1);
delay_ms (5);
output_bit(DIG_1,0);
delay_us(50);
}
if(digit== 1){
output_b( segment_data[st[1]]);
output_bit(DIG_2,1);
delay_ms (5);
output_bit(DIG_2,0);
delay_us(50);
}
if(digit == 0){
output_b( segment_data[st[0]]);
output_bit(DIG_3,1);
delay_ms (5);
output_bit(DIG_3,0);
delay_us(50);
}
digit ++;//表示桁を変更
if(digit ==4 ) digit=0;
}
}
お礼
koujikuuさん、ご助言ありがとうございます。 解決しました。 原因は、やはりULPWUをインターバルとするSLEEP関数の部分の順番(手順)が違っていました。 GP0をOUTPUTしてHiを送りコンデンサに充電した後の処理で、GP0をINPUTにしてからULPWUEビットをONにしていたのがNGでした。 正しくは、GP0をINPUTにする前に、ULPWUEビットをON、IOCの0ビットをONにすることでうまく動作するようになりました。 Mikro-Cで書かれたULPWUのプログラムgた中々ないので後日、時間あればソースを公開させて頂きます。 ありがとうございました。