• AVR Freaks

Helpful ReplyHot!Unable to receive SPI to a PIC16F1773

Author
GregToombs
Starting Member
  • Total Posts : 50
  • Reward points : 0
  • Status: offline
2020/12/08 14:02:18 (permalink)
0

Unable to receive SPI to a PIC16F1773

This is a cross-post from Electronics Stack Exchange because I was unable to get any responses, and this is probably a more appropriate forum anyway.
 
I have a PIC16F1773 acting as a fairly simple four-channel DAC for a Raspberry Pi 4. It's receiving garbage data - always the same value, 0x25 regardless of input.
 
I will edit for more details.
#1
GregToombs
Starting Member
  • Total Posts : 50
  • Reward points : 0
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/08 14:05:04 (permalink)
0
I can basically rule out the application code, ioctl calls and Pi hardware as the source of my problem since the SPI clock and data seem well-formed on the scope. Only SCK and MOSI are shown; MISO doesn't carry any data and is currently pulled up to the Pi's 3v3 supply.
#2
GregToombs
Starting Member
  • Total Posts : 50
  • Reward points : 0
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/08 14:06:47 (permalink)
0
The following shows the Pi sending 0x20:

#3
GregToombs
Starting Member
  • Total Posts : 50
  • Reward points : 0
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/08 14:07:27 (permalink)
0
This seems compatible with the PIC's Figure 32-10 SPI-mode waveform with CKE=1:
 

 
The PIC runs on 5.2 V, but a level shifter for input should not be necessary because it specifies TTL-level input high of 2V for Vdd between 4.5V and 5.5V, which it is.
 
#4
GregToombs
Starting Member
  • Total Posts : 50
  • Reward points : 0
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/08 14:08:13 (permalink)
0
The pin connections for the current setup are:
 

Things I have tried:
  • Varying the source frequency from 50kHz to 1MHz
  • Shorting the PIC's MOSI to ground
  • Shorting the PIC's MOSI to Vdd
  • Sending all 0x00
  • Sending all 0xFF
In all cases, the in-circuit debugger shows that the MSSP serial buffer receives 0x25.
 
 
#5
GregToombs
Starting Member
  • Total Posts : 50
  • Reward points : 0
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/08 14:09:54 (permalink)
0
The full firmware:
 
#include <xc.inc>


; CONFIG1
#if IsDebug==true
#warning Programming for debug mode
config WDTE=OFF ; Mandatory for debug: watchdog disabled
config PWRTE=OFF ; Power-up timer disabled
#else
config WDTE=ON ; Watchdog timer enabled even in sleep
config PWRTE=ON ; Power-up timer enabled
#endif
config FOSC=INTOSC ; RA7 has I/O. High-freq intern osc (HFINTOSC) used.
config MCLRE=ON ; Memory clear enabled, weak pull-up enabled
config CP=OFF ; Code protection off
config BOREN=ON ; Brown-out reset enabled
config CLKOUTEN=OFF ; RA6 has I/O, no clock out
config IESO=OFF ; No internal-external clock switchover
config FCMEN=OFF ; No fail-safe clock monitoring

; CONFIG2
config WRT=ALL ; All flash memory self-writes disabled
config PPS1WAY=ON ; Peripheral pin select only unlocked once
config ZCD=OFF ; Zero-crossing detect disabled by default
config PLLEN=ON ; Enable 4x phase-locked loop for internal osc
config STVREN=ON ; Stack over/underflow reset enabled
config BORV=HI ; Brown-out threshold is 2.7V typ
config LPBOR=ON ; Low-power brown-out reset enabled
; leave DEBUG up to the programmer
config LVP=OFF ; Low-voltage programming disabled


; If RAM is needed - which it currently isn't, outside of SFRs
; psect variables, class=COMMON, space=SPACE_DATA, delta=1, noexec
; some_var:
; ds 1


; A labelled program section (psect) that does not require ROM paging
code_psect macro name
psect psect_&name, class=NEARCODE, space=SPACE_CODE, delta=2
name:
endm

code_psect por_vec
; Oscillator config
banksel OSCCON
; IRCF INTOSC PRIMUX PLLMUX SCS FOSC
; 0111 500kHz 1 0 00 500kHz
bcf IRCF0
; 0110 250kHz 1 0 00 250kHz
bsf IRCF3
; 1110 8MHz 1 1 00 32MHz
; At this point, everything should become "ready": MFIOFR, PLLR, HFIOFR;
; HFINTOSC PLL should lock within 2% (HFIOFL);
; and it should stabilise within 0.5% (HFIOFS).
goto init

code_psect isr_vec
; Unused; interrupts are used to wake up main
retfie

code_psect init
; Leave WDT at default 2s
; OSCCON, PIEx and TRIS share bank 1 - set the latter two in sequence here

select_interrupts:
bsf SSP1IE ; SPI receive

init_ports:
; RA1: ana out OPA1OUT (DAC1)
; RA4: ana out DAC4
; RB1: ana out OPA2OUT (DAC2)
; RB6: dig in ICSPCLK
; RB7: dig in ICSPDAT
; RC1: SDI (MOSI)
; RC2: SDO (MISO)
; RC3: SCK
; RC4: dig out COG1A
; RC6: ana out OPA3OUT (DAC5)
; RE3: dig in MCLR
; Unused pins dig out driven to 0.
; Leave slew rate limitation enabled.
; Leave WPUEN disabled.

; Tristates
movlw 0b00010010
movwf TRISA
movlw 0b11000010
movwf TRISB
movlw 0b01001010
movwf TRISC

; Zero output latches
banksel LATA
clrf LATA
clrf LATB
clrf LATC

; The only analogue pins are for DAC/OPA
banksel ANSELA
movlw 0b00010010
movwf ANSELA
movlw 0b00000010
movwf ANSELB
movlw 0b01000000
movwf ANSELC

; Mostly Schmitt trigger levels; but:
; In practice, the RPI sends an SPI clock of 0-3V, and a MOSI of
; 0-3.28V. With our Vdd=5.2V,
; TTL in: 0.80-2.00
; ST in: 1.04-4.16
; out: 0.60-4.50
; So Schmitt levels are not appropriate for RC1,3.

banksel INLVLA
comf INLVLA ; Default TTL; switch to ST
comf INLVLB ; Default TTL; switch to ST
; Default ST; switch to TTL for RC1,3
movlw 0b11110001
movwf INLVLC

; To do a simple level-shift from our 5.2V to the Rpi's 3.3V on MISO, we
; add an external pullup to its 3.3V pin and put MISO on RC2 in open-drain
banksel ODCONC
bsf ODC2

init_pps:
; RC1: SDI (MOSI)
; RC2: SDO (MISO)
; RC3: SCK
; RC4: COG1A
banksel RC2PPS
movlw 0b100011 ; SDO
movwf RC2PPS
movlw 0b000101 ; COG1A
movwf RC4PPS

banksel PPSLOCK
movlw 0b010001 ; RC1
movwf SSPDATPPS
movlw 0b010011 ; RC3
movwf SSPCLKPPS

movlw 0x55
movwf PPSLOCK
movlw 0xAA
movwf PPSLOCK
bsf PPSLOCKED


init_rpi_spi:
; MSSP SPI child mode on all-PPS selected pins
; SCK, SDI (MOSI), SDO (MISO)
banksel SSP1CON1

; SPI child mode, SS pin control disabled
; clock = SCK pin with idle-low polarity
movlw SSP1CON1_SSPEN_MASK | 0b0101
movwf SSP1CON1

; Data read on low-to-high clock
bsf CKE

; TSCHSCK input high (also low) time, child mode, >= Tcy + 20 (ns)
; Instruction cycle time Tcy = 125 ns
; Sclk <= 3.45MHz from the Pi

enable_interrupts:
bsf PEIE ; Every interrupt we use is on a "peripheral"
; We don't actually need an interrupt vector; we just use interupts to wake
; bsf GIE

main:
rx_reset:
banksel PIR1

sleep ; until we get a serial interrupt for the first byte
; Only one interrupt is interesting at this point, so don't bother checking
; btfss SSP1IF
; goto rx_reset
bcf SSP1IF

banksel SSP1BUF
movf SSP1BUF ; Load from MSSP receive buffer into W

goto rx_reset

end por_vec

 
#6
ric
Super Member
  • Total Posts : 30239
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/08 14:39:33 (permalink) ☄ Helpfulby GregToombs 2020/12/08 14:52:38
+2 (2)
 movf SSP1BUF ; Load from MSSP receive buffer into W
should be
 movf SSP1BUF,w ; Load from MSSP receive buffer into W

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#7
GregToombs
Starting Member
  • Total Posts : 50
  • Reward points : 0
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/08 14:53:43 (permalink)
0
ric
movf SSP1BUF ; Load from MSSP receive buffer into W

should be
movf SSP1BUF,w ; Load from MSSP receive buffer into W




Wow, I can't believe it was that simple. What does the former syntax even do, in that case?
#8
ric
Super Member
  • Total Posts : 30239
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/08 15:01:58 (permalink)
+2 (2)
GregToombs
...
Wow, I can't believe it was that simple. What does the former syntax even do, in that case?



I assume you are using pic-as. It is probably emulating MPASM, which defaults to ",f" as the suffix if you omit it.

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#9
GregToombs
Starting Member
  • Total Posts : 50
  • Reward points : 0
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/09 13:38:27 (permalink)
0
That's... not great. I'd hope that either the default would be something used more frequently (W), issue a warning about the default during assembly, or better yet have no default at all and force the programmer to be explicit. Oh well. Thanks very much.
#10
ric
Super Member
  • Total Posts : 30239
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: offline
Re: Unable to receive SPI to a PIC16F1773 2020/12/09 13:59:44 (permalink)
+2 (2)
GregToombs
That's... not great. I'd hope that either the default would be something used more frequently (W),

",w" isn't necessarily "used more frequently".
The suffix applies to all the incf, decf, rlf, etc instructions, not just movf.
With those, the target is more often the register itself (,f), not W.
 I agree, I would prefer it to not have a default at all.
 
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#11
Jump to:
© 2021 APG vNext Commercial Version 4.5