{"id":251,"date":"2013-04-04T13:15:02","date_gmt":"2013-04-04T13:15:02","guid":{"rendered":"http:\/\/www.electronic-products-development.com\/?p=251"},"modified":"2022-02-18T15:37:49","modified_gmt":"2022-02-18T15:37:49","slug":"spi-pic32","status":"publish","type":"post","link":"https:\/\/ibex.tech\/embedded\/microchip\/pic32\/c32-compiler\/spi-pic32","title":{"rendered":"SPI &#8211; PIC32"},"content":{"rendered":"<h4>\nSPI Master<br \/>\n<\/h4>\n<pre>\r\n<code>\r\n\t\/\/----- SETUP SPI 1 -----\r\n\t\/\/Used for: \r\n\t\/\/Idle low, active high\r\n\t\/\/Transmit on active to idle (falling edge)\r\n\tSpiChnOpen(SPI_CHANNEL1, (SPI_CON_MSTEN | SPI_OPEN_CKE_REV | SPI_CON_MODE8), 2);       \t\/\/40MHz fpb \/ 2 = 20MHz\r\n<\/code><\/pre>\n<h4>\nSPI Slave<br \/>\n<\/h4>\n<pre>\r\n<code>\r\n#define\tCOMMS_SPI_NAME\t\t\t\t\tSPI_CHANNEL3\r\n#define\tCOMMS_SPI_ID\t\t\t\t\tSPI_CHANNEL3\r\n#define\tCOMMS_SPI_SS_PIN_STATE\t\t\tmPORTEReadBits(BIT_8)\r\n\r\n\t\/\/----- SETUP SPI 3 -----\r\n\t\/\/Used for:  (we are slave with SS pin used)\r\n\t\/\/Idle low, active high\r\n\t\/\/Transmit on idle to active (rising edge)\r\n\r\n\tSpiChnClose(COMMS_SPI_NAME);\r\n\r\n\tSpiChnOpen(COMMS_SPI_NAME, (SPI_OPEN_SLVEN | SPI_CON_MODE8 | SPI_OPEN_RBF_NOT_EMPTY | SPI_OPEN_ENHBUF | SPI_OPEN_SSEN), 50);       \t\/\/Master sets clock rate\r\n\tSpiChnWriteC(COMMS_SPI_NAME, (unsigned int)0xff);\t\t\t\/\/We are slave so setup 1st response byte to null\r\n\r\n\tINTSetVectorPriority(INT_VECTOR_SPI(COMMS_SPI_ID), INT_PRIORITY_LEVEL_5);\t\t\t\t\/\/1=lowest priority to 7=highest priority.  ISR function must specify same value\r\n\t\/\/INTClearFlag(INT_SOURCE_SPI_TX(COMMS_SPI_ID));\r\n\t\/\/INTEnable(INT_SOURCE_SPI_TX(COMMS_SPI_ID), INT_ENABLED);\r\n\tINTClearFlag(INT_SOURCE_SPI_RX(COMMS_SPI_ID));\r\n\tINTEnable(INT_SOURCE_SPI_RX(COMMS_SPI_ID), INT_ENABLED);\r\n\tINTClearFlag(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID));\r\n\tINTEnable(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID), INT_ENABLED);\r\n\r\n<\/code><\/pre>\n<p>\n&nbsp;\n<\/p>\n<pre>\r\n<code>\r\nWORD comms_spi_tx_byte;\r\nWORD comms_spi_rx_byte;\r\nWORD comms_spi_rx_no_of_bytes_to_rx;\r\n\r\n\/\/************************************\r\n\/\/************************************\r\n\/\/********** SPI INTERRUPTS **********\r\n\/\/************************************\r\n\/\/************************************\r\nvoid __ISR(_SPI_3_VECTOR, ipl5) Spi3InterruptHandler (void) \t\t\/\/(ipl# must match the priority level assigned to the irq where its enabled)\r\n{\r\n\tstatic BYTE data;\r\n\t\r\n\t\r\n\tNop();\r\n\r\n\r\n\/*\r\n\tif (\r\n\t(INTGetEnable(INT_SOURCE_SPI_TX(COMMS_SPI_ID))) &amp;&amp;\r\n\t(INTGetFlag(INT_SOURCE_SPI_TX(COMMS_SPI_ID)))\r\n\t)\r\n\t{\r\n\t\t\/\/--------------------------------------\r\n\t\t\/\/--------------------------------------\r\n\t\t\/\/---------- SPI TX INTERRUPT ----------\r\n\t\t\/\/--------------------------------------\r\n\t\t\/\/--------------------------------------\r\n\r\n\r\n\t\t\/\/INTClearFlag(INT_SOURCE_SPI_TX(COMMS_SPI_ID));\r\n\t}\r\n*\/\r\n\r\n\r\n\tif (\r\n\t(INTGetEnable(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID))) &amp;&amp;\r\n\t(INTGetFlag(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID)))\r\n\t)\r\n\t{\r\n\t\t\/\/-----------------------------------------\r\n\t\t\/\/-----------------------------------------\r\n\t\t\/\/---------- SPI ERROR INTERRUPT ----------\r\n\t\t\/\/-----------------------------------------\r\n\t\t\/\/-----------------------------------------\r\n\t\t\r\n\t\t\/\/Read and clear the SPIROV (overflow) bit\r\n\t\tSpiChnGetRov(COMMS_SPI_ID, 1);\r\n\r\n    \t\r\n    \t\/\/Clear RX buffer of bad data\r\n\t\twhile (SpiChnDataRdy(COMMS_SPI_NAME))\r\n\t\t\tdata = SpiChnReadC(COMMS_SPI_NAME);\r\n\r\n\t\tINTClearFlag(INT_SOURCE_SPI_RX(COMMS_SPI_ID));\r\n\t\tINTClearFlag(INT_SOURCE_SPI_ERROR(COMMS_SPI_ID));\r\n\r\n\t\tcomms_spi_rx_byte = 0xffff;\r\n\t}\r\n\r\n\r\n\r\n\tif (\r\n\t(INTGetEnable(INT_SOURCE_SPI_RX(COMMS_SPI_ID))) &amp;&amp;\r\n\t(INTGetFlag(INT_SOURCE_SPI_RX(COMMS_SPI_ID)))\r\n\t)\r\n\t{\r\n\t\t\/\/--------------------------------------\r\n\t\t\/\/--------------------------------------\r\n\t\t\/\/---------- SPI RX INTERRUPT ----------\r\n\t\t\/\/--------------------------------------\r\n\t\t\/\/--------------------------------------\r\n\r\n\t\tif (comms_rx_reset_1ms_timer == 0)\t\t\t\/\/We also check for CS gone high and reset comms_spi_rx_byte\r\n\t\t\tcomms_spi_rx_byte = 0;\r\n\t\t\t\t\r\n\t\tcomms_rx_reset_1ms_timer = 10;\t\t\t\t\/\/&lt;&lt;&lt;&lt; Gap required between packets to mark start of packet\r\n\r\n\t\twhile (SpiChnDataRdy(COMMS_SPI_NAME))\r\n\t\t{\r\n\t\t\t\/\/----- GET DATA BYTE -----\r\n\t\t\tdata = (BYTE)SpiChnReadC(COMMS_SPI_NAME);\r\n\r\n\t\t\t\/\/Check for SPI \/ UART COMMS CLASH\r\n\t\t\tif (comms_uart_rx_active_10ms_timer)\t\t\t\/\/If UART is active then ignore SPI comms (clash)\r\n\t\t\t{\r\n\t\t\t\tSpiChnWriteC(COMMS_SPI_NAME, (unsigned int)0xff);\t\t\/\/Return null next time\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tcomms_spi_rx_active_10ms_timer = 10;\t\t\t\/\/Flag that active comms is SPI (UART to ignore)\r\n\r\n\t\t\t\/\/Check for still processing last RX\r\n\t\t\tif (comms_rx_process_packet)\r\n\t\t\t{\r\n\t\t\t\tSpiChnWriteC(COMMS_SPI_NAME, (unsigned int)0xff);\t\t\/\/Return null next time\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\r\n\t\t\tif (comms_spi_tx_byte &lt; comms_tx_no_of_bytes_to_tx)\r\n\t\t\t{\r\n\t\t\t\t\/\/---------------------------------\r\n\t\t\t\t\/\/---------------------------------\r\n\t\t\t\t\/\/----- TRANSMITTING RESPONSE -----\r\n\t\t\t\t\/\/---------------------------------\r\n\t\t\t\t\/\/---------------------------------\r\n\t\t\t\tSpiChnWriteC(COMMS_SPI_NAME, (unsigned int)comms_tx_rx_buffer[comms_spi_tx_byte++]);\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\/\/Not transmitting so send mull\r\n\t\t\tSpiChnWriteC(COMMS_SPI_NAME, (unsigned int)0xff);\t\t\/\/Return null next time\r\n\t\t\t\r\n\r\n\r\n\r\n\t\t\t\/\/--------------------------\r\n\t\t\t\/\/--------------------------\r\n\t\t\t\/\/----- RECEIVING DATA -----\r\n\t\t\t\/\/--------------------------\r\n\t\t\t\/\/--------------------------\r\n\t\t\tif (comms_spi_rx_byte == 0)\r\n\t\t\t{\r\n\t\t\t\t\/\/--------------------\r\n\t\t\t\t\/\/----- LENGTH H -----\r\n\t\t\t\t\/\/--------------------\r\n\t\t\t\tcomms_spi_rx_no_of_bytes_to_rx = (WORD)data;\r\n\t\t\t\tcomms_spi_rx_no_of_bytes_to_rx &lt;&lt;= 8;\r\n\t\t\t\tcomms_tx_rx_buffer[comms_spi_rx_byte++] = data;\r\n\t\t\t}\r\n\t\t\telse if (comms_spi_rx_byte == 1)\r\n\t\t\t{\r\n\t\t\t\t\/\/--------------------\r\n\t\t\t\t\/\/----- LENGTH L -----\r\n\t\t\t\t\/\/--------------------\r\n\t\t\t\tcomms_spi_rx_no_of_bytes_to_rx |= (WORD)data;\r\n\t\t\t\tcomms_tx_rx_buffer[comms_spi_rx_byte++] = data;\r\n\t\t\t\t\r\n\t\t\t\tif (comms_spi_rx_no_of_bytes_to_rx &gt;= LENGTH_OF_USART_BUFFER)\r\n\t\t\t\t\tcomms_spi_rx_byte = 0xffff;\r\n\t\t\t}\r\n\t\t\telse if (comms_spi_rx_byte &lt; comms_spi_rx_no_of_bytes_to_rx)\r\n\t\t\t{\r\n\t\t\t\t\/\/--------------------------\r\n\t\t\t\t\/\/----- NEXT DATA BYTE -----\r\n\t\t\t\t\/\/--------------------------\r\n\t\t\t\tcomms_tx_rx_buffer[comms_spi_rx_byte++] = data;\r\n\r\n\t\t\t\tif (comms_spi_rx_byte &gt;= comms_spi_rx_no_of_bytes_to_rx)\r\n\t\t\t\t{\r\n\t\t\t\t\t\/\/---------------------------------\r\n\t\t\t\t\t\/\/----- VALID PACKET RECEIVED -----\r\n\t\t\t\t\t\/\/---------------------------------\r\n\t\t\t\t\tcomms_rx_process_packet = 2;\t\t\t\t\t\/\/Flag for main function to process rx\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t\tINTClearFlag(INT_SOURCE_SPI_RX(COMMS_SPI_ID));\t\t\t\t\/\/Do after reading data as any data in RX FIFO will stop irq bit being cleared\r\n\t}\r\n\t\r\n}\r\n<\/code><\/pre>\n<p>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>SPI Master \/\/&#8212;&#8211; SETUP SPI 1 &#8212;&#8211; \/\/Used for: \/\/Idle low, active high \/\/Transmit on active to idle (falling edge) SpiChnOpen(SPI_CHANNEL1, (SPI_CON_MSTEN | SPI_OPEN_CKE_REV | SPI_CON_MODE8), 2); \/\/40MHz fpb \/ 2 = 20MHz SPI Slave #define COMMS_SPI_NAME SPI_CHANNEL3 #define COMMS_SPI_ID SPI_CHANNEL3 #define COMMS_SPI_SS_PIN_STATE mPORTEReadBits(BIT_8) \/\/&#8212;&#8211; SETUP SPI 3 &#8212;&#8211; \/\/Used for: (we are slave with [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[],"class_list":["post-251","post","type-post","status-publish","format-standard","hentry","category-c32-compiler"],"_links":{"self":[{"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/posts\/251","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/comments?post=251"}],"version-history":[{"count":5,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/posts\/251\/revisions"}],"predecessor-version":[{"id":526,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/posts\/251\/revisions\/526"}],"wp:attachment":[{"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/media?parent=251"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/categories?post=251"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ibex.tech\/embedded\/wp-json\/wp\/v2\/tags?post=251"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}