mc9s12c32 transmit or receive 12 bits on SPI

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

mc9s12c32 transmit or receive 12 bits on SPI

2,599 Views
tabull
Contributor I
    Some chips such as the DS1626 temperature sensor transmit something other than 8 bits or a multiple of 8 bits.  Sending 12 bits to the DS1626 is not a problem as one can send two bytes and the DS1626 will simply ignore the extra bits.  Receiving 12 bits from the DS1626 is something I cannot figure out.

   The SPI will not receive one byte and then 4 more bits, or at least I cannot figure out how to do it.  Is there some way to do this?  I can transmit and receive DS1626 data by bit-banging on PTT pins, but I'd like to use the SPI.  I've tried to use the routines from both Professor Cady's and Professor Valvano's texts, but to no avail.

Can anyone help?

Thanks,
Dan

Labels (1)
0 Kudos
6 Replies

555 Views
JimDon
Senior Contributor III
First, you have this set up to use both SI and SO.

When send FF, you are actually reading data back because the '1' you are sending will be pulled low if the chip wants to send a '0'. We say that the 0 is dominate and the 1 is recessive.

So you send the AAh command which is 8 bits, then send FFh and read back the first 8 bits, then send FFh and read back the last 4 bits, but you ignore the lower 4 bits.







0 Kudos

555 Views
bigmac
Specialist III
Hello,
 
To further clarify some of the issues raised by Jim D -
 
You will need to select bi-directional mode (SPICR2_SPC0 = 1), and then control the data direction using the SPICR2_BIDIROE bit.  The bit would be set during the send of the command byte, and cleared immediately prior to the data being returned (i.e. the values 0xFFare sent to the SPI module).  The DQ line of the DS1626 would connect to the MOSI pin of the SPI module.  It is probably a good idea to connect an external pull-up resistor to the line, to cater when both devices are high-Z.
 
The DS1626 requires LS bit sent first, and this will require SPICR1_LSBFE = 1.
 
Regards,
Mac
 
 
 
0 Kudos

555 Views
tabull
Contributor I


bigmac wrote:
Hello,
 
To further clarify some of the issues raised by Jim D -
 
You will need to select bi-directional mode (SPICR2_SPC0 = 1), and then control the data direction using the SPICR2_BIDIROE bit.  The bit would be set during the send of the command byte, and cleared immediately prior to the data being returned (i.e. the values 0xFFare sent to the SPI module).  The DQ line of the DS1626 would connect to the MOSI pin of the SPI module.  It is probably a good idea to connect an external pull-up resistor to the line, to cater when both devices are high-Z.
 
The DS1626 requires LS bit sent first, and this will require SPICR1_LSBFE = 1.
 
Regards,
Mac

I must say I am not familiar with this business of explicitly sending 0xFF. The DS1626 is not an SPI device, and does not have MISO and MOSI pins.  I already had the bidirectional pin set, and I had been experimenting with, quite frankly, everything I could think of, including the BIDIROE bit. Can I use the SPI clock, or must I control the clock with an ordinary I/O pin?

As far as I can see from the Maxim datasheet, RST goes high and the command byte is sent out and the 12 bits (or 8 if reading CONFIG) are sent back, not 16. Am I wrong? I'm completely verblundget about this.

If possible, I would appreciate a more detailed explanation of just how to go about sending 0xFF, and when I must read or write SPIDR and when to read SPISR.  Is there any info online relating to this practice of sending 0xFF?

As I wrote earlier, I have successfully written code to do all this by bit-banging, but I thought the SPI could be used as well, and I think you folks are saying this is correct.  Professor Valvano's code for the DS1620 does not work at all, and I wonder whether the U Texas students ever have to actually try to implement that code.

Oh, well.  Anyway, any help for this poor ChE would be appreciated.

Thanks
Dan
 
0 Kudos

555 Views
bigmac
Specialist III
Hello Dan,
 
To generate a sequence of eight clock pulses for the receipt of each returned data byte, a "dummy" byte needs to be written to SPIDR within the SCI module.  It so happens that 0xFF is a benign value that does not interfere with the data returned from the sensor.  Of course, to return 16 bits of data you would send two dummy bytes in succession.
 
The basic sequence to read temperature data from the sensor, assuming bi-directional mode  -
 
Set BIDIROE control bit for output.
Set RST line to high.
Send command byte and ignore return.
Set BIDIROE control bit for input.
Send first dummy byte and store returned LS byte value.
Send second dummy byte and store returned MS byte value
Clear RST line to low.
 
The following function provides a single SPI data byte transfer in both directions, with appropriate testing and clearing of flags within SPISR  -
 
byte SPI_trans(byte val)
{
  while (SPISR_SPTEF == 0);
  SPIDR = val;
  while (SPISR_SPIF == 0);
  return SPIDR;
}
 
Regards,
Mac
 
0 Kudos

555 Views
tabull
Contributor I


bigmac wrote:
Hello Dan,
 
To generate a sequence of eight clock pulses for the receipt of each returned data byte, a "dummy" byte needs to be written to SPIDR within the SCI module.  It so happens that 0xFF is a benign value that does not interfere with the data returned from the sensor.  Of course, to return 16 bits of data you would send two dummy bytes in succession.
 
The basic sequence to read temperature data from the sensor, assuming bi-directional mode  -
 
Set BIDIROE control bit for output.
Set RST line to high.
Send command byte and ignore return.
Set BIDIROE control bit for input.
Send first dummy byte and store returned LS byte value.
Send second dummy byte and store returned MS byte value
Clear RST line to low.
 
The following function provides a single SPI data byte transfer in both directions, with appropriate testing and clearing of flags within SPISR  -
 
byte SPI_trans(byte val)
{
  while (SPISR_SPTEF == 0);
  SPIDR = val;
  while (SPISR_SPIF == 0);
  return SPIDR;
}
 
Regards,
Mac
 



Well Mac, this is very clear, and very helpful.  I can now read and write both 12 bit and 8 bit registers on the DS1626.  It amazes me how simple these things usually turn out to be, but of course you have to know what you are doing. Which leads me to ask, where can one find out about this technique in the Freescale literature? I have the latest version of the SPI Block Guide, and I can't seem to find anything referring to this. Maybe I'm just not looking in the right place. One can see from Table 4-1 how BIDIROE controls the buffer, but there is no explicit instruction to send a dummy byte to initiate serial data transmission of data in, 0xFF or otherwise.

One other thing. The first read or write of a register always returns 0xFF. For example, after initializing the SPI, if I read the Config register, 0xff is returned. The next read (or write), and all subsequent reads (or writes), are  successful. Any idea why this is so? This is not a serious problem, as I only need to add a read of, say, the CONFIG register to the initialization routine to obviate this, but it's always better to understand. I know that for some CPUs, one must read SPISR and SPIDR after initialization due to a bug, but that doesn't seem to be the case here.

As usual, many thanks for the excellent assistance.

Regards,
Dan

0 Kudos

555 Views
JimDon
Senior Contributor III
Well, I was thinking connecting the DQ line to both in t SI and the SO, but it could work your way fine too, and save a pin.
If you turn it around as Mac suggests, it will not matter what you send.
0 Kudos