HCS08QG8 - Bidirectional SPI routine

cancel
Showing results for 
Search instead for 
Did you mean: 

HCS08QG8 - Bidirectional SPI routine

3,286 Views
Contributor III
Hello,
CodeWarrior simulator does not work for this simple bidirectional SPI. Note, the device is a SPI compatible DAC (MAX548A) and only bytes are tranferred, no reads
The simulator does not set the second SPSTEF flag. The first SPSTEF is set almost immediately due to an idle SPI. Rather, the simulator sets SPRF when the second transfer starts, but its output mode.
void init_DAC(void)
{
unsigned char temp;

CS = LOW;
temp = SPIS;
SPID = 0xFF;
while(!SPIS_SPTEF);
temp = SPIS;
SPID = 0x00;
while(!SPIS_SPTEF);
while(SCLK);
CS = HIGH;
}
Note, CPOL and CPHA are 0 according to the MAX548A datasheet.


Alban Edit: FSL Part Number in Subject line.

Message Edited by Alban on 2007-03-14 11:33 AM

Labels (1)
0 Kudos
6 Replies

45 Views
Contributor III
I forgot to mention that its a HCS08QG8.
 
Upon further investigation, a small delay is requred between SCID writes.  The simulator indicates the two bytes sent.
 
void init_DAC(void)
{
 unsigned char temp;
 
 CS = LOW;
 temp = SPIS;
 SPID = CONTROL_BYTE1;
 while(!SPIS_SPTEF);
 
  temp = 5;
  while(--temp);     // delay
 temp = SPIS;
 SPID = DAC_INIT_VALUE;
 while(!SPIS_SPTEF);
 while(SCLK);
 CS = HIGH;
}
 
Remark on the SPRF flag, it will get set in single wire bidirectional mode when the BIDIROE is set (output )? 
0 Kudos

45 Views
Senior Contributor IV
Hi FC,
 
If this is the case then it would be due to imperfect simulation.
On the actual device if you know there are no pending SPI transfers you can load SPID twice in a row as in:
SPID = CONTROL_BYTE1;
SPID = DAC_INIT_VALUE;
then just hang around till its done to drop the CS. The first write falls through to the shift register faster than you can load the next byte in.
 
BTW what is:
while(SCLK);
 

 
0 Kudos

45 Views
Contributor III
Hello All,
 
The back to back writes makes sense because it will wake only 2 clock cyles for the first SPSTEF flag to set. 
 
#define SCLK  PTBD_PTBD2
 
while(SCLK);
 
Maybe not needed, but its to ensure the SPI clock is low before raising the CS line. It is in one of application notes.
 
Also, the simulator does show the SPTEF flag low on the second write.  The SPI clock is set to 1MHz, this flag should be abled to be viewed by single stepping. 
 
Clarrify this, it appears the SPRF flag will get set even when the SPI is set to output in singe wire mode?
0 Kudos

45 Views
Senior Contributor IV
Hi FC,
 
As the simulator, as is usual, steps instructions and not cycles, you will not see the flag as it is on for less than an instruction.
I believe the SPRF flag functions as normal even though valid data is not being clocked in in this mode. This is also because "data finished being shifted in" is exactly the same as "data finished being shifted out"
 
0 Kudos

45 Views
Contributor I
Here is the way I have done it using the 9S08AW32.  Should work the same.
 
Note:  This was ported from some old 705 code, so the X register is used to manipulate and maintain a stack(used too much in the code to change this).
 
Hope it helps.
 
;
; Read in a Word from the EEPROM
; E - TOS = Address of the Word
; R - TOS & TOS+1 = Word Read
; L - A
;
RD_93XX:
 LDA SPI1S   ;dummy read to clear flags
 LDA SPI1D   ;dummy read to clear Data reg
 LDA #$80  ;Add Read Command
 STA ,X   ;Save Command Bits
 LDA 1,X   ;Load Address from Para Stack
 AND #$3F  ;Mask Address Bits
 ORA ,X   ;Add Command Bits
 STA 1,X   ;Store on Parameter Stack
 ; write command
 PUL_A         ;Load Character from Stack
 STA SPI1D      ;Send Character
 BSR WAIT_SPI    ;wait for spi to finish
 LDA SPI1D       ;dummy read to clear Data reg
 ; READ BYTE
 STA SPI1D      ;dummy write
 BSR WAIT_SPI    ;wait for spi to finish
 LDA SPI1D       ;read byte
 STA ,X          ;store byte
 DECX        ;Dec Parameter Stack Ptr
 ; READ BYTE
 STA SPI1D      ;dummy write
 BSR WAIT_SPI    ;wait for spi to finish
 LDA SPI1D       ;read byte
 STA ,X          ;store byte
 DECX        ;Dec Parameter Stack Ptr
 RTS             ;return
 
;
; Write to EEPROM
; E - TOS = Address of EEPROM
;     TOS+1 & TOS+2 = Word to be Sent
; R - none
; L - A
;
WR_93XX:
 LDA SPI1S   ;dummy read to clear flags
 LDA SPI1D   ;dummy read to clear Data reg
 LDA #$40  ;Write Command
 STA ,X   ;Save Command Bits
 LDA 1,X   ;Load Address from Para Stack
 AND #$3F  ;Mask Address Bits
 ORA ,X   ;Add Command Bits
 STA 1,X   ;Store on Parameter Stack
 ; write command
 PUL_A         ;Load Character from Stack
 STA SPI1D      ;Send Character
 BSR WAIT_SPI    ;wait for spi to finish
 LDA SPI1D       ;dummy read to clear Data reg
 JSR SWAP   ; Swap Bytes
 ;write byte
 PUL_A         ; Load Character from Stack
 STA SPI1D      ; Send Character
 BSR WAIT_SPI    ;wait for spi to finish
 LDA SPI1D       ;dummy read to clear Data reg
 ;write byte
 PUL_A         ; Load Character from Stack
 STA SPI1D      ; Send Character
 BSR WAIT_SPI    ;wait for spi to finish
 LDA SPI1D       ;dummy read to clear Data reg
 RTS
 
; WAIT FOR SPI TRANSFER TO COMPLETE
WAIT_SPI:
 BRSET SPI1S_SPTEF,SPI1S,WAIT_SPI0 ; Check for Xmit Reg Empty
 JSR PAUSE      ; No Wait
 BRA WAIT_SPI
WAIT_SPI0:
 RTS
0 Kudos

45 Views
Specialist III
Hello,
 
Whether you use the returned data or not, I believe you will need to read SPID, with SPIF flag set, to prevent an over-run condition.  You will also need to wait until SPIF flag is set (for the second byte) before raising CS.
 
Perhaps the following modified code -
 
void init_DAC(void)
{
   unsigned char temp;
 
   CS = LOW;
   temp = SPIS;   /* SPTEF flag assumed already set */
   SPID = 0xFF;   /* First command byte */
   while (!SPIS_SPIF);
   temp = SPID;   /* Clears SPIF flag */
   SPID = 0x00;   /* Second command byte */
   while (!SPIS_SPIF);
   temp = SPID   /* Clears SPIF flag */
   CS = HIGH;
}
 
Regards,
Mac
 

Message Edited by bigmac on 2007-03-1401:35 PM

0 Kudos