PIC24FJ64GB002でSPIを使いたかった話

使いたかった話【未完】

1.目的
TLC5940をPICで扱いたい.TLC5940はクロック+クリア信号の入力+SPIが必要になる.
クロック+クリア信号については前回のPWM制御で解決したものの,肝心のSPIがまだできていない.
ので,やる.
 
2.概要
PIC24FJ64GB002はハードウェアでSPIをサポートしている.
SPIの利用法だが,Microchip Application LibraryがSPIを扱うためのドライバを提供しているため,そちらを使わせていただく.
 
3.初期設定
SPIは4つまで使用することができる.今回は1つだけで良いので,
#define DRV_SPI_CONFIG_CHANNEL_1_ENABLE
とすることでSPIのチャンネル1を使用可能にすることができる.
また,拡張バッファモードを設定する必要がある.拡張バッファモードを設定すると最大8個の未送信データを保持できるとのこと(ここの18.2 SPIレジスタ).使用する場合は何も記述せず,使用しない場合は
#define DRV_SPI_CONFIG_ENHANCED_BUFFER_DISABLE
と記述する.
 
4.初期化
初期化には
DRV_SPI_Initialize(DRV_SPI_INIT_DATA * pData)
を使う.引数のDRV_SPI_INIT_DATAは
typedef struct {
uint16_t channel;
uint16_t baudRate;
uint16_t dummy;
uint16_t primaryPrescale;
uint16_t secondaryPrescale;
uint8_t divider;
uint8_t cke;
SPI_BUS_MODES spibus_mode;
SPI_TRANSFER_MODE mode;
} DRV_SPI_INIT_DATA;
となっている.各変数の意味を以下に示す.
・uint16_t channel;
初期化するチャンネルを表す.例えばチャンネル1を使いたいときは1.
・uint16_t baudRate;
ボーレート,転送速度のこと.なお,PIC32の設定でのみ使用される.
・uint16_t dummy;
ドキュメントに書いてないしソースの検索にかからないし分からない.PIC32の設定でのみ使用される.
・uint16_t primaryPrescale;
SPIxCON1 のPPREに対応する.
11 = Primary prescale 1:1
10 = Primary prescale 4:1
01 = Primary prescale 16:1
00 = Primary prescale 64:1
となる.
・uint16_t secondaryPrescale;
SPIxCON1 のSPREに対応する.
111 = Secondary prescale 1:1
110 = Secondary prescale 2:1

000 = Secondary prescale 8:1
となっている.
・uint8_t divider;
ドキュメントに書いてないしソースの検索にかからないし分からない.
・uint8_t cke;
CPIxCON1のCKEに対応する.データを出力するタイミングを,クロックがアクティブからアイドルに変化したときか,アイドルからアクティブに変化したときかのどちらかを選ぶ(ここのp18-5参照).
・SPI_BUS_MODES spibus_mode;
SPIxCON1のCKPとSMPに関わる.CKPは1ならHighレベルをアイドル状態とし,0ならLowレベルをアイドル状態とする.SMPはマスターモードでのみ使用する.入力データのサンプリングのタイミングに関わるもので,1ならデータ出力の最後,0ならデータ出力の中間でサンプリングを行う.
なお,SPI_BUS_MODESはenumで定義されており,

SPI_BUS_MODE_0でCKP=0,SMP=0
SPI_BUS_MODE_1でCKP=0,SMP=1
SPI_BUS_MODE_2でCKP=1,SMP=0
SPI_BUS_MODE_3でCKP=1,SMP=1

となる.
・SPI_TRANSFER_MODE mode;
何バイト単位で通信を行うか決める.SPI_TRANSFER_MODEはenumで

SPI_TRANSFER_MODE_32BIT = 2,
SPI_TRANSFER_MODE_16BIT = 1,
SPI_TRANSFER_MODE_8BIT = 0
と定義されている.なお,32ビットの転送はPIC32でのみ使用可能である.
以上のことから,今回使用したい初期化データは以下のようになる.
DRV_SPI_INIT_DATA spiInitData = {1, 3, 7, 0, SPI_BUS_MODE_1, SPI_TRANSFER_MODE_8BIT};

 
5.送信
void DRV_SPI_PutBuffer(uint8_t channel, uint8_t * data, uint16_t count);を使用する.使用するチャンネルとバッファのアドレス,サイズを渡すことでデータを送信することができる.
 
6.受信
void DRV_SPI_GetBuffer(uint8_t channel, uint8_t * data, uint16_t count);を使用する.使用するチャンネルと受信バッファのアドレス,受信するデータのサイズを指定することでデータを受信することができる.
 
7.終了
void DRV_SPI_Deinitialize(uint8_t channel);で閉じるチャンネルを使用して閉じる.