電子負荷装置の製作(ソフトウェア)

Hardware & Software
Pocket

Windows用アプリの作成とパソコンと電子負荷との情報をやり取りする組み込みソフトの作成を行った。
 Windows用アプリ:        言語 python CPU:インテル i5-9600KF
 マイコンボード用組み込みソフト: 言語 c言語 CPU:ルネサス R8C29 16kB版 (実使用3kB未満)

【 各ソフトウェアの処理内容】

【Windows用アプリ フローチャート】

電圧/電流の測定結果を表示する処理に手間取った。
電圧測定後、一定時間毎にステップ電圧を加算し再度通信と測定をしたら、.placeで表示する。
という処理の繰り返しでは、最終値の表示しかされなかった。(上記表の赤字のループ)

色々、調査/検索した結果、下記2点の対策を行うことで改善できた。(上記表の緑のフロー)
(1).mainloopまで処理を進めないと、Windowsアプリの表示更新は行われない。
(2).mainloopの後に行いたい処理がある場合は、afterメソッドを使用する。

【 組み込みソフト】

R8C29マイコンの各機能(下記)の基本ライブラリは,過去に自作してあったものを流用したので、
メインプログラムの作成のみ行った。
 UART(シリアル)/ IICバス / AD変換 / ポート設定 / メインクロック・タイマー
 ※R8C29の選定理由は、自宅に複数個所有していて、本件の開発環境構築も容易な為。

電源に相当ノイズがのっている(下図)ので、それらの影響を極力抑えるため、
ADポートで電圧を読む際に、下記の処理を行った。
(1) ADポートの値を取り込む。
(2) 500uS待機する。※ノイズが収まっているかもしれないタイミングを狙う。
(3) (1)(2) を50回繰り返す。
(4) 最大値と最小値を破棄する。
(5) 48回の平均値を計算する。
(6) TxDポートから計算結果を出力する。

【ソースリスト】

Windows用pythonソースリスト

  1. # -*- coding: utf-8 -*-
  2. ##############################################################################################################################################
  3. # <目的>
  4. #  自作の電子負荷装置をパソコンから操作し、自動測定する。
  5. #
  6. # <パソコンから操作できる内容>
  7. #    ・指定した電流を本アプリにセットすると電子負荷の制御が開始され、下記3項目の測定と計算を行い、本アプリに結果を表示する。
  8. #        -> 単発測定モード
  9. # ・目標とする電流(最終値)、ステップ電流値(ステップアップのみ)、ステップ時間を入力すると、その設定に基づき電子負荷装置のパラメータが順次変更され、各ステップ値毎の下記3項目の測定と表示を行う。
  10. #        -> Sweep測定モード
  11. #
  12. #    -自動測定/計算項目-
  13. #     <1> 電源(入力)電圧 Vpw(V)
  14. #     <2> 負荷装置内の(シャント)抵抗に発生している電圧 Vs(V)
  15. #     <3> 負荷装置内の(シャント)抵抗に流れている電流(シャント抵抗0.5Ωと<2>の結果に基づき計算) Is (A)
  16. #
  17. # <電流設定範囲>
  18. #    0.04A 〜 3A
  19. # <ステップ電流設定範囲>
  20. #    0.04A 〜 目標とする電流(最終値)の1/2未満
  21. # <ステップ時間設定範囲>
  22. #    0より上、 10秒未満
  23. #
  24. # !!!注意事項!!!
  25. #    電子負荷装置の放熱が貧弱なため、単発/Sweep測定終了後は、速やかに、本アプリの”停止”ボタンを押すこと。 (停止ボタンを押すことで、最低電流値にセットされる)
  26. #
  27. # <ハードウェア構成>
  28. #    [PC] -USB - [USB/Serial変換基板] - Serial(TxD/RxD) - [R8C29] - IIC(SCL/SDA) - [電子負荷装置(DigiPOT : MCP4018)]
  29. #        [R8C29]AN10とAN11ポート で 電子負荷装置の電圧2か所を(分圧して)測定。 AD分解能10bit Max 0x03FF (=5V)
  30. #
  31. # <シリアル通信内容>
  32. #    PC -> R8C29 : MCP4018 レジスタ設定値 1バイト
  33. #    R8C29 -> PC : 電源電圧AD値 2バイト (?上位1バイト ?下位1バイト)、 シャント電圧AD値 2バイト (?上位1バイト ?下位1バイト) ※?->?->?->?の順で送信される
  34. # 
  35. # <機能追加予定>
  36. #    データの保存
  37. #    グラフのリアルタイム表示
  38. ##############################################################################################################################################
  39. import tkinter
  40. import serial
  41. #import datetime        # データ保存用
  42. #import numpy as np        # リアルタイムにグラフ表示する機能も追加するとき用
  43. # グローバル変数の初期値設定
  44. Stop_mode = 0                        #この値は、書き換えない -> 定数    #define Stop_mode 0
  45. Single_mode = 1                    #この値は、書き換えない -> 定数    #define Single_mode 1
  46. Sweep_mode = 2                    #この値は、書き換えない -> 定数    #define Sweep_mode 2
  47. Sweep_mode_running = 3        #この値は、書き換えない -> 定数    #define Sweep_mode_running 3
  48. step_time = 0                        # 関数"Data_measurement_Sweep()"のみが使用するグローバル変数
  49. after_ID_Number = None        # 関数"Data_measurement_Sweep()"と Stopボタン定義関数 が、使用するグローバル変数
  50. mode = Stop_mode                # グローバル変数
  51. ##############################################################################################################################################
  52. # ユーザー入力値のチェック
  53. def Check_entryCurrent(Current):
  54.     if (Current < 0.04) or (Current > 3):                #入力値が、0.04[A]以上で、3[A]以下かチェック
  55.             return False
  56.     Resister_val = 25.6 * Current                        # -> (128/5) * Current(A) * 1(ohm)
  57.     float_val = Resister_val - int(Resister_val)        # 小数点以下の四捨五入の計算
  58.     if float_val<0.5:
  59.         Resister_val = int(Resister_val)                # 小数点以下の数値が、0.5未満なら小数点以下を切り捨て(四捨)
  60.     else:
  61.         Resister_val = int(Resister_val)+1                # 小数点以下の数値が、0.5以上なら整数値に1を加算(五入)
  62.     return Resister_val                                    # MCP4018設定値を返す。
  63. ##############################################################################################################################################
  64. # シリアル通信処理
  65. def Serial_com(MCP4018_Resister_Data):
  66.     # シリアルポートの定義とオープン
  67.     ser = serial.Serial(        
  68.              port = 'COM4',
  69.                  baudrate = 19200,                    # これより上は、R8C29と通信できない。
  70.                      parity = serial.PARITY_NONE,
  71.                          bytesize = serial.EIGHTBITS,
  72.                             stopbits = serial.STOPBITS_ONE,
  73.                      timeout = None,
  74.                          xonxoff = 0,
  75.                             rtscts = 0,
  76.     )
  77.     #シリアルポートのリセット 
  78.     ser.reset_input_buffer()            # 受信バッファクリア
  79.     ser.reset_output_buffer()        # 送信バッファクリア
  80.     print('測定スタート')
  81.     print('MCP4018_Resister_Data =', MCP4018_Resister_Data)        # シリアルデータ読み取りと、結果表示
  82.     ser.write(MCP4018_Resister_Data.to_bytes(1,'big'))                    # MCP4018へレジスタ値を送信 (10進数データ(Max76=0x4C)をバイト型(1バイト))に変換)
  83.     print("TxD DATA = ", MCP4018_Resister_Data)        # debug
  84.     # 電源電圧の読み取り
  85.     ad_serial_2bytes = int.from_bytes(ser.read(), 'big')                                            # 上位1バイト読込
  86.     ad_serial_2bytes_vpw = ad_serial_2bytes * 256 + int.from_bytes(ser.read(), 'big')    # 上位1バイト+下位1バイト読込 (Max 5V = 0x03FF(Max))
  87.     # シャント電圧の読み取り
  88.     ad_serial_2bytes = int.from_bytes(ser.read(), 'big')                                        # 上位1バイト読込
  89.     ad_serial_2bytes = ad_serial_2bytes * 256 + int.from_bytes(ser.read(), 'big')        # 上位1バイト+下位1バイト読込 (Max 3A * 1ohm = 3V -> 0x0613 (Max))
  90.     ad_serial_2bytes = ad_serial_2bytes * 0.00488                                                # = ad_serial_2byte * 5 / 1024
  91.     vshunt.set(int(ad_serial_2bytes * 100) / 100)                                                # 1/1000以下を切り捨てた結果をテキストボックスへセット
  92.     print ('Vshunt(AN11) Volt =', ad_serial_2bytes)        # debug
  93.     # シャント電流の計算
  94.     isht = int(ad_serial_2bytes * 100) / 100                                                        # 1/1000以下を切り捨てた結果をテキストボックスへセット。 電圧(ad_serial_2bytes) / 抵抗(1ohm)
  95.     ishunt.set(isht)                                        
  96.     print ('Ishunt (Vshunt / 1) A = ', ad_serial_2bytes )        # debug
  97.     # 各電流毎のFET(2SJ334)のVds補正値 ※実測から設定
  98.     Vds = 0
  99.     if        isht <= 1:    Vds = 0.05
  100.     elif        1 < isht and isht <= 2:    Vds = 0.1
  101.     elif        2 < isht and isht <= 3:    Vds = 0.153
  102.     # Vds補正後の電源電圧の表示をセット
  103.     ad_serial_2bytes_vpw = 0.01953 * ad_serial_2bytes_vpw + Vds        # = ad_serial_2byte * 5 * 4 / 1024 + Vds (電源電圧20V(Max)の場合、読み取り電圧(Max)は1/4の5V)
  104.     vpower.set(int(ad_serial_2bytes_vpw * 100) / 100)                        # 1/1000以下を切り捨てた結果をテキストボックスへセット
  105.     print ('Vin(AN10) Volt =', ad_serial_2bytes_vpw)        # debug
  106.     # 電源電圧/シャント電圧/シャント電流 の表示
  107.     v_power.set(vpower.get())                    # 測定値Vpwをテキストボックスへセット
  108.     v_shunt.set(vshunt.get())                    # 測定値Vshuntをテキストボックスへセット
  109.     i_shunt.set(ishunt.get())                        # 計算結果Ishuntをテキストボックスへセット
  110.     ser.close()                                        # シリアルポートを閉じる。
  111.     print('Data get!! ')        # debug
  112.     print('\n')                #debug
  113.     return True
  114. ##############################################################################################################################################
  115. # 単発測定
  116. def Data_measurement():
  117.     global mode
  118.     current_data = entry_Current.get()                        # ユーザー入力値を変数に格納
  119.     dec_data = Check_entryCurrent(current_data)        # ユーザー入力値をMCP4018設定値へ変更
  120.     if dec_data == False:
  121.         mode = Stop_mode
  122.         return
  123.     serial_flg = Serial_com(dec_data)                            # シリアル通信/測定/表示の更新データセット
  124.     while serial_flg == False:{}                                    # シリアル通信/測定/表示の更新データセット が完了するまで待機
  125.     mode = Stop_mode                                            # Stopモードにセット ※注) 電流は最終値のまま流れ続ける。
  126. ##############################################################################################################################################
  127. # Sweep測定
  128. def Data_measurement_Sweep(current_data, step_current, max_count):
  129.     global mode
  130.     global step_time
  131.     global after_ID_Number
  132.     # Sweepモード1回目のみ実行する処理
  133.     if mode == Sweep_mode:
  134.         # Sweepモードの初回だけ、ユーザー入力値(目標電流、ステップ電流、ステップ時間)を取り込み、ローカル変数とグローバル変数に初期値として代入
  135.         current_data = entry_Current.get()                                # 電流値を取り込んで変数に格納(値のチェック後は、未使用)
  136.         dec_data = Check_entryCurrent(current_data)                # ユーザー入力値をMCP4018設定値へ変更 
  137.         if dec_data == False:
  138.             mode = Stop_mode
  139.             return
  140.         step_current = entry_Stepcurrent.get()                            # ユーザーの入力した電流増分を変数に格納
  141.         step_time = int(entry_Steptime.get()*1000)                    # ステップ時間(S)を(mS)に換算し、整数型へ変換しグローバル変数へ格納
  142.         if step_current == 0 or step_current*2 > current_data:        # ステップ電流が範囲内か確認
  143.             mode = Stop_mode
  144.             return
  145.         if step_time <= 0 or step_time > 10000:                            # ステップ時間が範囲内(0mSより上、 10000mS未満)か確認
  146.             mode = Stop_mode
  147.             return
  148.         max_count = int(current_data/step_current)                    # 測定を繰り返す回数を計算
  149.         current_data = 0                                                        # 電流初期値をセット。 NG判定値だが、0A状態を指定時間作る為にセットする。
  150.     # Sweepモード2回目以降も実行する処理
  151.     mode = Sweep_mode_running                                # Sweepモード継続中 にモードを変更
  152.     dec_data = Check_entryCurrent(current_data)        # ステップ電流を加算した後の値をMCP4018設定値に変換
  153.     serial_flg = Serial_com(dec_data)                            # シリアル通信/測定/表示更新データセット
  154.     while serial_flg == False:{}                                    # シリアル通信/測定/表示の更新データセット が完了するまで待機
  155.     current_data += step_current                                # ステップ電流値を加算
  156.     print('あと何回繰り返す? = ', max_count)                #debug
  157.     print('\n')                #debug
  158.     
  159.     if max_count == 0:
  160.         # 最大繰り返し回数に到達したら、afterメソッドの宣言を取り消す。
  161.         root_window.after_cancel(after_ID_Number)
  162.         mode = Stop_mode                                        # Stopモードにセット ※注) 電流は最終値のまま流れ続ける。
  163.     else:
  164.         max_count -= 1
  165.         # ステップ時間経過したら本関数を再度実行することを宣言し、root_windowループに処理を返す。windowループに返す事で、テキストラベルの表示が更新される。
  166.         after_ID_Number = root_window.after(step_time, lambda:Data_measurement_Sweep(current_data, step_current, max_count))    
  167. ##############################################################################################################################################
  168. # Startボタンの定義
  169. def click_Start_button():
  170.     global mode
  171.     if bln.get() == False and mode == Stop_mode:        # SweepチェックがOFFで STOPモードの場合 → 単発測定
  172.         mode = Single_mode
  173.         Data_measurement()                                        # 単発測定処理開始
  174.     elif bln.get() == True and mode == Stop_mode:        # SweepチェックがONで STOPモードの場合 → Sweep測定
  175.         mode = Sweep_mode
  176.         Data_measurement_Sweep(0,0,0)                        # Sweep測定処理開始
  177.     else:{}
  178.         # 何もしない。
  179. ##############################################################################################################################################
  180. # Stopボタンの定義
  181. def click_Stop_button():
  182.     global mode
  183.     if mode == Sweep_mode_running:
  184.         root_window.after_cancel(after_ID_Number)        # Sweepモードのafterメソッドの宣言を取り消す。
  185.     mode = Stop_mode                                            # Stopモードにセット
  186.     serial_flg = Serial_com(0)                                    # 最小電流値をセットし、シリアル通信/測定/表示の更新データセット
  187.     while serial_flg == False:{}                                    # シリアル通信/測定/表示の更新データセット が完了するまで待機
  188. ##############################################################################################################################################
  189. # Saveボタンの定義
  190. def click_Save_button():
  191.     global mode
  192. #########################未作成#########################
  193. ##############################################################################################################################################
  194. ############################################################### ここからメイン ####################################################################
  195. ##############################################################################################################################################
  196. # 表示ウィンドウの作成
  197. root_window = tkinter.Tk()
  198. root_window.title("Electric Load Tester")
  199. root_window.geometry("300x350")
  200. #ボタンの作成 3ヶ
  201. Run_button0=tkinter.Button(root_window, width=5, text="開始", command=lambda:click_Start_button())    
  202. Run_button0.place(x=30, y=10)
  203. Pause_button0=tkinter.Button(root_window, width=5, text="停止", command=lambda:click_Stop_button())    
  204. Pause_button0.place(x=100, y=10)
  205. Pause_button0=tkinter.Button(root_window, width=5, text="保存", command=lambda:click_Save_button())    
  206. Pause_button0.place(x=170, y=10)
  207. #ユーザー入力欄の作成と表示
  208. bln = tkinter.BooleanVar()
  209. entry_Current = tkinter.DoubleVar()
  210. entry_Stepcurrent = tkinter.DoubleVar()
  211. entry_Steptime = tkinter.DoubleVar()
  212. label = tkinter.Label(text = "負荷電流 Io        A (範囲:0.04〜3.0)")
  213. label.place(x=10, y=70)
  214. input_current = tkinter.Entry(root_window, textvariable = entry_Current, width = 5)            # ユーザー入力欄作成(入力値はentry_Currentに格納)
  215. input_current.grid(padx = 110, pady = 70)                                # ユーザー入力欄表示
  216. # Sweepモード用チェックボックスの作成と表示
  217. check_box = tkinter.Checkbutton(root_window, variable=bln, text = "Sweep Mode")
  218. bln.set(False)
  219. check_box.place(x=10, y=120)
  220. # Sweep設定用テキストボックスの作成と表示
  221. label = tkinter.Label(text = "ステップ電流         A (Min : 0.04 A)")
  222. label.place(x=10, y=140)
  223. input_StepCurrent = tkinter.Entry(root_window, textvariable = entry_Stepcurrent, width = 5)        # ステップ電流ユーザー入力欄作成(入力値はentry_Stepcurrentに格納)
  224. input_StepCurrent.place(x = 110, y=140)                                # ユーザー入力欄表示
  225. label = tkinter.Label(text = "ステップ時間        秒 (Max:10 秒)")
  226. label.place(x=10, y=170)
  227. input_StepTime = tkinter.Entry(root_window, textvariable = entry_Steptime, width = 5)        # ステップ時間ユーザー入力欄作成(入力値はentry_Steptimeに格納)
  228. input_StepTime.place(x = 110, y=170)                                    # ユーザー入力欄表示
  229. # 入力欄の初期入力値を消去
  230. input_current.delete(0, tkinter.END)
  231. input_StepCurrent.delete(0, tkinter.END)
  232. input_StepTime.delete(0, tkinter.END)
  233. # 測定値表示用テキストボックスの作成と表示
  234. v_power = tkinter.DoubleVar()
  235. v_shunt = tkinter.DoubleVar()
  236. i_shunt = tkinter.DoubleVar()
  237. vpower = tkinter.DoubleVar()
  238. vshunt = tkinter.DoubleVar()
  239. ishunt = tkinter.DoubleVar()
  240. label = tkinter.Label(text = "入力電圧 Vpw            V")    
  241. label.place(x=10, y=230)
  242. text_Vpower = tkinter.Entry(root_window, textvariable=v_power, width=10)    # 測定値Vpw表示欄作成
  243. text_Vpower.place(x = 110, y=230)                            # 測定値Vpw表示
  244. label = tkinter.Label(text = "シャント電圧 Vs            V")
  245. label.place(x=10, y=260)
  246. text_Vshunt = tkinter.Entry(root_window, textvariable=v_shunt, width=10)        # 測定値Vs表示欄作成
  247. text_Vshunt.place(x = 110, y=260)                            # 測定値Vs表示
  248. label = tkinter.Label(text = "シャント電流 Is            A")
  249. label.place(x=10, y=290)
  250. text_Ishunt = tkinter.Entry(root_window, textvariable=i_shunt, width=10)        # 測定値Is表示欄作成
  251. text_Ishunt.place(x = 110, y=290)                                # 測定値Is表示
  252. label = tkinter.Label(text = "Is = Vs / 1Ω")
  253. label.place(x=110, y=311)
  254. # MCP4018に対する初期設定
  255. serial_flg = Serial_com(0)        # 最小電流値をセットし、シリアル通信/測定/表示の更新データセット
  256. while serial_flg == False:{}        # シリアル通信/測定/表示の更新データセット が完了するまで待機
  257. print('MCP4018 is Ready!!')
  258. print('\n')                #debug
  259. # 繰り返し実行
  260. root_window.mainloop()            # ここで、表示が更新される。

R8C29用メインプログラム

  1. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // File名    :UART_Monitor
  3. // CPU型名    :R8C29
  4. // 作成日    :2021/02/24
  5. // 処理内容    :    
  6. //    PCからのUART信号をRxD0で受信し、そのデータをIICバスでMCP4018へ送信する。
  7. // AN10とAN11ポートで電圧を読み取り(それぞれ2バイトデータ)、シリアルでPCへ出力する。
  8. //
  9. //    AD変換50回(500uS待機含む)にかかる時間は25mS 実測約26mS
  10. //     = ( 33 / (20MHz / 4) + 500uS )* 50 (33 = サンプルホールド有り、10bitモード時)
  11.     
  12. // 使用するPort    :
  13. //            p1_0-p1_3        :AD (AN8-AN11)
  14. //            p4_2            :VREF (AD用) -> 5Vラインに接続すること。
  15. //            p1_4,p1_5        :UART0
  16. //            p3_4,p3_5        :IIC
  17. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  18. #include    "sfr_r829.h"
  19. #include    <Main_clock_init.h>
  20. #include    <wait_x.h>
  21. #include    <uart0_init.c>
  22. #include    <resi_init.h>                // レジスタ初期化ファイル
  23. #include    <iic.h>                        // IICバス初期設定ファイル
  24. #include    <AD_init.h>                    // ADレジスタ初期設定ファイル
  25. // 関数定義
  26. void            main(void);
  27. unsigned int    ad_read(unsigned char ad_port);
  28. void             uart_trans(unsigned int ad_dat);
  29. void            debug_port(void);
  30. // マクロ定義
  31. #define    MCP4018        0x2f    // MCP4018 device address
  32. #define    RESET        0xff    // MCP4018 RESET command
  33. #define bps            19200    // 転送レートを19200bpsに設定 ※これより上は、PCと通信できない。
  34. #define AN10        0b00000110
  35. #define AN11        0b00000111
  36. unsigned char resister_data;
  37. unsigned int ad_an10, ad_an11;
  38. unsigned char check_dat;                 // debug
  39. //////////////////////////////////////////////////////
  40. // メイン
  41. //////////////////////////////////////////////////////
  42. void main(void)
  43. {
  44.     Main_clock_init();            // メインクロック初期化
  45.     function_init();            // レジスタ初期化
  46.     iic_init();                    // IICバス 初期設定
  47.     uart0_set(bps);                // UART0初期設定    
  48.     AD_init();                    // AD初期設定 (10bitモード、単発、サンプルホールド)
  49.     debug_port();                // デバッグポート設定
  50.     // IICバスの通信速度を250kHzにセット
  51.     iccr1 &= 0b11110000;            // 上位4ビットをマスク
  52.     iccr1 |= 0b00001001;            // 下位4ビットにf1/80をセット(= 20MHz/80 = 250kHz)
  53.     iic_write(MCP4018, 0, RESET);    // MCP4018 ソフトウェアリセット
  54.     iic_write(MCP4018, 0, 0);        // シャント電流を最小値にセットする。
  55.     
  56.     while(1){
  57.         u0c1    |= 0b00000100;    // UARTO 受信許可 from PC (b2 = 1)
  58.         while(ri_u0c1 == 0);    // 1Byte受信完了まで待機
  59.         
  60.         // STOP_BITまで受信したら、u0rbレジスタに受信データを転送し、ri_u0c1フラグが1(データ有り)へ変化する。
  61.         // 受信バッファレジスタは 16bit単位で読み出す事 ※但し本Sourceでは上位8bitは未使用
  62.         resister_data = (unsigned char)u0rb;    // 受信バッファレジスタの下位8bitを保存    
  63.         u0c1 &= 0b11111011;                        // UARTO 受信禁止 from PC (b2 = 0)
  64.         iic_write(MCP4018, 0, resister_data);    // MCP4018へレジスタ値を出力
  65.         iic_read(MCP4018, 0, 1);                // デバッグ用 MCP4018からレジスタ値を読込
  66.         check_dat = iic_rcv_buff[0];            // デバッグ用 MCP4018から読み込んだレジスタ値が一致しているか値を確認
  67.         // ADポートの電圧を測定 (AD変換)し、UART送信する。
  68.         ad_an10 = ad_read(AN10);        // AN10ポートの電圧をAD変換
  69.         ad_an11 = ad_read(AN11);        // AN11ポートの電圧をAD変換
  70.         uart_trans(ad_an10);            // AN10ポートのAD変換値(2バイト)をUART送信する。
  71.         uart_trans(ad_an11);            // AN11ポートのAD変換値(2バイト)をUART送信する。
  72.     }
  73. }
  74. //////////////////////////////////////////////////////
  75. // ADポートの電圧を測定する。
  76. //////////////////////////////////////////////////////
  77. unsigned int ad_read(unsigned char ad_port)
  78. {
  79.     unsigned char i, count;
  80.     unsigned int ad_val, ad_sum, ad_max, ad_min;
  81.     count = 50;
  82.     ad_sum = 0;
  83.     // ad_portで指定されたポートの電圧を測定 (AD変換)
  84.     adcon0 &= 0b11111000;
  85.     adcon0 |= ad_port;            // AN1xポートを選択
  86.     p1 |=0b10000000;            // P1_7 Hi
  87.     for(i = 0; i<=count; i++){
  88.         if (i == 0){
  89.             ad_max = 0;
  90.             ad_min = 0;
  91.         }
  92.         adcon0 |= 0b01000000;    // AD変換開始    (b6 = 1)
  93.         while ( adst == 1 );    // AD変換完了(adst=0)まで繰り返し
  94.         ad_val = ad;            // AD値取り込み
  95.         adcon0 &= 0b10111111;    // AD変換停止    (b6 = 0)
  96.         
  97.         if( ad_val>ad_max )
  98.             ad_max = ad_val;    // Max値の取り込み
  99.         if( ad_val<ad_min )
  100.             ad_min = ad_val;    // Min値の取り込み
  101.         ad_sum += ad_val;
  102.         wait_x(5);            // 500uS待機
  103.     }
  104.     p1 &= 0b01111111;        // P1_7 Low      AD変換50回(500uS待機含む)にかかる時間は25.3mS 実測約26mS    
  105.     ad_val = (ad_sum-(ad_max)-(ad_min)) / (count -2);        // count回合計値-max値-min値の平均 / count回-2回(Max値の回とMin値の回 の2回)
  106.     return ad_val;    
  107. }
  108. //////////////////////////////////////////////////////
  109. // AD変換値(2バイト)をUART送信する。
  110. //////////////////////////////////////////////////////
  111. void uart_trans(unsigned int ad_dat)
  112. {
  113.     // 測定値(AD値2バイト)をUART送信
  114.     u0c1 |= 0b00000001;            // UART送信許可 (b0 =1)
  115.     u0tb = ad_dat >> 8;            // 上位1バイトをUART送信
  116.     while(ti_u0c1 == 0);        // 送信完了まで待機        
  117.     u0tb = ad_dat & 0x00ff;        // 下位1バイトをUART送信
  118.     while(ti_u0c1 == 0);        // 送信完了まで待機        
  119.     u0c1 &= 0b11111110;            // UART送信禁止 (b0 =0)
  120. }
  121. //////////////////////////////////////////////////////
  122. // デバッグ用 (処理時間測定用にP1_7を使用する。)
  123. //////////////////////////////////////////////////////
  124. void    debug_port(void)
  125. {
  126.     pd1 |= 0b10000000;        //P1_7 を出力設定
  127.     p1    &= 0b01111111;        //P1_7 をLow出力設定
  128. }

Hardware & Software
スポンサーリンク
シェアする
MTNブログ

コメント