CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Can't read data with SPI using PIC16f18346
Goto page Previous  1, 2, 3, 4, 5, 6, 7  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
L.T.



Joined: 24 Jul 2020
Posts: 62

View user's profile Send private message

PostPosted: Thu Aug 20, 2020 2:08 am     Reply with quote

And you mean, should not I use "use spi" function? Or should I change only LSB_FIRST settings? When I delete "LSB_FIRST" from the code, I can't get the correct frequency again. And data destroyed.

If I want to set as LSB first manually, how should I write? Is it correct to write as follows?
Code:
uint8 usscSPI_transfer(uint8 _data) {

    // MSB --> LSB /////////////////////////////////////////////////
   _data = (((_data & 0b11110000)>>4) | ((_data & 0b00001111)<<4));
   _data = (((_data & 0b11001100)>>2) | ((_data & 0b00110011)<<2));
   _data = (((_data & 0b10101010)>>1) | ((_data & 0b01010101)<<1));
   ////////////////////////////////////////////////////////////////

   return spi_xfer(PGA,_data,8);
}
L.T.



Joined: 24 Jul 2020
Posts: 62

View user's profile Send private message

PostPosted: Thu Aug 20, 2020 2:13 am     Reply with quote

PCM programmer wrote:
He has a bit reversal routine. It's this clever code in his first post.
Code:
// MSB --> LSB
_data = (((_data & 0b11110000)>>4) | ((_data & 0b00001111)<<4));
_data = (((_data & 0b11001100)>>2) | ((_data & 0b00110011)<<2));
_data = (((_data & 0b10101010)>>1) | ((_data & 0b01010101)<<1));


I deleted "LSB_FIRST" and I tried the code as below. But I get same signal like before. Frequency is not correct.

Code:
#include "16F18346.h"
#use delay(internal=16000000)
#use spi(DI=PIN_B4, DO=PIN_C7, CLK=PIN_B6, baud=1000000, MODE=2, stream=PGA)

uint8 usscSPI_transfer(uint8 _data) {

    // MSB --> LSB /////////////////////////////////////////////////
   _data = (((_data & 0b11110000)>>4) | ((_data & 0b00001111)<<4));
   _data = (((_data & 0b11001100)>>2) | ((_data & 0b00110011)<<2));
   _data = (((_data & 0b10101010)>>1) | ((_data & 0b01010101)<<1));
   ////////////////////////////////////////////////////////////////

   return spi_xfer(PGA,_data,8);
}

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Aug 20, 2020 2:20 am     Reply with quote

I was just informing Ttlemah about it. I didn't want to start a big mess.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Aug 20, 2020 2:45 am     Reply with quote

Problem is though that he needs to do it on the read data as well.
L.T.



Joined: 24 Jul 2020
Posts: 62

View user's profile Send private message

PostPosted: Thu Aug 20, 2020 2:51 am     Reply with quote

Ttelmah wrote:
Problem is though that he needs to do it on the read data as well.


I tried as below but it didn't work again.

Code:
#include "16F18346.h"
#fuses RSTOSC_HFINTRC,LVP,DEBUG
#use delay(internal=16000000)
#use spi(DI=PIN_B4, DO=PIN_C7, CLK=PIN_B6, baud=1000000, MODE=2, stream=PGA)

uint8 usscSPI_transfer(uint8 _data) {
uint8 _regdata=0;
    // MSB --> LSB /////////////////////////////////////////////////
   _data = (((_data & 0b11110000)>>4) | ((_data & 0b00001111)<<4));
   _data = (((_data & 0b11001100)>>2) | ((_data & 0b00110011)<<2));
   _data = (((_data & 0b10101010)>>1) | ((_data & 0b01010101)<<1));
   ////////////////////////////////////////////////////////////////

_regdata = spi_xfer(PGA,_data,8);
   // LSB --> MSB /////////////////////////////////////////////////
   _regdata = (((_regdata & 0b11110000)>>4) | ((_regdata & 0b00001111)<<4));
   _regdata = (((_regdata & 0b11001100)>>2) | ((_regdata & 0b00110011)<<2));
   _regdata = (((_regdata & 0b10101010)>>1) | ((_regdata & 0b01010101)<<1));
   ////////////////////////////////////////////////////////////////
return _regdata;
}
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Aug 20, 2020 10:43 am     Reply with quote

just some comments...

I'm wondering if the BYTES as well as their bits, have to be reversed ?
Say a 'result' from the device is 3 BYTES long. Are they in ABC order and need to be reversed to CBA , as well as all the bits within 'A', 'B' and 'C' ??

Then there's the 'when in UART mode, some 'address' ' is in the data stream though I have no idea how THAT gets handled when in SPI mode.

It'd be nice to see a documented (every line commented) sample of 'demo' code.....
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Aug 20, 2020 12:49 pm     Reply with quote

He is reading the bytes individually, so it is easy to reverse this order.
However the time overhead of the bit reversals will be significant. It's
just that the chip is really designed to talk to a UART, not to a SPI
peripheral, so works with the synchronous serial standard of least
significant bit first, not the SPI standard of most significant bit first.
As he was told at the start, much easier to use the UART. Since it is
perfectly possible to put multiple devices on the one UART, but just
reprogramming the device address, he does seem determined to do this
the hardest possible way..... Sad
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Aug 20, 2020 2:16 pm     Reply with quote

hmm.. after 5 pages I'm confused even more but wondering if the 'working MSP code' is using SPI or the default UART interface ?
it'd be nice to see the TI SPI code.....
L.T.



Joined: 24 Jul 2020
Posts: 62

View user's profile Send private message

PostPosted: Sun Aug 23, 2020 11:07 pm     Reply with quote

I can share with you TI codes if you give your email. MSP's original code is included SPI, UART, even OWU. All of these in the same code. You can select commode and use with all versions.

I think, the problem is SPI's speed. I can't change speed. I can send the correct data, slave can answer, but I can't read the distance because of communication's speed.
L.T.



Joined: 24 Jul 2020
Posts: 62

View user's profile Send private message

PostPosted: Mon Aug 24, 2020 4:33 am     Reply with quote

L.T. wrote:
I can share with you TI codes if you give your email. MSP's original code is included SPI, UART, even OWU. All of these in the same code. You can select commode and use with all versions.

I think, the problem is SPI's speed. I can't change speed. I can send the correct data, slave can answer, but I can't read the distance because of communication's speed.


In the demo code, SPI communication is descripted as below:

Code:

#include <msp430.h>
#include <stdint.h>
#include "pga460_spi_430.h"
#include <Energia.h>

// AW: re-allocate SPI port from B0 to B1 pins
static const uint8_t PGA460_SS      = 33;     /* P4.0 */
static const uint8_t PGA460_SCK     = 34;     /* P4.3 */
static const uint8_t PGA460_MOSI    = 10;     /* P4.2 */
static const uint8_t PGA460_MISO    = 9;     /* P4.1 */

#if defined(__MSP430_HAS_USCI_B0__) || defined(__MSP430_HAS_USCI_B1__) || defined(__MSP430_HAS_USCI__)

/**
 * USCI flags for various the SPI MODEs
 *
 * Note: The msp430 UCCKPL tracks the CPOL value. However,
 * the UCCKPH flag is inverted when compared to the CPHA
 * value described in Motorola documentation.
 */

#define SPI_MODE_0 (UCCKPH)             /* CPOL=0 CPHA=0 */
#define SPI_MODE_1 (0)                    /* CPOL=0 CPHA=1 */
#define SPI_MODE_2 (UCCKPL | UCCKPH)    /* CPOL=1 CPHA=0 */
#define SPI_MODE_3 (UCCKPL)             /* CPOL=1 CPHA=1 */

#define SPI_MODE_MASK (UCCKPL | UCCKPH)

/**
 * spi_initialize_pga460() - Configure USCI UCB1 for SPI mode
 *
 * P2.0 - CS (active low)   // AW --> P4.0 for F5529 (NC on BP)
 * P1.5 - SCLK           // AW --> P4.3 for F5529
 * P1.6 - MISO aka SOMI    // AW --> P4.2 for F5529
 * P1.7 - MOSI aka SIMO    // AW --> P4.1 for F5529
 *
 */

/* Calculate divisor to keep SPI clock close to 4MHz but never over */
#ifndef SPI_CLOCK_SPEED
#define SPI_CLOCK_SPEED 4000000L
#endif

#if F_CPU < 4000000L
#define SPI_CLOCK_DIV() 1
#else
#define SPI_CLOCK_DIV() ((F_CPU / SPI_CLOCK_SPEED) + (F_CPU % SPI_CLOCK_SPEED == 0 ? 0:1))
#endif

#define SPI_CLOCK_DIV_DEFAULT (F_CPU / 4)

void usscSPI_begin(void)
{
   UCB1CTL1 = UCSWRST | UCSSEL_2;      // Put USCI in reset mode, source USCI clock from SMCLK
   UCB1CTL0 = SPI_MODE_0 | UCMSB | UCSYNC | UCMST;  // Use SPI MODE 0 - CPOL=0 CPHA=0

    /* Set pins to SPI mode. */
   pinMode_int(PGA460_SCK, PORT_SELECTION0 | (PM_UCB1CLK << 8));//SPISCK_SET_MODE);
   pinMode_int(PGA460_MOSI, PORT_SELECTION0 | (PM_UCB1SDA << 8));//SPIMOSI_SET_MODE);
   pinMode_int(PGA460_MISO, PORT_SELECTION0 | (PM_UCB1SCL << 8));//SPIMISO_SET_MODE);

   UCB1BR0 = SPI_CLOCK_DIV() & 0xFF;   // set initial speed to 4MHz
   UCB1BR1 = (SPI_CLOCK_DIV() >> 8 ) & 0xFF;

   UCB1CTL1 &= ~UCSWRST;             // release USCI for operation
}

/**
 * spi_disable_pga460() - put USCI into reset mode
 */
void usscSPI_end(void)
{
    UCB1CTL1 |= UCSWRST;                // Put USCI in reset mode
}

/**
 * spi_send() - send a byte and recv response
 */
uint8_t usscSPI_transfer(const uint8_t _data)
{
   UCB1TXBUF = _data; // setting TXBUF clears the TXIFG flag
   while (UCB1STAT & UCBUSY)
      ; // wait for SPI TX/RX to finish

   return UCB1RXBUF; // reading clears RXIFG flag
}

/***SPI_MODE_0
 * spi_set_divisor_pga460() - set new clock divider for USCI
 *
 * USCI speed is based on the SMCLK divided by BR0 and BR1
 *
 */
void usscSPI_setClockDivider(const uint16_t clkdiv)
{
   UCB1CTL1 |= UCSWRST;      // go into reset state
   UCB1BR0 = clkdiv & 0xFF;
   UCB1BR1 = (clkdiv >> 8 ) & 0xFF;
   UCB1CTL1 &= ~UCSWRST;      // release for operation
}

/**
 * spi_set_bitorder_pga460(LSBFIRST=0 | MSBFIRST=1)
 */
void usscSPI_setBitOrder(const uint8_t order)
{
    UCB1CTL1 |= UCSWRST;        // go into reset state
    UCB1CTL0 = (UCB1CTL0 & ~UCMSB) | ((order == 1 /*MSBFIRST*/) ? UCMSB : 0); /* MSBFIRST = 1 */
    UCB1CTL1 &= ~UCSWRST;       // release for operation
}

/**
 * spi_set_datamode_pga460() - mode 0 - 3
 */
void usscSPI_setDataMode(const uint8_t mode)
{
    UCB1CTL1 |= UCSWRST;        // go into reset state
    switch(mode) {
    case 0: /* SPI_MODE0 */
        UCB1CTL0 = (UCB1CTL0 & ~SPI_MODE_MASK) | SPI_MODE_0;
        break;
    case 1: /* SPI_MODE1 */
        UCB1CTL0 = (UCB1CTL0 & ~SPI_MODE_MASK) | SPI_MODE_1;
        break;
    case 2: /* SPI_MODE2 */
        UCB1CTL0 = (UCB1CTL0 & ~SPI_MODE_MASK) | SPI_MODE_2;
        break;
    case 4: /* SPI_MODE3 */
        UCB1CTL0 = (UCB1CTL0 & ~SPI_MODE_MASK) | SPI_MODE_3;
        break;
    default:
        break;
    }
    UCB1CTL1 &= ~UCSWRST;       // release for operation
}
#else
    //#error "Error! This device doesn't have a USCI peripheral"
#endif


In the code I wrote, SPI communication settings are described as below:
Code:

#include "16F18346.h"
#device ADC=10
#use delay(internal=16000000)
#use spi(DI=PIN_B4, DO=PIN_C7, CLK=PIN_B6, baud=4000000, MODE=2, stream=PGA)

#include "PIC16F18346_PIN.h"
   uint8 _regdata=0;

//extern SPIClass usscSPI;
uint8 usscSPI_transfer(uint8 _data) {
   

    // MSB --> LSB /////////////////////////////////////////////////
   _data = (((_data & 0b11110000)>>4) | ((_data & 0b00001111)<<4));
   _data = (((_data & 0b11001100)>>2) | ((_data & 0b00110011)<<2));
   _data = (((_data & 0b10101010)>>1) | ((_data & 0b01010101)<<1));
   ////////////////////////////////////////////////////////////////
   
   _regdata = spi_xfer(PGA,_data,8);
   // LSB --> MSB /////////////////////////////////////////////////
   _regdata = (((_regdata & 0b11110000)>>4) | ((_regdata & 0b00001111)<<4));
   _regdata = (((_regdata & 0b11001100)>>2) | ((_regdata & 0b00110011)<<2));
   _regdata = (((_regdata & 0b10101010)>>1) | ((_regdata & 0b01010101)<<1));
   ////////////////////////////////////////////////////////////////
   
   return _regdata;
   
}

void usscSPI_begin()
{

}

void usscSPI_end()
{

}

void usscSPI_setBitOrder(uint8 bitOrder)
{

}

void usscSPI_setDataMode(uint8 mode)
{

}

void usscSPI_setClockDivider(uint8 rate)
{

}
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Aug 24, 2020 5:02 am     Reply with quote

re:
I think, the problem is SPI's speed. I can't change speed. I can send the correct data, slave can answer, but I can't read the distance because of communication's speed.
...
Are you saying that you can select and set various bits in the device registers and that they are correct ?
When you say 'slave answers' , does that mean it sends the proper data ?
How have you confirmed this ?
If the slave answers correctly it should not be an SPI 'speed' problem.

Have you used a 'scope to see the waveforms ? Are they within PIC spec ? Are they solid ,clean square wave ?

The speed is set in the #use SPI(...) directive. You can cut a very simple program to just send 0x55 out forever and receive it,say every 1/2 second, display result on PC or LCD. A scope will show the waveform and you can calculate the actual speed.

I read that device uses the same pins for UART and SPI and ??, so the actual configuration or setup code probably has to tell the device HOW to communicate. I'd like to see actual stand alone SPI interface 'driver' code from TI. Something NOT using some IDE or other 'canned' AP. I've never liked 'multi-use' pins, it's too easy for someone's 'default' to not be what you want or to change a pin a 'special sequence' has to be followed, if you don't do that correctly, it reverts back to another setup WITHOUT telling you you did it wrong.

In the TI code you post just above this post, there's 4 header files that are included, we need to see what's in them. It's quite possible something in one of them is altering the code somehow. I didn't see anything in that code that 'configures' the I/O pins to be 'SPI' pins not 'UART' pins....


Last edited by temtronic on Mon Aug 24, 2020 5:18 am; edited 1 time in total
L.T.



Joined: 24 Jul 2020
Posts: 62

View user's profile Send private message

PostPosted: Mon Aug 24, 2020 5:17 am     Reply with quote

temtronic wrote:
re:
I think, the problem is SPI's speed. I can't change speed. I can send the correct data, slave can answer, but I can't read the distance because of communication's speed.
...
Are you saying that you can select and set various bits in the device registers and that they are correct ?
When you say 'slave answers' , does that mean it sends the proper data ?
How have you confirmed this ?
If the slave answers correctly it should not be an SPI 'speed' problem.

Have you used a 'scope to see the waveforms ? Are they within PIC spec ? Are they solid ,clean square wave ?

The speed is set in the #use SPI(...) directive. You can cut a very simple program to just send 0x55 out forever and receive it,say every 1/2 second, display result on PC or LCD. A scope will show the waveform and you can calculate the actual speed.

I read that device uses the same pins for UART and SPI and ??, so the actual configuration or setup code probably has to tell the device HOW to communicate. I'd like to see actual stand alone SPI interface 'driver' code from TI. Something NOT using some IDE or other 'canned' AP.


I analyzed the signals before using MSP and demo code. Now I'm getting similar answers from PGA. When I changed ultrasonic sensor's place, signal was changing in relation to the distance. But signal's period is not normal. I can describe like this.

If When the MSP ready code is used, the signals can be described symbolically as follows:

I send 1st data like this: AAAA
PGA answered like this: TTTT
There is a time gap here.
I send 2st data like this: CCCCRRRRCCCCRRRR
PGA answered in relation to the distance like this: BBBBAAAFFFFEEEE

There is a time gap here.

And again:

I send 1st data like this: AAAA
PGA answered like this: TTTT
There is a time gap here.
I send 2nd data like this: CCCCRRRRCCCCRRRR
PGA answered in relation to the distance like this: BBBBAAAFFFFEEEE

There is a time gap here.

And again...

But when I send data using my code.
PIC sends all data twice at a time.: AAAACCCCRRRRCCCCRRRR AAAACCCCRRRRCCCCRRRR
PGA answered in relation to the distance like this: TTTTBBBBAAAFFFFEEEE TTTTBBBBAAAFFFFEEEE

There is a time gap here.

And again:
PIC sends all data twice at a time.: AAAACCCCRRRRCCCCRRRR AAAACCCCRRRRCCCCRRRR
PGA answered in relation to the distance like this: TTTTBBBBAAAFFFFEEEE TTTTBBBBAAAFFFFEEEE

There is a time gap here.

And again....

The letters are only symbolic and do not contain any meaning.

I don't understand why this is so. The data are sent one after the other, they are answered one after the other and the distance cannot be measured.
L.T.



Joined: 24 Jul 2020
Posts: 62

View user's profile Send private message

PostPosted: Mon Aug 24, 2020 5:56 am     Reply with quote

temtronic wrote:
re:
In the TI code you post just above this post, there's 4 header files that are included, we need to see what's in them. It's quite possible something in one of them is altering the code somehow. I didn't see anything in that code that 'configures' the I/O pins to be 'SPI' pins not 'UART' pins....


In the TI code, UART pins and SPI pins are different. I just sent you the part with SPI settings. If UART is to be used, UART is selected from the commode and the pins of PGA are connected to the UART pins of the MSP.
L.T.



Joined: 24 Jul 2020
Posts: 62

View user's profile Send private message

PostPosted: Mon Aug 24, 2020 8:05 am     Reply with quote

I looked to the SSP1CON1 register, and I saw I couldn't change clock if I change baud. I mean, I can't affect SPI frequency. You can see the register's value in picture below.

[img]https://imgur.com/CkRpEcH[/img]

[img]https://imgur.com/C1SHvDT[/img]

[img]https://imgur.com/xgieVfP[/img]
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Aug 24, 2020 8:52 am     Reply with quote

L.T. wrote:
I looked to the SSP1CON1 register, and I saw I couldn't change clock if I change baud.

The baud rate is stored in the SSPADD register. This is stated in the PIC
data sheet.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4, 5, 6, 7  Next
Page 5 of 7

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group