古い時代からあるシリアル通信のひとつであるUARTは双方の機器においてデータのやりとりの方法を事前に知っておかなければならない、現在の基準から見ると通信速度が遅いなどの理由により、今では別の手段、とくにパソコンではUSBに取って代わられました。一方で、最低2本の信号線があればやりとりが可能というシンプルさより、特別なデバッグツールなしにマイコンの内部処理をパソコンで調べたいときなどに、この通信方法が使われています。

PIC32ではいくつかの決められたピンの中から通信用に割り当てることができます。これはデータシートの「Peripheral Pin Select」で確認でき、「UnRXR」「UnRTX」のレジスタで指定できます。28ピン版では「A2,B6,A4,B13,B2」のいずれかをUART1のRXに、「A1,B5,B1,B11,B8」をUART2のRXに指定できます。
U1RXRbits.U1RXR = 0b0100; // B2ピンをUART1・RXに割り当て
/*
0000 = RPA2
0001 = RPB6
0010 = RPA4
0011 = RPB13
0100 = RPB2
*/
TXでは「A0,B3,B4,B15,B7」をUART1に、「A3,B14,B0,B10,B9」をUART2に割り振れます。

出力であるTXは「RXに○ピンを割り当てる」という先の指定方法とは逆で、「○ピンにTXを割り当てる」という命令を記述します。
RPB3Rbits.RPB3R = 0b0010; // B3にTXコードを割り当てる
速度を決めるためのボーレート設定レジスタ「UnBRG」の値は、周辺クロック数に基づいて「PBCLK/(16*baud)-1」という式で計算します。たとえば周辺クロックが20MHz、通常ボーレートモード(UxMODEbits.BRGH=0)においてボーレートを115200にしたい場合は、「20000000/(16*115200)-1=9.8」となります。プログラムでは近似値の10を指定することになるので、実行時には若干の誤差が発生します(データの送信ごとに同期し直されるので、誤差が5%未満であれば、データへの影響はありません)。

「UxSTAbits.UTXEN=1」にすると送信が、「UxSTAbits.URXEN = 1」にすると受信が受け付けられます。「UxSTAbits.UTXBA=0」であれば、送信バッファに空きがあるので「UxTXREG」にデータを代入して送信します。受け取ったデータが存在する場合、「UxSTAbits.URXDA=1」になっているので、「UxRXREG」から取得します。

こちらはUARTシリアル通信のサンプルです。この例ではArduino UnoをUSBシリアル変換ケーブルの代わりに使用しています(スケッチは不要。やりかたはこちら)。PIC32のRB3をArduinoのRXに、RB4をTXピンに接続してください。
#include <p32xxxx.h>
#include <sys/attribs.h>

// 外部の8MHz水晶発振器から40MHzのクロックを生成するための設定
#pragma config FNOSC = PRIPLL // 発信源 = 主外部発振器
#pragma config POSCMOD = XT // 主発振の方法 = 外部高精度発振器を使う
#pragma config FPLLIDIV = DIV_2 // PLL入力分数 = x1/2
#pragma config FPLLMUL = MUL_20 // PLL逓倍比 = x20
#pragma config FPLLODIV = DIV_2 // PLL出力分数 = x1/2
#pragma config FPBDIV = DIV_2 //周辺モジュールクロック倍数 : x1/2

char str[51]; int sp = 0;

void sendString(const char *s, int slen)
{
    int i;
     for(i = 0; i < slen; i++){
        U1TXREG = s[i];
        while(U1STAbits.UTXBF) ; // バッファに空きが出るまで待機
    }
}

void __ISR(_UART_1_VECTOR, IPL4AUTO) OnUartReceiving(void) 
{
    IFS1bits.U1RXIF = 0; // UART1受信フラグのリセット

    if(U1STAbits.URXDA == 0) return; // バッファが空の状態なら何もしない
    str[sp] = (char)U1RXREG; // 受信データバッファのデータを格納
    
    // 改行コードを受信するかバッファがいっぱいになったら
    if(str[sp] == '\n' || sp > 50){
        // 受け取ったデータをそのまま返す
        sendString(str, sp + 1);
        sp = 0;
    }else{
        sp++;
    }
}

int main(void)
{
    ANSELB = 0x00;        // ポートBをすべてデジタルモードにする

    U1RXRbits.U1RXR = 0b0100; // UART1/RXにB2を
    RPB3Rbits.RPB3R = 0b0001; // B3をUART1/TXに
    
    U1STAbits.UTXEN = 1;  // UART1の送信を有効
    U1STAbits.URXEN = 1;  // UART1の受信を有効
    U1BRG = 129;          // ボーレート9600 [20M/(16*9600)-1]
    
    U1MODEbits.ON = 1;   // UART1を有効
    IPC8bits.U1IP = 4;   // UART1優先割り込み度
    IPC8bits.U1IS = 3;   // UART1副優先度
    
    IFS1bits.U1RXIF = 0; // UART1受信フラグのリセット
    IFS1bits.U1TXIF = 0; // UART1送信フラグのリセット
    
    IEC1bits.U1RXIE = 1; // UART1受信完了割り込みを有効
    IEC1bits.U1TXIE = 0; // UART1送信完了割り込みを無効
    
    INTCONbits.MVEC = 1;  // マルチベクタ割り込みを有効にする
       
    __builtin_enable_interrupts();  // マイコンにおける割り込みの有効

    sendString("Hello!\n", 7);

    while(1) ;
}
Arduino IDEを開いて、シリアルモニタよりArduinoのCOMポートを開きボーレートに「9600 bps」を指定してPICよりプログラムを実行すると、はじめに文字列が表示されます。あとは、Arduino IDEから任意の文字列を送信すると、全く同じ文字列がPICから返され、シリアルモニタにその内容が表示されます。
また、XC32コンパイラではprintf()を使うことができ、「__XC_UART」で出力先のUARTピンを指定すると、マイコン側で文字列のフォーマットと送信を一度に行えます。
#include <stdio.h>

int main(void)
{
    __XC_UART = 1;
    U1RXRbits.U1RXR = 0b0100;
    RPB3Rbits.RPB3R = 0b0001;
    
    U1STAbits.UTXEN = 1;
    U1STAbits.URXEN = 1;
    U1BRG = 129;
    
    U1MODEbits.ON = 1;
    
    printf("Hello, world!\n");
    while(1);
}
 | 2018年9月26日

前回のタイマープログラムでPIC32マイコンの割り込み処理の基本を学んでいれば、ほかの種類の割り込みをプログラミングするのも難しくありません。今回はピンの状態が変化したときに割り込み処理が発生するプログラムを作ってみましょう。

状態変化検出モジュールによる割り込み関数を実行するには、以下の設定をすべて有効にします。


PIC32MX1XX/2XXの場合、ポートB状態変化検出モジュールのベクタ番号は34番(_CHANGE_NOTICE_VECTOR)となります。また、割り込み優先度は「IPC8bits」の「CNIP」および「CNIS」で定義します。

タクトスイッチに連動してLEDが点灯するサンプルプログラムを記述します。
マイコン内部には抵抗が組み込まれているので、「CNPUxbits.CNPUxn」で対象ピンのプルアップ抵抗を有効にすると、スイッチ回路に外部抵抗を継ぎ足すことなく、安定した情報を取得できます。
#include <p32xxxx.h>
#include <sys/attribs.h>

// 外部の8MHz水晶発振器から40MHzのクロックを生成するための設定
#pragma config FNOSC = PRIPLL // 発信源 = 主外部発振器
#pragma config POSCMOD = XT // 主発振の方法 = 外部高精度発振器を使う
#pragma config FPLLIDIV = DIV_2 // PLL入力分数 = x1/2
#pragma config FPLLMUL = MUL_20 // PLL逓倍比 = x20
#pragma config FPLLODIV = DIV_2 // PLL出力分数 = x1/2
#pragma config FPBDIV = DIV_1 //周辺モジュールクロック倍数 : x1/1

// 割り込みレベル4、34番(ポートB入力変化)ベクタ
void __ISR(_CHANGE_NOTICE_VECTOR, IPL4AUTO) OnPortChanged(void) 
{
    LATBbits.LATB0 = ~PORTBbits.RB1;
}

int main(void)
{
    ANSELB = 0x00;        // ポートBをすべてデジタルモードにする
    TRISBbits.TRISB0 = 0; // B0を出力にする
    PORTBbits.RB0 = 0;    // B0 = off
    
    TRISBbits.TRISB1 = 1; // B1を入力にする
    PORTBbits.RB1 = 1;    // B1の初期状態を設定
    
    INTCONbits.MVEC = 1;  // マルチベクタ割り込みを有効にする

    CNCONBbits.ON = 1;    // ポートBの状態変化検出モジュールを使用
    CNENBbits.CNIEB1 = 1; // B1の検出を有効
    CNPUBbits.CNPUB1 = 1; // B1のプルアップ抵抗を使用
    
    IPC8bits.CNIP = 4;    // 割り込み優先度(0-7)
    IPC8bits.CNIS = 3;    // 副優先度(0-3)
    IFS1bits.CNBIF = 0;   // 割り込みフラグをリセット
    IEC1bits.CNBIE = 1;   // 状態変化Bの割り込みを許可
       
    __builtin_enable_interrupts();  // マイコンにおける割り込みの有効

    while(1) ;
}
 | 2018年9月25日

PIC32マイコンのタイマーは指定したクロック(分周比)ごとにタイマーレジスタの値が増えていき、一定の値になると0に戻るとともに割り込みフラグレジスタ(IFS0)がセットされます。ループ中に加算されたタイマー値を計算して経過を時間調べることもできますが、もっぱら割り込みによって呼び出された関数(割り込みサービスルーチン:ISR)で個別の処理をするのが一般的です。

PIC32ではすべての割り込み処理を同じ関数で呼び出すシングルベクタと、割り込みごとに異なる関数で呼び出すマルチベクタがあります。シングルベクタよりもマルチベクタの方が処理が早く、また、関数内で条件分岐させるよりも関数ごとに分けた方がコードの可読性が高いので、シングルベクタが使われることはあまりありません。

PIC32MXにはタイマー1からタイマー5まで用意されています。タイマー1は16bitが上限で副発振回路でのカウントができます。一方で2~5は副発振回路は使えませんが2と3、もしくは4と5を組み合わせることで32bit値でカウントすることができます。

では、タイマー関連の設定をプログラムしてみましょう。タイマーの速度(クロック数)はPBCLKの分周比で決まるため、外部発振器を使用した場合は、FPBDIVの値も定義する必要があります。
#pragma config FPBDIV = DIV_1 //周辺モジュールクロック倍数 : x1/1
この場合はタイマーもCPUクロックと同じ周波数で動作しますが、これをDIV_2にするなどして周波数を落とすと消費電力の削減を図ることができます。

タイマー1の設定はT1CONレジスタに書き込みます。
T1CONbits.TCS   : 対象クロック (0=内部,1=外部)
T1CONbits.TSYNC : 外部クロック時の同期 (0=非同期,1=同期)
T1CONbits.TCKPS : プリスケーラ設定 (0=1,1=8,2=64,3=256)
T1CONbits.TGATE : 内部クロック時のゲート[T1CKピンがHighのときだけカウントするか] (0=無効,1=有効)
T1CONbits.TWIP  : 非同期書き込み中かどうかを調べる (0=完了している,1=処理中である)
T1CONbits.TWDIS : 非同期時の書き込みの許可 (0=許可,1=許可しない)
T1CONbits.SIDL  : アイドル中の動作 (0=動作を続行,1=停止させる)
T1CONbits.ON    : タイマーの実行 (0=中断,1=実行)
「T1CONbits.ON = 1」でタイマーが稼働し、TMR1の値がPR1に設定した値までカウントが増えるとTMR1が0にリセットされるとともに割り込みが発生します。TCKPS値を増やすと、1カウントされるまでの間隔が倍増するので、例えばモジュールクロック40MHzの状況で100msごとに発生させたい場合は「250ns(1/40MHz) * 256(T1CONbits.TCKPS = 3) * 15625(PR1 = 0x3D09) = 100ms」と計算します。

タイマー1による割り込みを有効にするには、プログラム全体での割り込み処理を使用する関数「__builtin_enable_interrupts()」を記述して「IEC0bits.T1IE = 1」をセットします。この状態でマイコン内部の処理によって「IFS0bits.T1IF」の0だった値が1になるとタイマー1モジュール(ベクタ番号4)を指定した関数が呼び出されます。タイマーを繰り返したい場合、T1IFは手動(プログラム内)で0にして再び受け入れられるようにします。

割り込みの優先度は「IPC1bits.T1IP(7で最優先、0で割り込みをしない)」および「IPC1bits.T1IS(副優先。先の優先が同じレベルならこの値の大きい方[0~3]が優先される)」で指定します。

割り込み関数を定義するにはXC32コンパイラの場合、関数名の前に「割り込み優先度○の○番ベクタ」であることを宣言します。今回は「割り込みレベル4、4番ベクタ(_TIMER_1_VECTOR)」なので下記のようになります。
void __attribute__((interrupt(IPL4AUTO))) __attribute__((vector(4))) OnTimer1(void){}
「#include <sys/attribs.h>」をインクルードすれば、__ISRマクロで簡潔に記述することができます。
void __ISR(_TIMER_1_VECTOR, IPL4AUTO) OnTimer1(void){}
以上を集約したプログラム例がこちらになります。回路図は「PIC32でシンプルなLチカをやってみる」と同じです。
#include <p32xxxx.h>
#include <sys/attribs.h>

// 外部の8MHz水晶発振器から40MHzのクロックを生成するための設定
#pragma config FNOSC = PRIPLL // 発信源 = 主外部発振器
#pragma config POSCMOD = XT // 主発振の方法 = 外部高精度発振器を使う
#pragma config FPLLIDIV = DIV_2 // PLL入力分数 = x1/2
#pragma config FPLLMUL = MUL_20 // PLL逓倍比 = x20
#pragma config FPLLODIV = DIV_2 // PLL出力分数 = x1/2
#pragma config FPBDIV = DIV_1 //周辺モジュールクロック倍数 : x1/1

unsigned char toggle = 0, count = 0;

// 割り込みレベル4、4番ベクタ(Timer1に該当)
void __ISR(_TIMER_1_VECTOR, IPL4AUTO) OnTimer1(void) 
//void __attribute__((interrupt(IPL4AUTO))) __attribute__((vector(4))) OnTimer1(void)
{
    IFS0bits.T1IF = 0; // 割り込みフラグをリセット

    count++;
    if(count >= 10){
        toggle = !toggle;
        count = 0;
        PORTBbits.RB0 = toggle; // RB0のスイッチを切り替える      
    }
}

void initTimer1()
{
    T1CONbits.ON = 0;    // 設定のため、タイマー1を無効にする
    TMR1 = 0;            // タイマー1をリセット
     
    // 100ms周期で割り込み <- 250ns(1 / 40MHz) * 256 * 15625(0x3D09) = 100ms
    T1CONbits.TCKPS = 3; // プリスケーラ : x1/256
    PR1 = 0x3D09;        // カウンター
    
    INTCONbits.MVEC = 1; // マルチベクタ割り込みを有効にする
    
    IPC1bits.T1IP = 4;   // 割り込み優先度(0-7)
    IPC1bits.T1IS = 3;   // 副優先度(0-3)
    IFS0bits.T1IF = 0;   // 割り込みフラグをリセット
    IEC0bits.T1IE = 1;   // タイマー1の割り込みを許可
    
    __builtin_enable_interrupts();  // マイコンにおける割り込みの有効。「asm volatile("ei")」と同義
    T1CONbits.ON = 1;    // タイマー1有効
}

int main(void)
{
    TRISBbits.TRISB0 = 0; // B0を出力にする
    PORTBbits.RB0 = 0;    // B0 = off
     
    initTimer1();
    while(1) ;
}

プログラムの値を変えて、任意の間隔でLEDを点滅できるようにしてみましょう。
 | 2018年9月24日

前回の記事で単純なLチカを確認できたら、外部発振器の設定をしてみましょう。ハードウェアの設定はpragmaで行います。8MHz水晶発振子で40MHzのクロックを生成させるには次のようにします。PIC32MXシリーズではシステムクロックは40~120MHzの範囲でないといけないため、入力分数を1/4にして20MHzで動作させるということはできません。
#include <p32xxxx.h>

#pragma config FNOSC = PRIPLL // 発信源 = 主外部発振器
#pragma config POSCMOD = XT // 主発振の方法 = 外部高精度発振器を使う
#pragma config FPLLIDIV = DIV_2 // PLL入力分数 = x1/2
#pragma config FPLLMUL = MUL_20 // PLL逓倍比 = x20
#pragma config FPLLODIV = DIV_2 // PLL出力分数 = x1/2
// 8(主発振の周波数)/2(入力分数)*20(逓倍比)/2(出力分数)=40
こちらは4MHz発振子を使った場合の設定例です。
#pragma config FPLLIDIV = DIV_2 // PLL入力分割(1/2)
#pragma config FPLLMUL = MUL_20 // PLL倍率(x20)
#pragma config FPLLODIV = DIV_1 // PLL出力分割(1/1)
// 8/2*20/1=20
続いて配線です。ブレッドボードにタクトスイッチと1kΩ抵抗を追加し、RB1ピンにつなぎます。
今回のプログラミングで注意しないといけないのは、標準の入力はアナログモードのため、RB1ピンを入力モードにしただけだとでは正しい結果を得られない点です。つまり、オン・オフの判定をしたいのであれば、対象のピンをデジタルモードに明示的に指定する必要があります。以上を踏まえてコードを書いてみましょう。
#include <p32xxxx.h>

#pragma config FNOSC = PRIPLL // 発信源 = 主外部発振器
#pragma config POSCMOD = XT // 主発振の方法 = 外部高精度発振器を使う
#pragma config FPLLIDIV = DIV_2 // PLL入力分数 = x1/2
#pragma config FPLLMUL = MUL_20 // PLL逓倍比 = x20
#pragma config FPLLODIV = DIV_2 // PLL出力分数 = x1/2

int main(int argc, char** argv) {
    // B0ピンを出力にする
    TRISBbits.TRISB0 = 0;
    
    // B1ピンのアナログを無効にする(つまり、B1ピンがデジタルモードになる)
    ANSELBbits.ANSB1 = 0;
    
    // B1ピンを入力にする
    TRISBbits.TRISB1 = 1;
      
    while(1){
        // スイッチが入ると電気がGNDに流れてRB1が0になる
        // つまりRB1が0のときRB0を1にすることで、スイッチを押すとLEDが点く
        PORTBbits.RB0 = ~PORTBbits.RB1;
    }
    
    return (EXIT_SUCCESS);
}
しかしながら、ピンの入出力を正しく設定したにもかかわらず、なおも正しく動作しないと思います。

原因は早すぎるクロック数にあります。PORTレジスタは入力も出力も受け付けることができる反面、検出までにわずかな時間がかかるため、クロックに処理が追いついていないのです。

この問題に対処するにはPORTレジスタではなく、読み込み専用のLATレジスタを使います。以下のようにLATレジスタに置き換えてみましょう。
LATBbits.LATB0 = ~PORTBbits.RB1;
//PORTBbits.RB0 = ~PORTBbits.RB1; クロック数が高い場合、入力の受付も兼ねたこのレジスタでは正しく対応できない
これでスイッチの入力に反応して、LEDが点灯するようになります。


入門編のため、この記事ではループを使ってGPIOを操作しましたが、ちゃんとしたプログラムでは、ループではなく割り込み処理で制御しましょう。割り込み処理を使ったプログラミングはこちらをご覧ください。
 | 2018年9月24日

今回はマイクロチップ謹製の統合開発環境を使った、最も簡素なLチカをプログラミングしてみましょう。

まずはプログラムライターを開発基板に接続します。サンプル基板では、Pickitの▼マークを一番右にして順にピンを差し込めば一致するようになっています。右から6番目のピンにはLEDと抵抗をつなぎます。また、5v電源はUSB端子から取得していますので、USB端子をパソコンやACアダプターなどに接続しておいてください。
マイクロチップのサイトより統合開発環境「MPLAB X IDE(現時点で最新版は5.0)」と32bitコンパイラ「XC32」をダウンロードし、インストールします。

開発ツール・MPLABを起動したら、メニューから「新しいプロジェクト」を選びます。今回はフレームワークを使用しない「Standard Project」を選択してください。
プログラム対象の機器を選びます。「Device」で名称をキーボードで打ち込むと徐々に候補が絞られていくので、「Family」で「PIC32」でフィルターする手間は必要ありません。
プログラミングツールを選択します。ちなみに黄色のマークは「動作はするが、こちらですべての検証は行っていない」を意味しています。私の手持ちはPickit3なので、ここではそれを選んでいます。
コンパイラ選択画面では、先ほどインストールしたXC32を指定します。
プロジェクト名とプロジェクトの保存先を指定します。ほかのエディタでも正しく文字を表示できるように「Encoding」は「UTF-8」にしておきましょう。
プロジェクトが無事作成されたら、C言語ファイルを作成しましょう。まずはメニューより「新規ファイル」を選択。
ファイルの種類は「Cメインファイル」を選びます。ファイル名は任意でかまいません。
コードを記入します。まずは手始めに内部発振回路を使用するなど、すべてマイコンの初期値を使用しています。ちなみに「#include <p32xxxx.h>」をインクルードすることで、レジスタのアドレス番号を名称で指定できるようになります。
#include <p32xxxx.h>

int main(int argc, char** argv) {
    // B0ピンを出力にする
    TRISBbits.TRISB0 = 0;
    
    int i = 0, n = 0;
    while(1){
        PORTBbits.RB0 = n;
        i++;
        if(i >= 100000){
            // 10万クロックに1回の割合でスイッチを切り替える
            n = (n == 0) ? 1 : 0;
            i = 0;
        }
    }
    
    return (EXIT_SUCCESS);
}
プログラムコードを入力したら、実行してみましょう。
プログラムコードにミスがなければ「プロジェクトを実行」ボタンを押すだけで、ビルドからチップへの書き込みまで一括で行われます。



また、以下の2行を追加するとPickit3を使ったデバッグができるようになります。
#pragma config ICESEL = ICS_PGx3 // 環境によってはICS_PGx2の場合もある
#pragma config DEBUG  = ON
 | 2018年9月24日

近所のホームセンターで見かけた電源タップのデコレーション例。この中で一見一番手軽にできそうな塗装による自作ですが、電源プラグの穴に塗料が詰まる可能性があるので、タップにペンキを塗るのは好ましくありません。そこで、電源タップを分解して電気が通る金属部分を外してから塗装に臨むわけですが、100v電源を扱う周辺機器という関係上、多くの電源タップは特殊なタイプのネジで封印されています。
星形やY型に関わらず、中央がへこんだタイプのネジであれば、マイナスドライバーを溝に当てることで一通り対応できるのですが、中央が出っ張っているタイプのネジだと、特殊ドライバーセットでもこの形に対応している商品はなかなか見かけません。電気機器をあつかうプロフェッショナルなら、エンジニア社製の専用ドライバー(DTC-27)を常備しても良いのでしょうが、一生に2回以上使うかわからない道具に2000円近く出すのも勇気がいります。

そこで代替品としておすすめしたいのが、ゲーム機用特殊ドライバーです。Amazonなら4.5mmと3.6mm口径のセットで150円くらい(ドライバーの柄の部分は100円均一のラチェットドライバーでOK)で購入でき、写真のようにぴったりとはまってネジを回すことができます。
漏電や火災の原因になるので、油性塗料は使わず、タップの内側など塗らない部分はマスキングテープなどでしっかりと保護し、塗料が完全に乾ききるのを待ちましょう。
 | 2018年9月23日

マイクロチップの32bitマイコン・PIC32シリーズを使った電子工作を行うために必要な環境を作りましょう。ハードウェア面で必要なのは以下の通りです。

オリジナルの開発基板のKiCadデータと印刷デザインを無料で配布しています。そのまま使用するか、このレイアウトを参考に回路を作ってみましょう。


[高密度基板用(USB 5Vは裏面、もしくは被覆ワイヤーで結線)]


[低密度基板用(USB D+/D-は被覆ワイヤーで結線)]

ユニバーサル基板で作成したい場合はこちらの作成例をヒントにしてください。
基板を作ったら、このような感じでパーツを半田付けします。なお、特に注記のないコンデンサーはすべて0.1uFです。
 | 2018年9月20日

PIC32はマイクロチップ社が開発するプログラマブル32bitマイコンのシリーズです。IoTやMakerブームで様々な種類のマイコンが入手できますが、LEDのオン・オフや、符号化処理をしない簡単な通信だけなら、ArduinoやRaspberry Piだけでも十分に実現できます。それでもあえてPIC32シリーズを選択肢に含める理由として次のものが挙げられます。

PIC32プログラミングの技術書としてAmazonで真っ先に見つかるのが、後閑哲也氏の著書「PIC32MX活用ガイドブック」です。ただ、PIC32マイコンのレジスタなどの技術情報を得るには大変便利な本著ですが、プログラミングという点では力不足になりつつあります。と、いうのも、サンプルコードで利用しているライブラリーがマイクロチップでは過去の遺物(レガシー)扱いとなっており、今後発展する予定がないからです。

意外に役に立つのが「ディジタル回路設計とコンピュータアーキテクチャ」という技術書です。本来はCPUの動く仕組みについて解説した本なのですが、x86よりもMIPSアーキテクチャに重心を置いており、第8章の「組み込みI/Oシステム」ではざっくりとながら、PIC32を用いたGPIO、SPI、PWMなどのプログラムサンプルを閲覧することができます。
TNKソフトウェアではこれらの参考資料を基に作成・開発したPIC32マイコンによる作品や近代的なプログラム例を公開していく予定です。
 | 2018年9月20日

PICマイコンにコンパイルしたプログラムデータを書き込むには、マイクロチップ謹製のPickit4を使うが定番ですが、比較的オープンなアーキテクチャを採用しているPIC32シリーズではArduinoをPICライターにすることができます。

まずはArduino Nanoを用意します。300円前後のNano互換ボードでもOKですが、CH340Gチップを搭載しているモデルには当たり外れがある(USBデバイスとして認識されないことがある)ので気をつけましょう。
続いてPIC32マイコンとArduinoをつなぐための回路を作ります。必要なのはユニバーサル基板と、100Ω抵抗x2、3.3KΩ抵抗x3、ツェナーダイオード(3.3v)x1、いくつかのピンヘッダです。ユニバーサル基板に半田付けする際は、4番目のピンを除くすべてのワイヤーが電源端子につながるようにします。ダイオードには向きがあるので間違えないように。基板を作ったら、NanoのGNDがダイオードのあるピンに、D7が反対の端のピンとつながるようにブレッドボードへ差し込みます。
Arduinoにファームウェアを書き込みます。写真のように5vピンとRSTピンをショートさせてUSBによるリセット操作を無効にしたら、Serge Vakulenko氏の開発したPIC32ライターユーティリティ「pic32prog.exe」をダウンロードします。一部のアンチウイルスソフトでは警告が表示されることがあるので、そのときはセーフリストに加えましょう。

ArduinoとパソコンをUSBケーブルでつなげたら、対象の機器が持っているCOMポートの番号を控えます。下のスクリーンショット場合は「3」になります。
コマンドラインを開いたらpic32progのあるフォルダーに移動(cdコマンド)し、「pic32prog -d ascii:com# -b3」と打ち込みます(#はAdruinoが所有しているポート番号)。以下のようなメッセージが出たらファームウェアの書き込みは完了です。5vとRSTをショートしていた線を外してください。
ではプログラムを書き込んでみましょう。中央のピンから外側に向かってMLCR、ICSPDAT/PGD、ICSPCLK/PGC、GNDのピンに、独立した1ピンはVDDに割り当てます。
コマンドラインより「pic32prog -d ascii:com# binary.hex」と入力(#はポート番号、"binary.hex"はMPLABなどの開発ツールで作成したPIC向けプログラム、もしくはファームウェア)して、対象のhexファイルを書き込みます。手っ取り早く試したい人は、私が書いたLチカプログラムのhexファイル(RB0ピンのオン・オフが1秒単位で切り替わります。詳しい回路図は近日公開します)を使ってください。

書き込みが成功すると以下のメッセージが表示されます。マイコンが認識されない場合は、ArduinoでRSTピンがショートしたままであったり、PICマイコンでコンデンサーを正しく付けていない可能性があります。
プログラムを書き込んだら、ArduinoのRSTとGNDピンをショートさせて、Arduinoのライター機能を無効にします。これにより、PIC32マイコンのプログラムの動作が始まるとともに、ArduinoのTX/RXピンを介してのUSBシリアルモニターを利用することができるようになります。

, | 2018年9月20日

電子工作でむき出しの電線を覆うために欠かせないのが、熱を加えると小さくなってケーブルにひっつく熱収縮チューブ。そんな熱収縮チューブでケーブルを保護するとともに見分けを付けやすくできるアイテムがキングジムから販売されています。

それが「PROテープカートリッジ熱収縮チューブ」。キングジムのロングセラーラベルプリンター「テプラPRO」専用のテープで、テプラで印刷したら、そのままヒートガンを当てて熱収縮チューブとして使うことができます。
 
 | 2018年9月19日