配線図
PSoC 4 Pioneer Kitのボード上のジャンパを3.3V駆動に設定して、信号レベルを両方とも3.3Vにした。
Nucleo F401RE(SPI Master)
SPI MasterのNucleo F401REはmbedのオンライン・コンパイラで、SPIクラスと割り込み処理にTickerクラスを使った。
mbedのmain.cpp
#include "mbed.h" #define SPIM_TICKER_PERIOD (0.01) #define SPIM_RATE (8000000) // 8MHz #define SPI_PACKET_HEADER (0x55) // ピン・アサイン #define PSOC4_DCO_CS PB_6 SPI spim(SPI_MOSI, SPI_MISO, SPI_SCK); Ticker spim_write_ticker; DigitalOut PSoC4_DCO_CS(PSOC4_DCO_CS); void spim_tx() { static uint8_t i = 0; PSoC4_DCO_CS = 0; spim.write(SPI_PACKET_HEADER); spim.write(i); spim.write(i); spim.write(i); spim.write(i); wait_us(1); PSoC4_DCO_CS = 1; i++; } int main() { spim.format(8, 0); spim.frequency(SPIM_RATE); spim_write_ticker.attach(&spim_tx, SPIM_TICKER_PERIOD); for (;;) { //spim_tx(); //wait(0.1); } }
spim_tx()が割り込み処理ルーチンで、SPI Masterから送信している。
wait_us(1);とPSoC4_DCO_CSをHにする前にウェイトをかけているのは、タイミングなどの条件によってSCKの送信が完了する前にCSがHになってしまう場合があったから。
また、mbedオフィシャルのTickerのページで
No blocking code in ISR
In ISR you should avoid any call to wait, infinitive while loop, or blocking calls in general.
No printf, malloc, or new in ISR
In ISR you should avoid any call to bulky library functions. In particular, certain library functions (like printf, malloc and new) are non re-entrant and their behaviour could be corrupted when called from an ISR.
RTOS Timer
Consider using the mbed RTOS Timer instead of a Ticker. In this way your periodic function will not be executed in a ISR, giving you more freedom and safety in your code.
とあるので、ほんとはwaitをかけるのは良くないのかもしれないし、SPIのコマンドを発行するのも良くないのかもしれない。RTOSクラスのTimerを使え、と書いてあるのでそうしするつもり。ただし、RTOS Timerの間隔指定はミリ秒単位のようだ(クロックで言うと1kHz)。
SPIの通信状態
ch1:MOSI ch2:SCK
ch1:CS ch2:SCK
mbedのプログラムでSPIのクロックは8MHzを指定しているが、実際は5MHz程度になっている。いくつか値を試してみたが設定通りのクロックになることはまずなかった。タイミングがシビアなときには確認が必要だと思う。
PSoC 4 Pioneer Kit(SPI Slave)
PSoCのTop Design
PWMコンポーネントは受け取った値でPulse Widthを変えて様子を見るために使っている。Master側のSPIの送信速度が速くなるとUARTでは処理落ちしてしまうため。
#define UART_TRACE (1) #include <project.h> #include <stdio.h> #define RX_PACKET_SIZE (5) #define RX_PACKET_HEADER (0x55) int main() { uint8_t rxBuffer[RX_PACKET_SIZE]; char strBuffer[100]; int i; CyGlobalIntEnable; /* Enable global interrupts. */ UART_Start(); UART_UartPutString("PSoC 4 SPI Slave Test\r\n"); SPIS_Start(); PWM_Start(); for(;;) { // Check Packet Header if (RX_PACKET_SIZE <= SPIS_SpiUartGetRxBufferSize()) { rxBuffer[0] = SPIS_SpiUartReadRxData(); if (RX_PACKET_HEADER != rxBuffer[0]) { break; } for (i = 1; i < RX_PACKET_SIZE; i++) { rxBuffer[i] = SPIS_SpiUartReadRxData(); } PWM_WriteCompare(rxBuffer[1]); #if(UART_TRACE) sprintf(strBuffer, "%d\t%d\t%d\t%d\t%d\r\n", rxBuffer[0], rxBuffer[1], rxBuffer[2], rxBuffer[3], rxBuffer[4]); UART_UartPutString(strBuffer); #endif } } }
SPIのパケットの先頭byteのヘッダ(0x55)を見て、パケットごとに処理するようにしている。
Github:
https://github.com/ryood/PSoC4_SPI_Slave_Test/tree/master/PSoC(Slave)/PSoC4_SPI_Slave_Test/PSoC4_SPI_Slave_Test_for_NucleoF401RE.cydsn
0 件のコメント:
コメントを投稿