PIC24 LCメーター プログラム

2017年1月24日

LC メーターのプログラムです。

Code Configurator対応のPICなら、どの種類でも同じです。使わなくても、画像の通りに設定するだけです。一部画像がありませんが。

32bitタイマーを使っていますが、ちらっとTimer5で16bitタイマーのコードが書かれています。

まずは作り方から。

プロジェクトを作って、MPLAB Code Configurator v3で「Generate」ボタンを押すと、Main関数から全部完成です。

Timer1の関数がありますが、Generateされたtmr1.cからのコピペです。元の方をコメントアウトします。

PIC18のCode Configuratorは割り込み関数の処理が違います。v3から同じなのかな。以前作ったものとは違いますので。

割り込み関数を自分で作って、tmr.cの関数を使い、呼び出すように登録します。

TMR2_SetInterruptHandler(MainTimerCallback);

こっちのほうがスマートなんですけどねー、なぜ24,32は違うんでしょ。

使い方

コンデンサ測定の表示はマイナスも表示するようにしてあります。起動したとき、いつもよりずれていたら、電源入れなおしを出来るようにするためです。

Timer5は使っていません。16bit、8bitタイマーの場合はこうやる感じです。

doubleで計算していますが、コンパイラの初期設定ではfloatです。本当にdoubleにしたいときは、コンパイルスイッチを変えるだけです。

/**
  Generated Main Source File

  Company:
    Microchip Technology Inc.

  File Name:
    main.c

  Summary:
    This is the main file generated using MPLAB(c) Code Configurator

  Description:
    This header file provides implementations for driver APIs for all modules selected in the GUI.
    Generation Information :
        Product Revision  :  MPLAB(c) Code Configurator - pic24-dspic-pic32mm : v1.25
        Device            :  PIC24FJ64GB002
        Driver Version    :  2.00
    The generated drivers are tested against the following:
        Compiler          :  XC16 1.26
        MPLAB             :  MPLAB X 3.45
*/

/*
    (c) 2016 Microchip Technology Inc. and its subsidiaries. You may use this
    software and any derivatives exclusively with Microchip products.

    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
    WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
    PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION
    WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.

    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
    BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
    FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
    ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
    THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.

    MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE
    TERMS.
*/

#include "system_config.h"
#include "mcc_generated_files/mcc.h"
#include <stdio.h>
#include "SC1602.h"

#define PI      3.1415926535897932384626433


static short mInt500msec = 0;
static short mTMR_OverFlow = 0;

static unsigned long mFrequency = 0;
static char mString[21];

static double mC1, mL1, mOpen, mClose;

void __attribute__ ((weak)) TMR5_CallBack(void)
{
    // Add your custom callback code here
    mTMR_OverFlow++;
}

// ----------------------------------------------------------------------------
//
void __attribute__ ((weak)) TMR1_CallBack(void)
{
    // Add your custom callback code here
    T1CONbits.TON = 0;

    mInt500msec = 1;
    
#if 1
    TMR4_Stop();
    mFrequency = TMR4_Counter32BitGet();
    TMR4_Counter32BitSet(0);
    TMR4_Start();
#else
    /*
    T5CONbits.TON = 0;
    mFrequency = TMR5 + (unsigned long)mTMR_OverFlow * 0xFFFFul;
    mTMR_OverFlow = 0;
    TMR5 = 0;
    T5CONbits.TON = 1;
    */
    TMR5_Stop();
    mFrequency = TMR5_Counter16BitGet() + (unsigned long)mTMR_OverFlow * 0xFFFFul;
    mTMR_OverFlow = 0;
    TMR5_Counter16BitSet(0);
    TMR5_Start();
#endif
    T1CONbits.TON = 1;
}

void Calc(void)
{
    double n;
    
    n = mOpen / mFrequency;
    n = n * n -1;
    if(LC_MODE() == C_MODE) {
        n = n * mC1;
        if(mFrequency < 50) {
            // 発振していない
            sprintf(mString, "       -.---pF");
        }
        else if(n < 0) {
//            sprintf(mString, "% 14.3fpF", 0);
            // いつもよりずれていたら電源入れなおし
            sprintf(mString, "% 14.3lfpF", n);
        }
        else if(n > 1000) {
            sprintf(mString, "% 14.6lfuF", n / 1000000);
        }
        else {
            sprintf(mString, "% 14.3lfpF", n);
        }
    }
    else {
        n = n * mL1;
        if(mFrequency < 50) {
            // 発振していない
            
            sprintf(mString, "         -.---uH");
        }
        else {
            sprintf(mString, "% 14.3lfuH", n * 1000000.0); // pHからuHにする
        }
    }
    SC1602_WriteString(0, 1, mString);
}

void Calibrate(void)
{
    double a1, a2;
    
    a1 = mOpen * mOpen;
    a2 = mClose * mClose ;
    mC1 = (a2 * 1000) / (a1 - a2);
    // mL1 = 1000000000000.0 / (4.0 * PI * PI * a1 * mC1);
    // Hz で計算
    mL1 = (1000000.0 * 1000000.0) / (4.0 * PI * PI * 4.0 * a1 * mC1);
}

void PrintLine1(void)
{
    if(LC_MODE() == C_MODE) {
        SC1602_WriteString(0, 0, "C MODE");
    }
    else {
        SC1602_WriteString(0, 0, "L MODE");
    }
//    sprintf(mString, "Count:0x%04x%04x", 
//                (unsigned short)(mFrequency >> 16), (unsigned short)mFrequency);
    sprintf(mString, "%8ldHz", mFrequency * 2);
    SC1602_WriteString(6, 0, mString);
}

void LC_Calc(void)
{
    static int boot_count = 20;
    
    PrintLine1();
    
    if(boot_count == 20) {
        if(LC_MODE() != C_MODE) {
            SC1602_WriteString(0, 1, "PLZ SW C Mode   ");
        }
        else {
            SC1602_WriteString(0, 1, "Calibrating...  ");
            boot_count--;
        }
        RELAY_OFF();
    }
    else if(boot_count == 11) {
        boot_count--;
        mOpen = mFrequency;
        RELAY_ON();
    }
    else if(boot_count == 1) {
        boot_count--;
        mClose = mFrequency;
        Calibrate();
        RELAY_OFF();
    }
    else if(boot_count == 0) {
        Calc();
    }
    else {
        boot_count--;
    }
}

/*
                         Main application
 */
int main(void)
{
    // initialize the device
    SYSTEM_Initialize();
   
    __delay_ms(500);
    
    SC1602_Initialize();
    
    SC1602_WriteString(0,0,"                ");
    SC1602_WriteString(0,1,"                ");

    while (1)
    {
        // Add your application code
        if(mInt500msec) {
            mInt500msec = 0;
            ToggleLED();
            LC_Calc();
        }
    }

    return -1;
}
/**
 End of File
*/
// TODO Insert declarations
#define RELAY               LATAbits.LATA4
#define RELAY_ON()          RELAY = 1
#define RELAY_OFF()         RELAY = 0

#define RunLED              LATBbits.LATB5
#define ToggleLED()         RunLED = ~RunLED

#define L_MODE              0
#define C_MODE              1
#define LC_MODE()           PORTBbits.RB4