うごく

Dependencies:   mbed

main.cpp

Committer:
maxonK
Date:
2015-05-09
Revision:
2:ad8fad576e79
Parent:
1:f50a49407c60

File content as of revision 2:ad8fad576e79:


#include <mbed.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

//文字列受信関数プロトタイプ宣言
int stringReceive();
//float cramp関数プロトタイプ宣言
int cramp(int,int,int);
//serialハードウェアバッファクリア関数プロトタイプ宣言
void bufferClear ();

//dp4pwm初期化関数プロトタイプ宣言
void CT32B0_MAT3_PWM_registerSet(unsigned int );
//グローバル変数宣言
//dp4pwmDuty
unsigned int dp4pwmDuty = 0;
//dp4pwmFrequency
unsigned int dp4pwmFrequency = 0;


DigitalOut myled(LED1);
//タイムアウトタイマー初期化
Timer timeOutTimer;

//シリアル初期化
Serial sensSerial (dp16, dp15);
/*
//I2C初期化
I2C i2c(dp5 , dp27 ); //sda scl
const int addr = 0x20 << 1; // I2C address
*/

//割り込みハンドラ(PICでいうISRのこと)
void TIMER32_0_IRQHandler(void)
{
    //タイマー操作
    //タイマリセット→保持
    //タイマ制御レジスタアドレス
    volatile unsigned int *TMR32B0TCRLocal = (unsigned int *)0x40014004;
    //1ビット目を1にしてタイマリセット
    unsigned int mask_TMR32B0TCR = 1 << 1;
    //タイマ制御レジスタセット
    *TMR32B0TCRLocal |= mask_TMR32B0TCR;
    /***********************************************************************************/
    //マッチレジスタセット
    //新しくセットする値はグローバルで宣言しとく(割り込みハンドラは、引数、戻り値ともに意味を成さない)
    //0~1023もらって0%~100%のpwm出力する
    //CT32B0_MAT3に対応したマッチレジスタアドレス
    volatile unsigned int *TMR32B0MR3 = (unsigned int *)(0x40014024);
    //デューティセット
    *TMR32B0MR3 = ((((48000000 / dp4pwmFrequency)/20)*18)+((((48000000 / dp4pwmFrequency)/20)/1024) * (1024 - dp4pwmDuty)));//停波(18ms)+((1ms/1024)*(1024-Duty))
    //*TMR32B0MR2 = (((48000000 / dp24pwmFrequency) / 1024)*(1024 - dp24pwmDuty));
    /*******************************************************************************************/

    //タイマリセット解除
    //タイマ制御レジスタセット
    *TMR32B0TCRLocal &= ~mask_TMR32B0TCR;
    /*******************************************************************************************/

    //マッチチャネル0 用の割り込みフラグリセット
    //割り込みレジスタアドレス
    volatile unsigned int *TMR32B0IRLocal = (unsigned int *)0x40014000;
    //0ビット目を1にしてMR0の割り込みフラグをリセット
    unsigned int mask_TMR32B0IR = 1;
    //割り込みレジスタセット
    *TMR32B0IRLocal |= mask_TMR32B0IR;

}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*****************************************************************************************************************/

int main()
{
    //setup
    sensSerial.baud(9600);//シリアル通信開く
    //(switchmbed基板でUSB通信するときは低速に抑えること)
    myled = 0;

    //割り込み設定
    //Interrupt Service Routineが書いてある、割り込み時ジャンプ先アドレス設定?
    NVIC_SetVector(TIMER_32_0_IRQn, (uint32_t)&TIMER32_0_IRQHandler);
    //割り込みハンドライネーブル
    NVIC_EnableIRQ(TIMER_32_0_IRQn);
    //割り込み優先順位設定
    NVIC_SetPriority(TIMER_32_0_IRQn, 1);
    //PWM周波数
    dp4pwmFrequency = 50;
    //dp4pwm初期化
    CT32B0_MAT3_PWM_registerSet(dp4pwmFrequency);

    //ESCのセンター感知のため中立サーボ信号を5秒間出力
    //pwm関係
    //グローバルdp4pwmDutyセット
    dp4pwmDuty = (1024 / 2);
        //pwm周波数設定用マッチレジスタの動作をタイマークリアから割り込み発生へ変更
        //マッチ制御レジスタアドレス
        volatile unsigned int *TMR32B0MCR = (unsigned int *)(0x40014014);
        //マッチ制御レジスタマスク
        //マッチレジスタMR0とのマッチで割り込みが発生するように機能切り替え//マッチでのクリアは停止される
        unsigned int mask_TMR32B0MCR = 1;
        //マッチ制御レジスタセット
        *TMR32B0MCR = mask_TMR32B0MCR;
        //待ち
        wait(5);

    /***************************************************************************/
    //mainloop
    while(1) {
        int receiveVal = 0;
        static int sReceiveVal = 0;
        int gain = 10;
        receiveVal = stringReceive();


        if(receiveVal >= 0) {
            myled = !myled;

            //pwm関係
            //グローバルdp4pwmDutyセット
            dp4pwmDuty = cramp((( receiveVal*gain ) - (((1023*gain)/2)-(1023/2)) ),0,1023);
            //dp24pwmDuty = cramp((( receiveVal*gain ) - (((1023*gain)/2)-(1023/2)) - (512 - 76) ),51,102);
            //dp24pwmDuty = receiveVal;

            if(receiveVal != sReceiveVal) {
                sReceiveVal = receiveVal;
                //pwm周波数設定用マッチレジスタの動作をタイマークリアから割り込み発生へ変更
                //マッチ制御レジスタアドレス
                volatile unsigned int *TMR32B0MCR = (unsigned int *)(0x40014014);
                //マッチ制御レジスタマスク
                //マッチレジスタMR0とのマッチで割り込みが発生するように機能切り替え//マッチでのクリアは停止される
                unsigned int mask_TMR32B0MCR = 1;
                //マッチ制御レジスタセット
                *TMR32B0MCR = mask_TMR32B0MCR;
            }
            /*
            //I2C送信
            char cmd[10] = {'\0'};//I2C送信バッファ
            //int to asic2(sprintf関数)
            sprintf(cmd ,"%4d",dp4pwmDuty);//格納する配列アドレス , 書式文字列
            //null終端
            cmd[sizeof(cmd) - 1] = '\0'; // NULL 終端する
            //書き出し
            i2c.write(addr, cmd, 7);
            */
        }

    }
    /****************************************************************************/

}

/*****************************************************************************************************************/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//受信関数
//受信完了時0~4095
//タイムアウト検出用のタイマーをグローバルで初期化する必要あり
//Timer timeOutTimer;
int stringReceive()
{
    //各種定数
    //正常なデータ長,書き込み位置大きくなりすぎていないかチェック用
    const int dataLength = 7;//7個(6個のデータ+null終端)(添字は0~ 宣言時の大きさは1~)(添字の位置確認時は-1する)
    //startbitに使用する文字
    char startbitChar = '*';
    //stopbitに使用する文字
    char stopbitChar = '#';
    //各種変数
    //現在書き込むべきバッファの位置変数
    static int stringPosition = 0;
    //受信値一時格納変数
    char receiveChar = '\0';
    //受信データ格納バッファ文字列
    static char receiveDataString [dataLength] = {'\0'};//7個
    //データ送信要求フラグ
    static bool Cflag = true;
    //関数内セットアップルーチン実行staticフラグ
    //はじめてこの関数が呼ばれたときだけ実行される
    static bool setup = false;
    if(!setup){
        timeOutTimer.start();
        Cflag = true;
        setup = true;
        }

    //タイムアウトによるデータ送信要求フラグセット
    if(timeOutTimer.read() >= 1){
        Cflag = true;
        }

    //データ送信要求
    //sensSerial.putc('C');
    if(Cflag){
        sensSerial.putc('C');
        Cflag = false;
        //タイマリセット
        timeOutTimer.stop();
        timeOutTimer.reset();
        timeOutTimer.start();
        }
    
    
    //ハードウェアバッファに到着した情報があるか
    //空ならリターン、あるなら受信値格納用変数にうつす
    if(!sensSerial.readable()) {
        //空のとき
        return -1;
    } else { //あるとき
        receiveChar = sensSerial.getc();
    }
    //バッファ書き込み位置変数が大きくなりすぎている
    //(ストップビットがくるはずがきてない)ときリターン
    if(stringPosition > (dataLength - 2)) {
        stringPosition = 0;
        //ハードウェアバッファクリア
        bufferClear();
        return -2;
    }

    //到着していたデータがスタートビットだった場合
    if(receiveChar == startbitChar) {

        //バッファクリア
        for (int i = 0; i < dataLength; i++) { //配列の要素は0~ 大きさは1~
            receiveDataString[i] = '\0';
        }
        //書き込み位置変数クリア
        stringPosition = 0;
        //バッファへ書き込み
        receiveDataString[stringPosition] = receiveChar ;


        //書き込み位置進め
        stringPosition ++;
        //-1リターン
        return -3;
    }

    //到着していたデータが数字だった場合
    if(receiveChar=='0'||receiveChar=='1'||receiveChar=='2'||receiveChar=='3'||receiveChar=='4'||receiveChar=='5'||receiveChar=='6'||receiveChar=='7'||receiveChar=='8'||receiveChar=='9') {
        //バッファへ書き込み
        receiveDataString[stringPosition] = receiveChar ;

        //書き込み位置進め
        stringPosition++;
        //-1リターン
        return -4;
    }

    //到着していたデータがストップビットだった場合
    if(receiveChar == stopbitChar) {
        //使う変数宣言
        //バッファ内容をコピーするための文字列
        char copyString [dataLength] = {'\0'};
        //スタート、ストップビットをトリムしたデータだけの文字列
        char trimString [dataLength] = {'\0'};
        //文字列→数値変換後の値を格納する変数
        int intVal = 0;

        //バッファへ書き込み
        receiveDataString[stringPosition] = receiveChar ;
        //null終端
        copyString[sizeof(copyString) - 1] = '\0'; /* NULL 終端する */
        receiveDataString[sizeof(receiveDataString) - 1] = '\0';//null終端


        //バッファの内容をうつす
        strlcpy(copyString,receiveDataString,sizeof(copyString));
        //バッファクリア
        for (int i = 0; i < dataLength; i++) { //配列の要素は0~ 大きさは1~
            receiveDataString[i] = '\0';
        }
        //ハードウェアバッファクリア
        bufferClear();
        //書き込み位置クリア
        stringPosition = 0;

        //以下チェックとAtoI
        //先頭がスタートビットになってるか
        if(!(copyString[0] == startbitChar)) {
            return -5;
        }
        //末尾がストップビットになっているか(配列の最後はnull)
        if(!(copyString[(dataLength - 2)] == stopbitChar)) {
            return -6;
        }
        //データだけをトリミング
        //1個目から、後ろから2個目まで*xxxx#(\n)
        for(int Idx = 1; Idx < (dataLength - 2) ; Idx++) {
            trimString[(Idx - 1) ] = copyString[Idx];
        }
        //null終端
        trimString[sizeof(trimString) - 1] = '\0'; /* NULL 終端する */
        //文字列→数値
        intVal = atoi(trimString);
        //送信要求フラグセット
        Cflag = true;
        //数値リターン
        return intVal;

    }


    //以上にひっかからなかった異常時
    //バッファクリア
    for (int i = 0; i <dataLength; i++) { //配列の要素は0~ 大きさは1~
        receiveDataString[i] = '\0';
    }
    //ハードウェアバッファクリア
    bufferClear();
    //書き込み位置クリア
    stringPosition = 0;
    //-3リターン
    return -7;
}


//cramp関数
int cramp(int val , int min , int max)
{
    if(val < min) {
        return min;
    }
    if(val > max) {
        return max;
    }

    return val;
}

//serialハードウェアバッファクリア関数
void bufferClear()
{
    char temp = 0;
    while(sensSerial.readable()) {
        temp = sensSerial.getc();
    }
    return;
}






void CT32B0_MAT3_PWM_registerSet(unsigned int pwmFrequency)
{
    //PWM機能設定用
    //pwmピンのピン機能選択をmbedで行う
    //PwmOut MAT2(dp24);//CT32B0_MAT2
    //PWM周波数
    //unsigned int pwmFrequency = 4;
    //各種レジスタ設定用ビットマスク
    //システムAHBクロック制御レジスタマスク
    unsigned int mask_SYSAHBCLKCTRL = 0x3 << 9;
    //IO設定レジスタレジスタマスク
    unsigned int mask_IOCON_PIO0_11 = 0x3;
    //タイマ制御レジスタマスク
    //0ビット目を1にしてタイマ、プリスケールカウンタをイネーブルへ
    unsigned int mask_TMR32B0TCR = 1;
    //プリスケールレジスタマスク
    unsigned int val_TMR32B0PR = 0;
    //マッチ制御レジスタマスク
    //0~3番のマッチレジスタの、PWM出力ピンにしたい番号以外のどれか1つをタイマ・カウンタ(TC)リセット用に設定する
    //残りのマッチレジスタはディスエーブルにする
    //mbedのピン配列ではタイマ0は0番をTCリセットに使うといいかも
    unsigned int mask_TMR32B0MCR = 1 << 1;
    //PWM制御レジスタマスク
    //1つのタイマブロックで同時に、異なるデューティで動作できるPWMは3つまで
    //CT32Bn_MATxピンの、TCリセットに使っていない番号のどれをPWMピンにするか選択して、ビットを1にする
    //mbedではMAT2がpwmOutになってるがISPモードに使用しているので、dp4-MAT3を試す
    unsigned int mask_TMR32B0PWMC = 1 << 3;
    //マッチレジスタ値
    //・マッチ制御レジスタでTCリセット用に設定したマッチレジスタに、周期を設定する
    // ((48*10^6)/nHz)で任意の周波数になる、はずである
    //・マッチ制御レジスタでTCリセット用に設定しなかったマッチレジスタで、PWM出力ピンにする番号のマッチレジスタにパルス長を設定する
    // ここでいうパルス長は、LOWレベルの長さになる。 0で常にHIGH,TCリセット値より大きいと常にLOW,TCリセット値と等しい場合は完全にはLOWにならない
    unsigned int val_TMR32B0MR0 = /*10;*/((48000000) / (pwmFrequency));
    unsigned int val_TMR32B0MR3 = /*8;*/((48000000) / (pwmFrequency)) + 1;

    //システムAHBクロック制御レジスタアドレス
    volatile unsigned int *SYSAHBCLKCTRLLocal = (unsigned int *)0x40048080;
    //IO設定レジスタアドレス
    volatile unsigned int *IOCON_PIO0_11Local = (unsigned int *)0x40044074;
    //プリスケールレジスタアドレス
    volatile unsigned int *TMR32B0PRLocal = (unsigned int *)0x4001400C;
    //タイマ制御レジスタアドレス
    volatile unsigned int *TMR32B0TCR = (unsigned int *)(0x40014004);
    //マッチ制御レジスタアドレス
    volatile unsigned int *TMR32B0MCR = (unsigned int *)(0x40014014);
    //マッチレジスタ0アドレス
    volatile unsigned int *TMR32B0MR0 = (unsigned int *)(0x40014018);
    //マッチレジスタ3アドレス
    volatile unsigned int *TMR32B0MR3 = (unsigned int *)(0x40014024);
    //PWM制御レジスタアドレス
    volatile unsigned int *TMR32B0PWMC = (unsigned int *)(0x40014074);

    //PWM機能制御レジスタセット
    //システムAHBクロック制御レジスタセット
    *SYSAHBCLKCTRLLocal |= mask_SYSAHBCLKCTRL;
    //IO設定レジスタセット
    *IOCON_PIO0_11Local |= mask_IOCON_PIO0_11;
    //プリスケーラレジスタセット
    *TMR32B0PRLocal = val_TMR32B0PR;
    //PWM制御レジスタセット
    *TMR32B0PWMC |= mask_TMR32B0PWMC;
    //マッチレジスタセット
    //デフォルト値設定操作
    //MR0_周波数
    *TMR32B0MR0 = val_TMR32B0MR0;
    //MR3_LOWパルス長
    *TMR32B0MR3 = val_TMR32B0MR3;
    //マッチ制御レジスタセット
    *TMR32B0MCR |= mask_TMR32B0MCR;
    //タイマ制御レジスタセット
    *TMR32B0TCR |= mask_TMR32B0TCR;
}