• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:PIC(デジタル電圧計のプログラム)について教えてください)

デジタル電圧計作成についての質問

このQ&Aのポイント
  • デジタル電圧計作成において、0.1単位で表示させる方法について質問です。
  • 現在作成中のデジタル電圧計は、PIC16F819を使用し、1点(0ch)0~5Vの範囲を7セグメントLEDで表示するものです。
  • また、プログラムの一部の処理についても疑問があるようです。

質問者が選んだベストアンサー

  • ベストアンサー
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

プログラムで書くと長くなりそうなので考え方だけ書きます。 ・少数を扱うと面倒なので内部電圧値として0から49の数値として扱います。 ・ADコンバートして得れる値は10ビットですから0から1023までの値をとります。これを21で割ると内部電圧値として0から48までの数値になります。誤差多いですかね?(割り算は、いちばん簡単な引ける回数をカウントする方法で計算します) ・上位桁と下位桁は、内部電圧値を10で割ったら上位桁で、下位桁は余りです。これをそれぞれのLEDに表示すれば0.0vから4.8vまで表示可能です。 [+α案] (1)遅くなるが精度を上げる方法。 ・ADコンバートで入力された値を10倍して、これを204で割ります。これで0から50の値を得ることができます。この値の方が精度が高くなります。 (2)とてもアセンブラな方法。 ・ADコンバートした値をADとします。 ・ADを右へ1ビットシフトして1/2にします。これをAD05とします。 ・ADとADとADを足してAD3を作ります。 ・AD3とAD3を足してAD6を作ります。 ・AD6とAD6を足してAD12を作ります。 ・AD12とAD05を足して、AD125を作ります(12.5倍したことになります)。 ・AD125を右へ8ビットシフトして1/256にします。これで0から49の数値が得られます。これが一番精度が高くて高速な方法です。 疑問があったら質問してください。

noname#46996
質問者

お礼

お返事ありがとうごぜいます。 お礼が遅れてごめんなさい。 たくさん書いていただいたのですがよく理解できないのでまた質問させていただいてもいいでしょうか?? 初歩的なものばかりで申し訳ないのですが・・ [+α案]の(2)についてなのです。 何がわからないかがうまく説明できないので質問が難しいのですが。 ・なぜ1/256するのですか?256=2^8ですよね。出力のビット数で割ると何がわかるのでしょうか?? ・なぜ1/256するのにまず12.5倍するのですか? ・ポートBの8ビットを7セグメントの上位下位に分けて出力するときに、どのようにすれば00~49という値が手に入るのでしょうか。 ・・なんだか質問もあいまいになってしまいましたが・・ よろしかったらまたお答お願いします。

その他の回答 (16)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.17

大事なことは、まずハードの動作を確認することです。 次の事は一回でも、試しましたか? (1)2つのLEDにそれぞれ、0,1,2,4,8が表示できることを確認する。全部の結線が正しいかこれで確認できる。 (2)AN0からちゃんと入力されているか?ADRESHの値をそのままPORTBに出力して電圧でLEDの表示が変化することを確認する。もちろん16進の値を与えるのでLED表示はデタラメだが、とりあえずAN0に反応していることは確認できる。 これらをクリアしたら、初めてソフトの検証に入りましょう。 ソフトの方は、合っているように見えますがシミュレートしてみないと分かんないですね。

noname#46996
質問者

お礼

ありがとうございます。 おかげ様でなんとかうまく走らせることができました。 いろいろとお世話になりました。 何度も何度もご迷惑をおかけしてごめんなさい。 本当にありがとうございます!

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.16

>あと、また質問で申し訳ないのですが、 >入力を0chと1chの2つにして、1秒ごとにそれぞれの値を出力することってできますかね?? >その場合、どういったプログラムを追加すべきですか?? >交互に表示っていうのは無理でしょうか? 切り替えることは全然問題ありません。追加するの物。 (1)どちらを表示しているかを覚えておくメモリ。1秒毎に値をXORなどで反転してやる。その値をみてAN0かAN1かをADCON0で切り替える。 (2)タイマーを使って1秒を計測する処理。タイマー1を使います。クロックからタイマーの周期を自分でちゃんと計算しましょう(PICの回路図がわからないのでアドバイスできませんです)。 参考↓ http://www.page.sannet.ne.jp/ja1hwo/pic/pic_25.htm って参考先を見て思い出しました。 8ビットのPICってSFRのバンク切り替え制御をする必要がありました。最近16ビットのdSPICばっかりだったので忘れてましたよ。 16ビット計算の方でADRESLを使うときは BSF STATUS,RP0 と BCF STATUS,RP0 を追加してください。

noname#46996
質問者

お礼

ありがとうございます。 また考えてみますね。 あと、今リファレンス電圧5.1で走らせてみてるんですけど・・ 7セグメントの表示が変わりません; 電圧をあげていってもいっこうに0のままです。 考えられる原因はなんですかね? 参考までに現在のプログラムです↓ LIST P=PIC16F819 #INCLUDE<P16F819.INC> __CONFIG _HS_OSC & _CP_OFF & _WDT_OFF & _PWRTE_ON & _MCLR_ON & _LVP_OFF     CNT EQU 020H     SHOU EQU 021H     AMARI EQU 022H     TMP EQU 023H ORG 0H MAIN     BSF STATUS,RP0     MOVLW 01H     MOVWF TRISA     MOVLW 00H     MOVWF TRISB     MOVLW 00DH     MOVWF ADCON1     BCF STATUS,RP0     MOVLW 081H     MOVWF ADCON0     CLRF PORTA     CLRF PORTB     CLRF SHOU ADSTART     CALL TIME20U     BSF ADCON0,GO ADLOOP     BTFSC ADCON0,GO     GOTO ADLOOP     MOVF ADRESH,W     MOVWF TMP     MOVLW 5     CALL WARI     MOVF SHOU,W     MOVWF TMP     MOVLW 10     CALL WARI     CALL LED     GOTO ADSTART WARI     SUBWF TMP     BTFSS STATUS,C     RETURN     INCF SHOU     GOTO WARI LED     ADDWF TMP SWAPF SHOU,W     IORWF AMARI,W     MOVWF PORTB     RETURN TIME20U     MOVLW 020H     MOVWF CNT     NOP LOOP     DECFSZ CNT,F     GOTO LOOP     RETURN     END お時間があればまたよろしくお願いします。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.15

>MOVLW 00DH >MOVWF ADCON1 >の部分で左詰めにしたつもりなんですが・・違ってましたか? 00DHなら左詰め、08DHなら右詰ですので正解です。 >それから、シミュレータやってみたんですけどエラーがでてしまって・・; >また時間のあるときにゆっくり読んで試してみますね。 >どうもありがとうございます。 アセンブルは出来てますよね? アセンブルが通らないとシミュレーションできませんよ。 >シミュレーション前で申し訳ないのですが、もしおかしなところがあればご指摘おねがいします。 惜しいです。 CALL LED のあと、 GOTO ADSTART が抜けてます。 あとは大丈夫に見えますので、ぜひ走らせて見てください。

noname#46996
質問者

お礼

ありがとうございます。 今日か明日にでも走らせて見ますね。 あと、また質問で申し訳ないのですが、 入力を0chと1chの2つにして、1秒ごとにそれぞれの値を出力することってできますかね?? その場合、どういったプログラムを追加すべきですか?? 交互に表示っていうのは無理でしょうか?

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.14

>ただ、上位8ビットだけを使って計算することってできるんですか? >私は、0~255ではなくて、0~1023だと思ってました。(勝手に10ビットに割り当てられるのかなと・・) ADCON1のADFMビットでADコンバートの右詰/左詰を切り替えることができます。左詰にするとADRESHに上位8ビットが割り当てられますので、そこを見る限りは0~255の値です。最初のプログラムはそうなってますよね? 逆に右詰にするとADRESHとADRESLで合わせて0~1023の10ビットの値を扱うことができます。細かい精度がほしくなければ8ビットで十分ですから。 >プログラムはシミュレータにかけていません。 >MPLABの入ってないパソコンで作っていたので; >ごめんんさい。 >次からは注意します。 PICマイコンが無くてもMPLABは使えますので、ぜひインストールしてください。シミュレータで動作を確認することが理解の早道です。PICマイコンが無くても動作を確認できるなんてすごく便利なんですから。

noname#46996
質問者

お礼

お返事ありがとうございます。 左詰めにするとADRESHに上位8ビットが割り当てられるんですね。 分りました。どうもです。 ひとつ前に書いたプログラムも MOVLW 00DH MOVWF ADCON1 の部分で左詰めにしたつもりなんですが・・違ってましたか? それから、シミュレータやってみたんですけどエラーがでてしまって・・; また時間のあるときにゆっくり読んで試してみますね。 どうもありがとうございます。 とりあえず5で割ることの意味がやっとわかりました。 サブルーチン化したほうがよいとのことだったので、 ADLOOP     ・     ・     ・    MOVWF  TEMP    MOVLW  5    CALL  WARI    MOVF  SHOU,W    MOVWF  TEMP    MOVLW  10    CALL  WARI    CALL  LED WARI    SUBWF  TEMP    BTFSS  STATUS, C    RETURN    INCF   SHOU    GOTO   WARI としてみました。 シミュレーション前で申し訳ないのですが、もしおかしなところがあればご指摘おねがいします。 本当に何度も何度もごめんなさい。 ありがとうございます。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.13

>ADRESHだけを取り出して割っていくのでよかったですか?? 5で割り忘れてます。250を10で割っていますよ。0~9の間の値しかLEDには表示できません。 それと2回割り算するので、TIME20Uの様に割り算をサブルーチン化したほうが良いでしょう。 このプログラムは、ちゃんとシミュレータで走らしてみましたか? 走らせていれば問題に気づいたはずです。 私の言う通り作っていても理解したことになりませんよ。VDDが5.12Vは間違ってましたが、この間違いを指摘できるぐらいの理解度を目指してくださいね。 理解しないでプログラムを作っても今後の応用が利きませんから、理解するのことを最優先でやりましょう。

noname#46996
質問者

お礼

ありがとうございます。 何で5.1Vに設定すればよいのかも分りました。 ただ、上位8ビットだけを使って計算することってできるんですか? 私は、0~255ではなくて、0~1023だと思ってました。 (勝手に10ビットに割り当てられるのかなと・・) プログラムはシミュレータにかけていません。 MPLABの入ってないパソコンで作っていたので; ごめんんさい。 次からは注意します。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.12

>なんでVDDを5.12にすれば5VのときにADRESHの値が250になるんですか?? 上位8ビットを利用する設定でかつリファレンス電圧がVDDの設定でADコンバータを動かす前提で話します。 ADコンバータは、リファレンス電圧を基準に電圧を数値化します。ADRESHは0から255の間を取りますが、VDDと同じ電圧のとき255の値をとります。 あっと、しまった。今気づきましたがVDDは5.1Vが正しいですね。訂正します。 例を書きます。 ADRESHが255←AN0の入力電圧が5.1V ADRESHが250←AN0の入力電圧が5.0V ADRESHが200←AN0の入力電圧が4.0V となります。 電圧の変化と数値の変化は等比例することが、5.0Vで250だと言い切れる理由です。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.11

>RA3に最高電圧を定める媒体をおいて、RA2はグランドにいれればなるかなぁって思ったんですけど違いますか?? それでもできます。ただし、電圧がVDD+0.3Vを超えると壊れる可能性があるので注意してください。 >VDDが5.12という整数以外の数にできるかはわかりませんが・・ データシートを見るとわかりますが、PIC16F819は電源電圧(VDD)が4.0V~5.5Vの間の電圧なら何Vでもかまいません。だから、可変電圧レギュレータICで5.12Vを電源電圧にできます。デジタルテスターで計るとわかりますが電圧なんて正確に5.00Vが出ている可能性はほとんどZEROですよ。5Vの電源レギュレータICを通していても正確に5Vじゃないのを知識として知っておいてください。 >あと、そうするとなぜすべて8ビットで計算できるのかを詳しく教えていただいてもよろしいですか?? AN.07で答えてますよ。

noname#46996
質問者

お礼

お返事どうもです。 前答えていただいたのって >5Vの時にADRESHの値が250になる様にハード的に調整します。 >250を5で割ると50ですから、5Vの時50という値が得られるようになります。 >あとは、10で割った値と余りをLEDに表示するだけです。 ですよね。 なんでVDDを5.12にすれば5VのときにADRESHの値が250になるんですか??

noname#46996
質問者

補足

あと、一応書いてみたのですが・・ LIST P=PIC16F819 #INCLUDE<P16F819.INC> __CONFIG _HS_OSC & _CP_OFF & _WDT_OFF & _PWRTE_ON & _MCLR_ON & _LVP_OFF     CNT    EQU   020H     SHOU   EQU   021H     AMARI   EQU   022H     TMP    EQU   023H          ORG    0H MAIN     BSF    STATUS,RP0     MOVLW   01H     MOVWF   TRISA     MOVLW   00H     MOVWF   TRISB     MOVLW   00DH     MOVWF   ADCON1     BCF    STATUS,RP0     MOVLW   081H     MOVWF   ADCON0     CLRF   PORTA     CLRF   PORTB ADSTART     CALL   TIME20U     BSF   ADCON0,GO ADLOOP     BTFSC   ADCON0,GO     GOTO   ADLOOP     MOVF   ADRESH,W     MOVWF   TMP     CLRF   SHOU     MOVLW   10 LOOP1     SUBWF   TMP     BTFSS   STATUS,C     GOTO   LED     INCF   SHOU     GOTO   LOOP1 LED     ADDWF  TMP     SWAPF  SHOU,W     IORWF  AMARI,W     MOVWF  PORTB     GOTO   ADSTART TIME20U     MOVLW  020H     MOVWF  CNT     NOP     LOOP     DECFSZ CNT,F     GOTO  LOOP ADRESHだけを取り出して割っていくのでよかったですか??

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.10

>何[V]を1024で割るかを決められるようで、考え方によってはもう少し楽なプログラムができるんじゃないかなと思ってるんですけど・・ そんな制御ができるレジスタは聞いたことが無いです。 何レジスタのどのビットの事でしょうか? ADコンバータの変換クロックと勘違いしていませんか? 私としては、VDDを5.12Vにしてやるのが一番簡単だと思いますけど。そうすれば5Vの時にADコンバータの上位8ビットの値が250になるので、全て8ビットで計算できます。

noname#46996
質問者

お礼

いつも素早い返答をありがとうございます。 ADCON1の設定を00CHにすればなりませんかね? ADCON1の下位は以下のようになっていています。 PCFG AN4 AN3 AN2  AN1 AN0 VREF+ VREF- C/R 1101 D VREF+ VREF-  A  A   AN3  AN2  2/2 1110 D  D    D   D  A   AVDD AVSS 1/0 (RA3/AN3/VREF+,RA2/AN2/VREF) RA3に最高電圧を定める媒体をおいて、RA2はグランドにいれればなるかなぁって思ったんですけど違いますか?? VDDが5.12という整数以外の数にできるかはわかりませんが・・ あと、そうするとなぜすべて8ビットで計算できるのかを詳しく教えていただいてもよろしいですか??

noname#46996
質問者

補足

↓ごめんなさい。表がずれましたね。 また00DHにすれば・・の間違いでした。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.9

補足事項。 MPLABにソフトシミュレーション機能があるのを知っていますか? この機能を使うと1ステップづつ命令動作を確認することが出来ます。 http://www.picfun.com/mplab00.html 勉強になりますので、ぜひ使ってみてください。 私に質問する前に、これで動作確認した上で疑問があったら聞いてもらえると効率良く作業を進めることが出来ると思います。

noname#46996
質問者

お礼

今調べたところ、PIC16F819の設定でリファレンス電圧を決めることができるみたいです。 何[V]を1024で割るかを決められるようで、考え方によってはもう少し楽なプログラムができるんじゃないかなと思ってるんですけど・・ そんなことないですかね??

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.8

チェックが遅くなりましたが、まだ問題が何点かあります。 あくまで目検で見つけただけの問題なので、実際に走らせると別の問題がでるかもしれません。 問題点のある周辺のソースだけをコメントしました。 ; 3回を一度に足すのは駄目。キャリー(C)値が正常ではなくなるため。 BCF STATUS,C ;これは意味が無いです。RRFの時は意味あり。 MOVF ADRESL ;AD→AD? MOVF ADRESL,Wが正解。 ADDWF ADRESL ;AD+AD→AD? ADDWF ADRESL,Wが正解。 ; ここで上位の桁の処理を先にすること。今の流れだとキャリー値が壊れます。 ADDWF ADRESL ;AD+AD+AD→AD MOVWF AD3L ;W→AD3L ADDWF AD3L,F ;AD3L+W→AD3Lで意味不明?横にコメント書くとミスに気づきやすいですよ。 ; この計算は全てやり直しのこと。 MOVF ADRESH BTFSC STATUS,C INCF ADRESH,W ADDWF ADRESH BTFSC STATUS,C INCF ADRESH,W ADDWF ADRESH MOVWF AD3H BTFSC STATUS,C INCF ADRESH,W ADDWF AD3H,F ; MOVFのWの書き忘れが多いです。 BCF STATUS,C ;不要です。 MOVF AD3L MOVWF AD6L ADDWF AD6L,F MOVF AD3H BTFSC STATUS,C INCF AD3H,W ADDWF AD6H,F ;AD6Hの値が不定のまま、AD3Hに加算されています。 ; MOVFのWの書き忘れが多いです。 BCF STATUS,C ;不要です。 MOVF AD6L MOVWF AD12L ADDWF AD12L,F MOVF AD6H BTFSC STATUS,C INCF AD6H,W ADDWF AD12H,F ;上と同じです。 ; ん?AD12H,AD12Lの内容は足しこまれていません。 BCF STATUS,C MOVF AD05L MOVWF AD125L ADDWF AD125L,F MOVF AD05H BTFSC STATUS,C INCF AD125H,W ADDWF AD125H;Wに残さないと。 MOVWF TMP ;上位8bitを移動。W→TMPと転送する場合はWに最終値が必要です。 ; AD3,AD6,AD12,AD125は全て同じメモリにまとめた方が転送の無駄が減って楽かもしれません。どちらがプログラム的に分かりやすいか検討して決めてください。 ; 割り算ルーチン。OKかな。 CLRF SHOU MOVLW 10 LOOP1 SUBWF TMP BTFSS STATUS,C GOTO LED INCF SHOU GOTO LOOP1 LED ADDWF TMP SWAPF SHOU,W IORWF AMARI,W ;あまりはTMPに入っています。AMARIは未使用。 MOVWF PORTB GOTO ADSTART

関連するQ&A