PIC24 SPI not working - Page 1
Forum section: electronics / general

author: diyaudio
author_rank: Frequent Contributor
timestamp: March 23, 2014, 10:26:39 am
content: Hi GuysI cannot get SPI to work, no clock nothing, I slapped together some SPI code after reading the PIC24F128210 after reading the datasheet a reasonable amount of times, I still cannot seem to understand why its not working.The SPI is commanding a MCP4921 DAC.Here is the codeFOSC using internal 8MHZ clock.Code:int main(int argc, char** argv){// G15 PORTG as output. (used as a test)TRISGbits.TRISG15 = 0; // OUTPUT LED status flashTRISEbits.TRISE6 = 0; // OUTPUT SCL-3TRISEbits.TRISE7 = 0; // OUTPUT SDA-3TRISEbits.TRISE5 = 0; // DAC Chip select.reset_clock();CS_DAC = 1;/* Init SPI-3 *//* ## SPI3CON1: SPIx CONTROL REGISTER 1 */// bit 1-0 PPRE<1:0>: Primary Prescale bits (Master mode)// 11 = Primary prescale 1:1SPI3CON1bits.PPRE = 11;// bit 4-2 SPRE<2:0>: Secondary Prescale bits (Master mode)// 111 = Secondary prescale 1:1SPI3CON1bits.SPRE = 111;// bit 5 MSTEN: Master Mode Enable bit (1 = Master mode).SPI3CON1bits.MSTEN = 1;// bit 6 CKP: Clock Polarity Select bit// (1 = Idle state for the clock is a low level; active state is a high level).SPI3CON1bits.CKP = 0;// bit 8 CKE: SPIx Clock Edge Select bit(3)// 0 = Serial output data changes on transition from Idle clock state to active clock state (see bit 6).SPI3CON1bits.CKE = 0;// bit 10 MODE16: Word/Byte Communication Select bit// 1 = Communication is byte-wide (16 - bits).SPI3CON1bits.MODE16 = 0;// bit 11 DISSDO: Disable SDOx Pin bit(2)// 0 = SDOx pin is controlled by the module.SPI3CON1bits.DISSDO = 0;// bit 12 DISSCK: Disable SCKx Pin bit (SPI Master modes only)(1)// 0 = Internal SPI clock is enabledSPI3CON1bits.DISSCK = 0;// ## SPI3CON3: SPIx CONTROL REGISTER 2// bit 0 SPIBEN: Enhanced Buffer Enable bit// 0 = Enhanced buffer is disabled (Legacy mode)SPI3CON2bits.SPIBEN = 0;// 3. Clear the SPIROV bit (SPIxSTAT<6>).SPI3STATbits.SPIROV = 0;// 4. Enable SPI operation by setting the SPIEN bit. (SPIxSTAT<15>).SPI3STATbits.SPIEN = 1;while(1){adc_spi_write(11);__delay_us(100);}return (EXIT_SUCCESS);}void adc_spi_write(unsigned int data){CS_DAC = 0;/* 5. Write the data to be transmitted to the SPIxBUFregister. Transmission (and reception) will startas soon as data is written to the SPIxBUFregister.*/SPI3BUF = data;/*bit 1 SPITBF: SPIx Transmit Buffer Full Status bit1 = Transmit has not yet started, SPIxTXB is full0 = Transmit has started, SPIxTXB is emptyIn Standard Buffer mode:Automatically set in hardware when the CPU writes to the SPIxBUF location, loading SPIxTXB.Automatically cleared in hardware when the SPIx module transfers data from SPIxTXB to SPIxSR.*/while(!SPI3STATbits.SPIRBF);CS_DAC = 1;}

author: hans
author_rank: Super Contributor
timestamp: March 23, 2014, 11:50:05 am
content: Code:TRISEbits.TRISE6 = 0; // OUTPUT SCL-3TRISEbits.TRISE7 = 0; // OUTPUT SDA-3Unless you're using it elsewhere, that is not SPI but I2C. (They are the correct pins for I2C, but the MCP4921 isn't an I2C device. Also I2C pins are usually configured as inputs/open-drain, with pull-ups).Some DAC's or ADC's are so minimalistic set-up, they only have a SDI (MOSI/DAC) or SDO (MISO/ADC), clock and chip select pin. Some DAC's don't have any registers to read from, so they saved a pin by leaving out the MISOSee the pinout of the chip and notice how the bold RPx are shown. These are pins that can have a variety of pins mapped to them. Peripherals like UART, SPI, most timer input/outputs, and most external interrupts are only active&accessible via PPS (peripheral pin select) module.You have to map the pins to the reprogrammable Pins you use at start-up. For example (XC16 code):Code:#include <pps.h>[..]PPSUnLock; // unlocks PPS for configurationiPPSOutput(OUT_PIN_PPS_RP7, OUT_FN_PPS_SCK1OUT); // Reprogrammable Pin 7 = SPI SCK 1iPPSOutput(OUT_PIN_PPS_RP8, OUT_FN_PPS_SDO1); // Reprogrammable Pin 8 = SPI MOSI 1iPPSInput(IN_FN_PPS_SDI1, IN_PIN_PPS_RP20); // Reprogrammable Pin 20 = SPI MISO 1PPSLock;[..]You also need to set TRIS registers correctly for each pin, and also good thing to check if analog features are disabled (if available) for that pin.Edit: I suspect you're using a PIC24FJ128GB210 or PIC24FJ128DA210, because those are only the few parts that end with 210.

author: dannyf
author_rank: Super Contributor
timestamp: March 23, 2014, 11:55:28 am
content: QuoteA more accurate description would be that you cannot make it work.QuoteThat's some chip. No one can help you, I am afraid.The general process is this:1) read and understand the datasheet;2) code to the datasheet;3) celebrate success.For PIC24s, make sure you have assigned the spi pins to RPx.Code:void adc_spi_write(unsigned int data){CS_DAC = 0;It is generally a bad idea to put framing signal inside of a spi byte transmission session, as you may need to transmitt multiple bytes in one frame.Code:/* 5. Write the data to be transmitted to the SPIxBUFregister. Transmission (and reception) will startas soon as data is written to the SPIxBUFregister.*/SPI3BUF = data;The typical sequence would be something like this:Code:spi_write(data):while (spi buffer is not empty) continue; //wait for the buffer to be availableSPIxBUF = data; //load up the buffer:endyour transmmmision sequence would be like this:Code:activate CS;spi_write(data1);spi_write(data2);...spi_write(last data);while (spi_busy) continue; //wait for the transmission to finishdeactivate CS;For spi modules with a buffer, this greatly speeds up the transmission, particularly at low baud rate.For spi module without a buffer, those two conditions are the same.

author: diyaudio
author_rank: Frequent Contributor
timestamp: March 23, 2014, 12:22:06 pm
content: Sorry Guys, I just started working with the PIC-24 Family now recently. I come from the PIC18F45K20 demo-board.Correction. its a PIC24FJ128GB210, some clarity around the problem I mean nothing works as I mentioned, no clock on the scope, no data on the scope. (during SPI data transmission)I think my problem is around the reprogrammable pins, you need at start-up. as @hans and you mentioned. (I'm new to this the datasheet says nothing around this during start-up)QuoteI did this only as a first time test, but thanks for the tip i will keep this in mind. care to show me how you do it ?I will look into the reprogrammable pins now... I am 100% sure its this.

author: diyaudio
author_rank: Frequent Contributor
timestamp: March 23, 2014, 01:14:52 pm
content: Code:int main(int argc, char** argv){PPSUnLock; // unlocks PPS for configurationiPPSOutput(OUT_PIN_PPS_RP7, OUT_FN_PPS_SCK1OUT); // Reprogrammable Pin 7 = SPI SCK 1iPPSOutput(OUT_PIN_PPS_RP6, OUT_FN_PPS_SDO1); // Reprogrammable Pin 8 = SPI MOSI 1// iPPSInput(IN_FN_PPS_SDI1, IN_PIN_PPS_RP20); // Reprogrammable Pin 20 = SPI MISO 1PPSLock;// G15 PORTG as output. (used as a test)TRISGbits.TRISG15 = 0; // OUTPUT LED status flashTRISEbits.TRISE5 = 0; // DAC Chip select.reset_clock();CS_DAC = 1;/* Init SPI-3 *//* ## SPI3CON1: SPIx CONTROL REGISTER 1 */// bit 1-0 PPRE<1:0>: Primary Prescale bits (Master mode)// 11 = Primary prescale 1:1SPI1CON1bits.PPRE = 110;// bit 4-2 SPRE<2:0>: Secondary Prescale bits (Master mode)// 111 = Secondary prescale 1:1SPI1CON1bits.SPRE = 111;// bit 5 MSTEN: Master Mode Enable bit (1 = Master mode).SPI1CON1bits.MSTEN = 1;// bit 6 CKP: Clock Polarity Select bit// (1 = Idle state for the clock is a low level; active state is a high level).SPI1CON1bits.CKP = 1;// bit 8 CKE: SPIx Clock Edge Select bit(3)// 0 = Serial output data changes on transition from Idle clock state to active clock state (see bit 6).SPI1CON1bits.CKE = 1;// bit 10 MODE16: Word/Byte Communication Select bit// 1 = Communication is byte-wide (16 - bits).SPI1CON1bits.MODE16 = 0;// bit 11 DISSDO: Disable SDOx Pin bit(2)// 0 = SDOx pin is controlled by the module.SPI1CON1bits.DISSDO = 0;// bit 12 DISSCK: Disable SCKx Pin bit (SPI Master modes only)(1)// 0 = Internal SPI clock is enabledSPI1CON1bits.DISSCK = 0;// ## SPI3CON3: SPIx CONTROL REGISTER 2// bit 0 SPIBEN: Enhanced Buffer Enable bit// 0 = Enhanced buffer is disabled (Legacy mode)SPI1CON2bits.SPIBEN = 0;// 3. Clear the SPIROV bit (SPIxSTAT<6>).SPI1STATbits.SPIROV = 0;// 4. Enable SPI operation by setting the SPIEN bit. (SPIxSTAT<15>).SPI1STATbits.SPIEN = 1;while(1){adc_spi_write('U');__delay_us(10);}return (EXIT_SUCCESS);}void adc_spi_write(unsigned char data){CS_DAC = 0;/* 5. Write the data to be transmitted to the SPIxBUFregister. Transmission (and reception) will startas soon as data is written to the SPIxBUFregister.*/SPI1BUF = data;/*bit 1 SPITBF: SPIx Transmit Buffer Full Status bit1 = Transmit has not yet started, SPIxTXB is full0 = Transmit has started, SPIxTXB is emptyIn Standard Buffer mode:Automatically set in hardware when the CPU writes to the SPIxBUF location, loading SPIxTXB.Automatically cleared in hardware when the SPIx module transfers data from SPIxTXB to SPIxSR.*/while(!SPI1STATbits.SPIRBF);CS_DAC = 1;}Thanks, it works it was the reprogrammable pins, I have much to learn around this area.Interesting not sure why the data packets look so dirty.