SPIの受信をメインループ内でポーリングしていたのを、SPI(SCB)コンポーネントのInterruput SourceでFIFOにデータが5エントリー溜まったら割り込みが発生するようにして処理してみた。
main.c
/* ======================================== * * Copyright YOUR COMPANY, THE YEAR * All Rights Reserved * UNPUBLISHED, LICENSED SOFTWARE. * * CONFIDENTIAL AND PROPRIETARY INFORMATION * WHICH IS THE PROPERTY OF your company. * * ======================================== */ #include <project.h> #include <stdio.h> #define UART_TRACE (0) #define LCD_DISPLAY (0) #define TITLE_STR1 ("PSoC 4 DCO") #define TITLE_STR2 ("20160606") #define SAMPLING_CLOCK (24000000) #define SPIS_RX_PACKET_SIZE (5) #define SPIS_RX_PACKET_HEADER (0x55) #define WAVESHAPE_SQUARE 0 #define WAVESHAPE_SAW 1 #define WAVESHAPE_N 2 volatile uint8 count; uint8 waveShape = WAVESHAPE_SQUARE; uint8 squareDuty = 127; int32 frequency10 = 4400; #if(LCD_DISPLAY) void printLCD(uint8* rxBuffer) { char strBuffer[20]; sprintf(strBuffer, "%3u %3u %3u %3u", rxBuffer[0], rxBuffer[1], rxBuffer[2], rxBuffer[3]); LCD_Char_Position(0, 0); LCD_Char_PrintString(strBuffer); sprintf(strBuffer, "%3u %5ld", rxBuffer[4], frequency10); LCD_Char_Position(1, 0); LCD_Char_PrintString(strBuffer); } #endif CY_ISR(ISR_Saw_handler) { Pin_Check2_Write(1); count++; IDAC8_SetValue(count); Timer_Sampling_ClearInterrupt(Timer_Sampling_INTR_MASK_TC); Pin_Check2_Write(0); } CY_ISR(ISR_Square_handler) { Pin_Check2_Write(1); count++; IDAC8_SetValue((count / squareDuty) ? 255 : 0); Timer_Sampling_ClearInterrupt(Timer_Sampling_INTR_MASK_TC); Pin_Check2_Write(0); } void doCommand(uint8 *rxBuffer) { uint16 timerPeriod; if (waveShape != rxBuffer[1]) { waveShape = rxBuffer[1]; switch (waveShape) { case WAVESHAPE_SQUARE: ISR_Timer_Sampling_StartEx(ISR_Square_handler); break; case WAVESHAPE_SAW: ISR_Timer_Sampling_StartEx(ISR_Saw_handler); break; } } squareDuty = rxBuffer[2]; frequency10 = ((uint16)rxBuffer[3] << 8) | rxBuffer[4]; timerPeriod = (uint64)SAMPLING_CLOCK * 10 / (frequency10 * 256); Timer_Sampling_WritePeriod(timerPeriod); } void SPI_RX_handler() { uint8 rxBuffer[SPIS_RX_PACKET_SIZE]; int i; Pin_Check1_Write(1); rxBuffer[0] = SPIS_SpiUartReadRxData(); if (SPIS_RX_PACKET_HEADER == rxBuffer[0]) { for (i = 1; i < SPIS_RX_PACKET_SIZE; i++) { rxBuffer[i] = SPIS_SpiUartReadRxData(); } doCommand(rxBuffer); } SPIS_ClearRxInterruptSource(SPIS_INTR_RX_FIFO_LEVEL); Pin_Check1_Write(0); } int main() { CyGlobalIntEnable; /* Enable global interrupts. */ #if(UART_TRACE) UART_Start(); UART_UartPutString("PSoC 4 SPI Slave Test\r\n"); #endif #if(LCD_DISPLAY) LCD_Char_Start(); LCD_Char_ClearDisplay(); LCD_Char_PrintString(TITLE_STR1); LCD_Char_Position(1, 0); LCD_Char_PrintString(TITLE_STR2); CyDelay(1000); #endif IDAC8_Start(); Opamp_IV_Conv_Start(); Timer_Sampling_Start(); ISR_Timer_Sampling_StartEx(ISR_Saw_handler); SPIS_SetCustomInterruptHandler(SPI_RX_handler); SPIS_Start(); for(;;) { } } /* [] END OF FILE */
SPI信号とタイマー割り込み
割り込みがかからない?
ch1:Pin_Check1 ch2:SPI_MOSI
拡大
ch1のPin_Check1はタイマー割り込みがかかるたびに割り込み処理ルーチンの最初と最後でH→Lさせている。
ch2はSPIのMOSIの信号を拾っている。1枚目の画像はch2が単にH→Lになっているように見えるが、拡大するとHの後にMOSIの信号が流れて最後はLになっている。MOSIの通信の前後のレベルは不定でよいと思うのでHでもLでもいいと思うけど、違うかな?
SPIのマスター(Nucleo)から音程が変更されるデータが送られてくるタイミングで、1枚目の画像のようにゴソッと割り込みがかからなくなる。
出力波形をWaveSpectraで取り込み
メモ:
いくつかバグや無駄な処理があったので修正してみたが、改善されない。
DWRエディターでSPIとタイマーの割り込みの優先度を変えてみたがかえって悪化する(ーー;
SPIとタイマー割り込みの絡みかと思っていたが、周期的に割り込みが発生している最中にPeriod(割り込みの周期)を変更しているのが原因のような気もする。
→SPIの処理を外して実験して見る。
mbed erepository:
https://developer.mbed.org/users/ryood/code/SpiSequenceSender_Test/
Github:
https://github.com/ryood/PSoC4_DCO/tree/master/PSoC/PSoC4_DCO_for_NucleoF401RE_Interrupt_Test.cydsn
0 件のコメント:
コメントを投稿