SPI2xv and 18F37Q84

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
garryp4
Posts: 126
Joined: Mon May 21, 2007 7:18 am
Location: Loveland, CO USA

SPI2xv and 18F37Q84

Post by garryp4 » Wed Apr 19, 2023 9:17 pm

Due to the availability of the 18F27J13 parts, I have changed to an 18F27Q84. The Vcap has been removed. My code for an SPI real time clock worked fine on the J13 part, but I can not get any response from the Q84 on the scope. Neither from the SCK1 or SDO1. The code is a bit lengthy but is just more of the same for seconds, minutes, etc. The pins are SCK1 = RC3 (default from pin allocation table), SDI1 = RC4 (default), and SDO1 = RC5 (mapped). Any help where I am going wrong would be greatly appreciated.

Code: Select all

{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2023 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 2/5/2023                                                       *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
FRAM MEMORY ADDRESSES ($0000 - $1FFF)
ALARM            0000 - 0003   - 1 = SECONDS, 2 = MINUITES, 3 = HOURS
ALARM VALUE      0004 - 0007
}
Module DS1394

#option SPI_SDO = PORTC.5

Include "USART.bas"
Include "SPI2xv.bas"
Include "convert.bas"
Include "system.bas"
Include "utils.bas"
Include "MEM_64K.BAS"


Private Dim
  b1               As Byte,
  b2               As Byte,
  b3               As Byte,
  b4               As Byte
  

Private Structure m_Date_Time
  dt_seconds       As Byte,
  dt_minutes       As Byte,
  dt_hours         As Byte,
  dt_dow           As Byte,
  dt_date          As Byte,
  dt_month         As Byte,
  dt_year          As Byte
End Structure

Private Structure m_Time
  t_seconds        As Byte,
  t_minutes        As Byte,
  t_hours          As Byte
End Structure

Private Structure m_Date
  d_dow            As Byte,
  d_date           As Byte,
  d_month          As Byte,
  d_year           As Byte
End Structure

Private Dim
  red              As PORTA.7,
  green            As PORTA.6,
  mem_cs           As PORTB.2,
  rtc_cs           As PORTB.3,
  time             As m_Time,
  date             As m_Date
   
Private Const
  sec_10_100_read   = $00,
  sec_10_100_write  = $80,
  sec_read          = $01,
  sec_write         = $81,
  min_read          = $02,
  min_write         = $82,
  hour_read         = $03,
  hour_write        = $83,
  dow_read          = $04,
  dow_write         = $84,
  dom_read          = $05,
  dom_write         = $85,
  month_read        = $06,
  month_write       = $86,
  year_read         = $07,
  year_write        = $87,
  alm_10_100_read   = $08,
  alm_10_100_write  = $88,
  alm_sec_read      = $09,
  alm_sec_write     = $89,
  alm_min_read      = $0A,
  alm_min_write     = $8A,  
  alm_hour_read     = $0B,
  alm_hour_write    = $8B,
  alm_dow_read      = $0C,
  alm_dow_write     = $8C,
  control_read      = $0D,
  control_write     = $8D,
  status_read       = $0E,
  status_write      = $8E,
  trickle_read      = $0F,
  trickel_write     = $8F
  
'****************************************************************************
Public Sub RTC_SPI()
  PPSLOCK.0 = 0
  RC5PPS    = $32                      ' RC5 set to SPI1 SDO
  PPSLOCK.0 = 1
  SPI2.Open(SPI_MODE_0,spiOscDiv64,spiSampleEnd)    '
  DelayUS(5)
  Low(rtc_cs)
End Sub
'****************************************************************************
Private Sub SET_TERM_SERIAL()            ' Term emulator rs232
  PPSLOCK.0 = 0
  U1RXPPS  = $17                         ' USART1 RCV = RC6
  RC6PPS   = $20                         ' RC7 = USART1 SND
  PPSLOCK.0 = 1
  USART.SetBaudrate(br9600)              ' Baud rate
  'USART.ReadTerminator = 13
End Sub
'****************************************************************************
Public Sub INIT_RTC()
  RTC_SPI
  SPI2.Transfer(status_write)           '
  SPI2.Transfer($00)                    ' Clear Osc and Alarm flags
  High(rtc_cs)
  
  RTC_SPI
  SPI2.Transfer(control_write)          ' Enable osc, int on batt, enable int, AIE disabled (enabled on alarm set) 
  SPI2.Transfer($24)
  High(rtc_cs)

  RTC_SPI
  SPI2.Transfer(trickel_write)
'  SPI2.Transfer($A5)                    ' No diode, 250 ohm resistor  
  SPI2.Transfer($A6)                    ' No diode, 2K resistor
'  SPI2.Transfer($A7)                    ' No diode, 4K resistor
  High(rtc_cs)

End Sub
'****************************************************************************
Public Function READ_SECONDS() As Byte
  RTC_SPI
  SPI2.Transfer(sec_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_SECONDS(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(sec_10_100_write)
  SPI2.Transfer($00)                    ' Set 10ths and 100ths seconds to 0
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_SECONDS
End Sub
'****************************************************************************
Public Function READ_MINUITES() As Byte
  RTC_SPI
  SPI2.Transfer(min_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_MINUITES(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(min_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_MINUITES
End Sub
'****************************************************************************
Public Function READ_HOUR() As Byte
  RTC_SPI
  SPI2.Transfer(hour_read)
  result = SPI2.Transfer
  High(rtc_cs)
 End Function  
'****************************************************************************
Public Sub SET_HOUR(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(hour_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_HOUR
End Sub
'****************************************************************************
Public Function READ_DOW() As Byte
  RTC_SPI
  SPI2.Transfer(dow_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_DOW(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(dow_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_DOW
End Sub
'****************************************************************************
Public Function READ_DOM() As Byte     ' Day of the month
  RTC_SPI
  SPI2.Transfer(dom_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_DOM(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(dom_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_DOM
End Sub
'****************************************************************************
Public Function READ_MONTH() As Byte
  RTC_SPI
  SPI2.Transfer(month_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_MONTH(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(month_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_MONTH
End Sub
'****************************************************************************
Public Function READ_YEAR() As Byte
  RTC_SPI
  SPI2.Transfer(year_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_YEAR(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(year_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_YEAR
End Sub
'****************************************************************************
Public Sub SET_H_M_S(pHour As Byte,pMin As Byte,pSec As Byte)
  SET_HOUR(pHour)
  SET_MINUITES(pMin)
  SET_SECONDS(pSec)
End Sub
'****************************************************************************
Public Sub SET_D_M_Y(pDate As Byte,pMonth As Byte,pYear As Byte)
  SET_DOM(pDate)
  SET_MONTH(pMonth)
  SET_YEAR(pYear)
End Sub
'****************************************************************************
Public Sub SHOW_TIME()
  SET_TERM_SERIAL
  time.t_seconds = READ_SECONDS
  time.t_minutes = READ_MINUITES
  time.t_hours   = READ_HOUR
  USART.Write(DecToStr(HighNibble(time.t_hours)),DecToStr(LowNibble(time.t_hours)),":",DecToStr(HighNibble(time.t_minutes)),
        DecToStr(LowNibble(time.t_minutes)),":",DecToStr(HighNibble(time.t_seconds)),DecToStr(LowNibble(time.t_seconds)),
        "  ")
  DelayMS(2)
End Sub
'****************************************************************************
Public Sub SHOW_DATE()
  SET_TERM_SERIAL
  date.d_month   = READ_MONTH
  date.d_date    = READ_DOM
  date.d_year    = READ_YEAR
  USART.Write(DecToStr(HighNibble(date.d_month)),DecToStr(LowNibble(date.d_month)),"/",DecToStr(HighNibble(date.d_date)),
        DecToStr(LowNibble(date.d_month)),"/",DecToStr(HighNibble(date.d_year)),DecToStr(LowNibble(date.d_year)),
        "         ")
  DelayMS(2)
End Sub
'****************************************************************************
Public Sub SET_TIME()
  USART.Write("ENTER HOUR IN 24 HOUR FORMAT",10,13)
  DelayMS(2)
  b1 = USART.ReadByte
  b2 = USART.ReadByte
  b2 = b2 - 48
  b1 = ((b1 - 48) * 16) + b2
  SET_HOUR(b1)
  
  USART.Write("ENTER MINUITES",10,13)
  DelayMS(2)
  b1 = USART.ReadByte
  b2 = USART.ReadByte
  b2 = b2 - 48
  b1 = ((b1 - 48) * 16) + b2
  SET_MINUITES(b1)  
  
  USART.Write("SECONDS",10,13)
  DelayMS(2)
  b1 = USART.ReadByte
  b2 = USART.ReadByte
  b2 = b2 - 48
  b1 = ((b1 - 48) * 16) + b2
  SET_SECONDS(b1)
End Sub
'****************************************************************************
'****************************************************************************
Public Function READ_ALM_10_100() As Byte
  RTC_SPI
  SPI2.Transfer(alm_10_100_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_ALM_10_100(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(alm_10_100_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_10_100
End Sub
'****************************************************************************
Public Function READ_ALM_SEC() As Byte
  RTC_SPI
  SPI2.Transfer(alm_sec_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_SEC(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(alm_sec_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_SEC
End Sub
'****************************************************************************
Public Function READ_ALM_MIN() As Byte
  RTC_SPI
  SPI2.Transfer(alm_min_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_MIN(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(alm_min_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_MIN
End Sub
'****************************************************************************
Public Function READ_ALM_HOUR() As Byte
  RTC_SPI
  SPI2.Transfer(alm_hour_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_HOUR(pVal As Byte)
  RTC_SPI
  SPI2.Transfer(alm_hour_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_HOUR
End Sub
'****************************************************************************
Public Function READ_ALM_DOW() As Byte
  RTC_SPI
  SPI2.Transfer(alm_dow_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_DOW(pVal As Byte)
  pVal = pVal + $40                    ' Make the register DOW instead of Date
  RTC_SPI
  SPI2.Transfer(alm_dow_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_DOW
End Sub
'****************************************************************************
Public Sub CLEAR_OSC_FLAG()
  RTC_SPI
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
  If b1.7 = 1 Then                     ' Osc flag set?
    b1.7 = 0
  EndIf
  Low(rtc_cs)
  SPI2.Transfer(status_write)           ' Clear it
  SPI2.Transfer(b1)
  High(rtc_cs)

  Low(rtc_cs)
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
End Sub
'****************************************************************************
Public Sub CLEAR_ALM_FLAG()
  RTC_SPI
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
  If b1.0 = 1 Then                     ' Alm flag set?
    b1.0 = 0
  EndIf
  Low(rtc_cs)
  SPI2.Transfer(status_write)           ' Clear it
  SPI2.Transfer(b1)
  High(rtc_cs)

  Low(rtc_cs)
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
End Sub
'****************************************************************************
Public Function READ_ALM_Flag() As Boolean
  RTC_SPI
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
  If b1.0 = 1 Then                     ' Alm flag set?
    result = true
   Else 
    result = false
  EndIf
End Function
'****************************************************************************
Public Sub ENABLE_ALM()
  CLEAR_ALM_FLAG
  RTC_SPI
  SPI2.Transfer(control_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
'  USART.Write("ENABLE ALARM = ",BinToStr(b1,8),". NEEDS TO BE 0010 0101.",10,13)
'  DelayMS(2)

  If b1.0 = 0 Then                     ' Enable ALM if need be
    b1.0 = 1
    Low(rtc_cs)
    SPI2.Transfer(control_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
End Sub
'****************************************************************************
Public Sub DISABLE_ALM()
  RTC_SPI

  SPI2.Transfer(control_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
'  USART.Write("DISABLE ALARM = ",BinToStr(b1,8),". NEEDS TO BE 0010 0100.",10,13)
'  DelayMS(2)

  If b1.0 = 1 Then
    b1.0 = 0
    Low(rtc_cs)
    SPI2.Transfer(control_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
End Sub    
'****************************************************************************
Public Sub ALARM_ON_HOUR(pHr As Byte)  ' Number of hours to delay
  DISABLE_ALM
  b1 = READ_ALM_DOW                    ' Set AM4 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_dow_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf

  SET_ALM_10_100($00)                  ' Set second registers to 0
  SET_ALM_SEC($00)
  SET_ALM_MIN($00)                     ' Set alarm minuites to 0
        
  b1 = READ_ALM_HOUR                   '
  b1 =  b1 + pHr

  If HighNibble(b1) > 2 Then
    b1 = LowNibble(b1)
  EndIf
  
  SET_ALM_HOUR(b1)                     ' Set the hour alarm
  ENABLE_ALM                           ' Start the timer
End Sub
'****************************************************************************
Public Sub ALARM_ON_MIN(pMin As Byte)  ' Number of minuites to delay
  DISABLE_ALM
    
  b1 = READ_ALM_DOW                    ' Set AM4 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_dow_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
  b1 = READ_ALM_HOUR                   ' Set AM3 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_hour_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf

  SET_ALM_10_100($00)                  ' Set second registers to 0
  SET_ALM_SEC($00)
  
  b1 = READ_MINUITES
'  USART.write("CURRENT MINUITES - ",HexToStr(b1),10,13)
'  DelayMS(1)
  b1 = b1 + pMin
  If LowNibble(b1) > 9 Then            ' Adjust the minuites alarm reg
    b1 = (b1 + $10) - 10
  EndIf
  If HighNibble(b1) > 5 Then
    b1 = b1 - (HighNibble(b1) * $10)
  EndIf
  
'  USART.write("CALCULATED ALARM MINUITES - ",HexToStr(b1),10,13)
'  DelayMS(1)
  SET_ALM_MIN(b1)
  ENABLE_ALM                           ' Start the timer
End Sub
'****************************************************************************
Public Sub ALARM_ON_SEC(pSec As Byte)  ' Number of minuites to delay
  DISABLE_ALM
  b1 = READ_ALM_DOW                    ' Set AM4 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_dow_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
  b1 = READ_ALM_HOUR                   ' Set AM3 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_hour_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
  b1 = READ_ALM_MIN                    ' Set AM2 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_min_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf 

  SET_ALM_10_100($00)                  ' Set second registers to 0
  SET_ALM_SEC($00)
  SET_ALM_MIN($00)                     ' Set alarm minuites to 0
'  b1 = READ_MINUITES
'  USART.write("CURRENT MINUITES - ",HexToStr(b1),10,13)
'  DelayMS(1)
  b1 = b1 + pSec

  b1 = READ_ALM_SEC                   ' 
  b1 = b1 + pSec
  If LowNibble(b1) > 9 Then            ' Adjust the minuites alarm reg
    b1 = (b1 + $10) - 10
  EndIf
  If HighNibble(b1) > 5 Then
    b1 = b1 - (HighNibble(b1) * $10)
  EndIf
  
  SET_ALM_SEC(b1)                      ' Set the second alarm
  ENABLE_ALM                           ' Start the timer
End Sub
'****************************************************************************
Public Sub WAKE_RTC_ALARM()
  INIT_RTC
  b3 = MEM_64K.READ_BYTE($0000)
  b4 = MEM_64K.READ_BYTE($0004)
'  USART.write(10,13,"H M S - ",DecToStr(b3),"  DELAY - ",DecToStr(b4),10,13)
'  DelayMS(2)
  
  Select b3
    Case 1
      ALARM_ON_SEC(b4)
    Case 2
      ALARM_ON_MIN(b4)
    Case 3
      ALARM_ON_HOUR(b4)
  End Select
End Sub
'****************************************************************************
SET_TERM_SERIAL









  

Jerry Messina
Swordfish Developer
Posts: 1486
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: SPI2xv and 18F37Q84

Post by Jerry Messina » Thu Apr 20, 2023 12:10 pm

I don't think the PPS assignments are being used as intended... you keep setting them in various subs, and the lock/unlock isn't correct.
The pps.bas file shows how to unlock and lock the pps peripheral and will also handle the PPS1WAY config setting.

I would also recommend moving all the hardware assignments to the main program module instead of being in some random module somewhere.
I'm not sure if you meant to use SPI1 or SPI2, but I put together an example using SPI2.
ds1394.bas

Code: Select all

Module DS1394

Include "SPI2xv.bas"
Include "USART.bas"
Include "convert.bas"
Include "system.bas"
Include "utils.bas"
// JM - commented out so I could compile w/out MEM_64K.bas
'Include "MEM_64K.BAS"

// JM - changed 'rtc_cs' IO pin declaration to use '#option'
// default rtc_cs pin (over-ride before including this file)
#option RTC_SPI_CS = PORTB.3    // assign a default for rtc_cs
dim rtc_cs as RTC_SPI_CS.RTC_SPI_CS@

Private Structure m_Date_Time
  dt_seconds       As Byte,
  dt_minutes       As Byte,
  dt_hours         As Byte,
  dt_dow           As Byte,
  dt_date          As Byte,
  dt_month         As Byte,
  dt_year          As Byte
End Structure

Private Structure m_Time
  t_seconds        As Byte,
  t_minutes        As Byte,
  t_hours          As Byte
End Structure

Private Structure m_Date
  d_dow            As Byte,
  d_date           As Byte,
  d_month          As Byte,
  d_year           As Byte
End Structure

// JM - removed these module level variables
// and replaced them with local declarations where needed
// this will take advantage of the SF frame variable mechanism
{
Private Dim
  b1               As Byte,
  b2               As Byte,
  b3               As Byte,
  b4               As Byte

Private Dim
  time             As m_Time,
  date             As m_Date
}

// JM - removed these private PORT pin definitions
// much better to use #options to define these outside the module
// that way they're not hidden and can easily be changed
{
Private Dim
  red              As PORTA.7,
  green            As PORTA.6,
  mem_cs           As PORTB.2,
  rtc_cs           As PORTB.3
}
   
Private Const
  sec_10_100_read   = $00,
  sec_10_100_write  = $80,
  sec_read          = $01,
  sec_write         = $81,
  min_read          = $02,
  min_write         = $82,
  hour_read         = $03,
  hour_write        = $83,
  dow_read          = $04,
  dow_write         = $84,
  dom_read          = $05,
  dom_write         = $85,
  month_read        = $06,
  month_write       = $86,
  year_read         = $07,
  year_write        = $87,
  alm_10_100_read   = $08,
  alm_10_100_write  = $88,
  alm_sec_read      = $09,
  alm_sec_write     = $89,
  alm_min_read      = $0A,
  alm_min_write     = $8A,  
  alm_hour_read     = $0B,
  alm_hour_write    = $8B,
  alm_dow_read      = $0C,
  alm_dow_write     = $8C,
  control_read      = $0D,
  control_write     = $8D,
  status_read       = $0E,
  status_write      = $8E,
  trickle_read      = $0F,
  trickel_write     = $8F
  
'****************************************************************************
Public Sub INIT_RTC()
  SPI2.Open(SPI_MODE_0,spiOscDiv64,spiSampleEnd)

  Low(rtc_cs)
  SPI2.Transfer(status_write)           '
  SPI2.Transfer($00)                    ' Clear Osc and Alarm flags
  High(rtc_cs)
  
  Low(rtc_cs)
  SPI2.Transfer(control_write)          ' Enable osc, int on batt, enable int, AIE disabled (enabled on alarm set) 
  SPI2.Transfer($24)
  High(rtc_cs)

  Low(rtc_cs)
  SPI2.Transfer(trickel_write)
'  SPI2.Transfer($A5)                    ' No diode, 250 ohm resistor  
  SPI2.Transfer($A6)                    ' No diode, 2K resistor
'  SPI2.Transfer($A7)                    ' No diode, 4K resistor
  High(rtc_cs)

End Sub
'****************************************************************************
Public Function READ_SECONDS() As Byte
  Low(rtc_cs)
  SPI2.Transfer(sec_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_SECONDS(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(sec_10_100_write)
  SPI2.Transfer($00)                    ' Set 10ths and 100ths seconds to 0
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_SECONDS
End Sub
'****************************************************************************
Public Function READ_MINUITES() As Byte
  Low(rtc_cs)
  SPI2.Transfer(min_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_MINUITES(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(min_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_MINUITES
End Sub
'****************************************************************************
Public Function READ_HOUR() As Byte
  Low(rtc_cs)
  SPI2.Transfer(hour_read)
  result = SPI2.Transfer
  High(rtc_cs)
 End Function  
'****************************************************************************
Public Sub SET_HOUR(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(hour_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_HOUR
End Sub
'****************************************************************************
Public Function READ_DOW() As Byte
  Low(rtc_cs)
  SPI2.Transfer(dow_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_DOW(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(dow_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_DOW
End Sub
'****************************************************************************
Public Function READ_DOM() As Byte     ' Day of the month
  Low(rtc_cs)
  SPI2.Transfer(dom_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_DOM(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(dom_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_DOM
End Sub
'****************************************************************************
Public Function READ_MONTH() As Byte
  Low(rtc_cs)
  SPI2.Transfer(month_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_MONTH(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(month_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_MONTH
End Sub
'****************************************************************************
Public Function READ_YEAR() As Byte
  Low(rtc_cs)
  SPI2.Transfer(year_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_YEAR(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(year_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_YEAR
End Sub
'****************************************************************************
Public Sub SET_H_M_S(pHour As Byte,pMin As Byte,pSec As Byte)
  SET_HOUR(pHour)
  SET_MINUITES(pMin)
  SET_SECONDS(pSec)
End Sub
'****************************************************************************
Public Sub SET_D_M_Y(pDate As Byte,pMonth As Byte,pYear As Byte)
  SET_DOM(pDate)
  SET_MONTH(pMonth)
  SET_YEAR(pYear)
End Sub
'****************************************************************************
Public Sub SHOW_TIME()
  dim time as m_Time

  time.t_seconds = READ_SECONDS
  time.t_minutes = READ_MINUITES
  time.t_hours   = READ_HOUR
  USART.Write(DecToStr(HighNibble(time.t_hours)),DecToStr(LowNibble(time.t_hours)),":",DecToStr(HighNibble(time.t_minutes)),
        DecToStr(LowNibble(time.t_minutes)),":",DecToStr(HighNibble(time.t_seconds)),DecToStr(LowNibble(time.t_seconds)),
        "  ")
  DelayMS(2)
End Sub
'****************************************************************************
Public Sub SHOW_DATE()
  dim date as m_Date

  date.d_month   = READ_MONTH
  date.d_date    = READ_DOM
  date.d_year    = READ_YEAR
  USART.Write(DecToStr(HighNibble(date.d_month)),DecToStr(LowNibble(date.d_month)),"/",DecToStr(HighNibble(date.d_date)),
        DecToStr(LowNibble(date.d_month)),"/",DecToStr(HighNibble(date.d_year)),DecToStr(LowNibble(date.d_year)),
        "         ")
  DelayMS(2)
End Sub
'****************************************************************************
Public Sub SET_TIME()
  dim b1, b2 as byte
    
  USART.Write("ENTER HOUR IN 24 HOUR FORMAT",10,13)
  DelayMS(2)
  b1 = USART.ReadByte
  b2 = USART.ReadByte
  b2 = b2 - 48
  b1 = ((b1 - 48) * 16) + b2
  SET_HOUR(b1)
  
  USART.Write("ENTER MINUITES",10,13)
  DelayMS(2)
  b1 = USART.ReadByte
  b2 = USART.ReadByte
  b2 = b2 - 48
  b1 = ((b1 - 48) * 16) + b2
  SET_MINUITES(b1)  
  
  USART.Write("SECONDS",10,13)
  DelayMS(2)
  b1 = USART.ReadByte
  b2 = USART.ReadByte
  b2 = b2 - 48
  b1 = ((b1 - 48) * 16) + b2
  SET_SECONDS(b1)
End Sub
'****************************************************************************
'****************************************************************************
Public Function READ_ALM_10_100() As Byte
  Low(rtc_cs)
  SPI2.Transfer(alm_10_100_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_ALM_10_100(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(alm_10_100_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_10_100
End Sub
'****************************************************************************
Public Function READ_ALM_SEC() As Byte
  Low(rtc_cs)
  SPI2.Transfer(alm_sec_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_SEC(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(alm_sec_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_SEC
End Sub
'****************************************************************************
Public Function READ_ALM_MIN() As Byte
  Low(rtc_cs)
  SPI2.Transfer(alm_min_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_MIN(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(alm_min_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_MIN
End Sub
'****************************************************************************
Public Function READ_ALM_HOUR() As Byte
  Low(rtc_cs)
  SPI2.Transfer(alm_hour_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_HOUR(pVal As Byte)
  Low(rtc_cs)
  SPI2.Transfer(alm_hour_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_HOUR
End Sub
'****************************************************************************
Public Function READ_ALM_DOW() As Byte
  Low(rtc_cs)
  SPI2.Transfer(alm_dow_read)
  result = SPI2.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_DOW(pVal As Byte)
  pVal = pVal + $40                    ' Make the register DOW instead of Date
  Low(rtc_cs)
  SPI2.Transfer(alm_dow_write)
  SPI2.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_DOW
End Sub
'****************************************************************************
Public Sub CLEAR_OSC_FLAG()
  dim b1 as byte
  
  Low(rtc_cs)
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
  If b1.7 = 1 Then                     ' Osc flag set?
    b1.7 = 0
  EndIf
  Low(rtc_cs)
  SPI2.Transfer(status_write)           ' Clear it
  SPI2.Transfer(b1)
  High(rtc_cs)

  Low(rtc_cs)
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
End Sub
'****************************************************************************
Public Sub CLEAR_ALM_FLAG()
  dim b1 as byte

  Low(rtc_cs)
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
  If b1.0 = 1 Then                     ' Alm flag set?
    b1.0 = 0
  EndIf
  Low(rtc_cs)
  SPI2.Transfer(status_write)           ' Clear it
  SPI2.Transfer(b1)
  High(rtc_cs)

  Low(rtc_cs)
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
End Sub
'****************************************************************************
Public Function READ_ALM_Flag() As Boolean
  dim b1 as byte

  Low(rtc_cs)
  SPI2.Transfer(status_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
  If b1.0 = 1 Then                     ' Alm flag set?
    result = true
   Else 
    result = false
  EndIf
End Function
'****************************************************************************
Public Sub ENABLE_ALM()
  dim b1 as byte

  CLEAR_ALM_FLAG

  Low(rtc_cs)
  SPI2.Transfer(control_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
'  USART.Write("ENABLE ALARM = ",BinToStr(b1,8),". NEEDS TO BE 0010 0101.",10,13)
'  DelayMS(2)

  If b1.0 = 0 Then                     ' Enable ALM if need be
    b1.0 = 1
    Low(rtc_cs)
    SPI2.Transfer(control_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
End Sub
'****************************************************************************
Public Sub DISABLE_ALM()
  dim b1 as byte

  Low(rtc_cs)
  SPI2.Transfer(control_read)
  b1 = SPI2.Transfer
  High(rtc_cs)
'  USART.Write("DISABLE ALARM = ",BinToStr(b1,8),". NEEDS TO BE 0010 0100.",10,13)
'  DelayMS(2)

  If b1.0 = 1 Then
    b1.0 = 0
    Low(rtc_cs)
    SPI2.Transfer(control_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
End Sub    
'****************************************************************************
Public Sub ALARM_ON_HOUR(pHr As Byte)  ' Number of hours to delay
  dim b1 as byte

  DISABLE_ALM
  b1 = READ_ALM_DOW                    ' Set AM4 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_dow_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf

  SET_ALM_10_100($00)                  ' Set second registers to 0
  SET_ALM_SEC($00)
  SET_ALM_MIN($00)                     ' Set alarm minuites to 0
        
  b1 = READ_ALM_HOUR                   '
  b1 =  b1 + pHr

  If HighNibble(b1) > 2 Then
    b1 = LowNibble(b1)
  EndIf
  
  SET_ALM_HOUR(b1)                     ' Set the hour alarm
  ENABLE_ALM                           ' Start the timer
End Sub
'****************************************************************************
Public Sub ALARM_ON_MIN(pMin As Byte)  ' Number of minuites to delay
  dim b1 as byte

  DISABLE_ALM
    
  b1 = READ_ALM_DOW                    ' Set AM4 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_dow_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
  b1 = READ_ALM_HOUR                   ' Set AM3 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_hour_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf

  SET_ALM_10_100($00)                  ' Set second registers to 0
  SET_ALM_SEC($00)
  
  b1 = READ_MINUITES
'  USART.write("CURRENT MINUITES - ",HexToStr(b1),10,13)
'  DelayMS(1)
  b1 = b1 + pMin
  If LowNibble(b1) > 9 Then            ' Adjust the minuites alarm reg
    b1 = (b1 + $10) - 10
  EndIf
  If HighNibble(b1) > 5 Then
    b1 = b1 - (HighNibble(b1) * $10)
  EndIf
  
'  USART.write("CALCULATED ALARM MINUITES - ",HexToStr(b1),10,13)
'  DelayMS(1)
  SET_ALM_MIN(b1)
  ENABLE_ALM                           ' Start the timer
End Sub
'****************************************************************************
Public Sub ALARM_ON_SEC(pSec As Byte)  ' Number of minuites to delay
  dim b1 as byte

  DISABLE_ALM
  b1 = READ_ALM_DOW                    ' Set AM4 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_dow_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
  b1 = READ_ALM_HOUR                   ' Set AM3 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_hour_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf
  b1 = READ_ALM_MIN                    ' Set AM2 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI2.Transfer(alm_min_write)
    SPI2.Transfer(b1)
    High(rtc_cs)
  EndIf 

  SET_ALM_10_100($00)                  ' Set second registers to 0
  SET_ALM_SEC($00)
  SET_ALM_MIN($00)                     ' Set alarm minuites to 0
'  b1 = READ_MINUITES
'  USART.write("CURRENT MINUITES - ",HexToStr(b1),10,13)
'  DelayMS(1)
  b1 = b1 + pSec

  b1 = READ_ALM_SEC                   ' 
  b1 = b1 + pSec
  If LowNibble(b1) > 9 Then            ' Adjust the minuites alarm reg
    b1 = (b1 + $10) - 10
  EndIf
  If HighNibble(b1) > 5 Then
    b1 = b1 - (HighNibble(b1) * $10)
  EndIf
  
  SET_ALM_SEC(b1)                      ' Set the second alarm
  ENABLE_ALM                           ' Start the timer
End Sub
'****************************************************************************
// JM - commented out so I could compile w/out MEM64K.bas
{
Public Sub WAKE_RTC_ALARM()
  dim b3, b4  as byte

  b3 = MEM_64K.READ_BYTE($0000)
  b4 = MEM_64K.READ_BYTE($0004)

'  USART.write(10,13,"H M S - ",DecToStr(b3),"  DELAY - ",DecToStr(b4),10,13)
'  DelayMS(2)
  
  Select b3
    Case 1
      ALARM_ON_SEC(b4)
    Case 2
      ALARM_ON_MIN(b4)
    Case 3
      ALARM_ON_HOUR(b4)
  End Select
End Sub
}

end module
Here's a main program module example:

Code: Select all

device = 18F27Q84
clock = 64

include "intosc.bas"        // assumes using the int osc
include "setdigitalio.bas"

'PPS Tool version: 0.0.6.4
'PinManager data: v1.81.7b
include "pps.bas"
#option USART_RX = PORTC.6
#option USART_TX = PORTC.7
include "USART.bas"
#option SPI2_SCK = PORTC.3
#option SPI2_SDI = PORTC.4
#option SPI2_SDO = PORTC.5
include "SPI2xv.bas"

// assign rtc cs IO pin
#option RTC_SPI_CS = PORTB.3
include "ds1394.bas"

// from PPS tool
public sub InitPPS()
    pps.unlock()

    'Module: SPI2
    SPI2SCKPPS = $13    'RC3 > SCK2
    RC3PPS = $34        'SCK2 > RC3 (bidir)
    SPI2SDIPPS = $14    'RC4 > SDI2
    RC5PPS = $35        'SDO2 > RC5

    'Module: UART pin directions
    input(PORTC.6)     ' Make RX1 pin an input
    output(PORTC.7)    ' Make TX1 pin an output
    'Module: UART1
    U1RXPPS = $16      'RC6 > RX1
    RC7PPS = $20       'TX1 > RC7

    pps.lock()
end sub

main:
    SetAllDigital()
    InitPPS()

    USART.SetBaudrate(br9600)
    ds1394.INIT_RTC()
    
    // probably want to set these first, but as an example...
    ds1394.show_time()
    ds1394.show_date()
        
end program

Jerry Messina
Swordfish Developer
Posts: 1486
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: SPI2xv and 18F37Q84

Post by Jerry Messina » Thu Apr 20, 2023 3:23 pm

Also, if you make the structure definitions public you can get rid of all the references to the uart.

That way the module is less dependent on other modules and the only thing ds1394 needs to include is the spi2xv.bas file. You could then use it in programs without the uart module, or use another uart.

garryp4
Posts: 126
Joined: Mon May 21, 2007 7:18 am
Location: Loveland, CO USA

Re: SPI2xv and 18F37Q84

Post by garryp4 » Thu Apr 20, 2023 5:55 pm

Jerry:
Again, thanks so much!

That did correct my problem, and now I have a few questions.

How can I set the routine to use SPI1? I tried :

Code: Select all

  'SPI1
  SPI1SCKPPS = $13                     'RC3 > SCK1
  RC3PPS = $31                         'SCK1 > RC3 (bidir)
  SPI1SDIPPS = $14                     'RC4 > SDI1
  RC5PPS = $32                         'SDO1 > RC5
instead of

Code: Select all

  SPI2SCKPPS = $13                     'RC3 > SCK2
  RC3PPS = $34                         'SCK2 > RC3 (bidir)
  SPI2SDIPPS = $14                     'RC4 > SDI2
  RC5PPS = $35                         'SDO2 > RC5
but that did not work.

What does

Code: Select all

  rtc_cs As RTC_SPI_CS.RTC_SPI_CS@
gain over

Code: Select all

rtc_cs       As PORTB.3
?

And, if I am using the default input ports, such as RC3 for SCK1, do I still need to map it? It seems the Jxx parts have very long lead times, so I need to understand the differences to the Kxx and Qxx parts.

Thanks.

Jerry Messina
Swordfish Developer
Posts: 1486
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: SPI2xv and 18F37Q84

Post by Jerry Messina » Fri Apr 21, 2023 11:58 am

SPIxv.bas uses SPI1 and SPI2xv.bas uses SPI2, so to use SPI1 instead of SPI2 you need to:
- change the include to use the SPIxv.bas module
- change all of the 'SPI2' references to 'SPI' in ds1394.bas
- change InitPPS to map SPI1

ds1394.bas (using SPI1)

Code: Select all

Module DS1394

Include "SPIxv.bas"
Include "USART.bas"
Include "convert.bas"
Include "system.bas"
Include "utils.bas"
// JM - commented out so I could compile w/out MEM_64K.bas
'Include "MEM_64K.BAS"

// JM - changed 'rtc_cs' IO pin declaration to use '#option'
// default rtc_cs pin (over-ride before including this file)
#option RTC_SPI_CS = PORTB.3    // assign a default for rtc_cs
dim rtc_cs as RTC_SPI_CS.RTC_SPI_CS@

Private Structure m_Date_Time
  dt_seconds       As Byte,
  dt_minutes       As Byte,
  dt_hours         As Byte,
  dt_dow           As Byte,
  dt_date          As Byte,
  dt_month         As Byte,
  dt_year          As Byte
End Structure

Private Structure m_Time
  t_seconds        As Byte,
  t_minutes        As Byte,
  t_hours          As Byte
End Structure

Private Structure m_Date
  d_dow            As Byte,
  d_date           As Byte,
  d_month          As Byte,
  d_year           As Byte
End Structure

// JM - removed these module level variables
// and replaced them with local declarations where needed
// this will take advantage of the SF frame variable mechanism
{
Private Dim
  b1               As Byte,
  b2               As Byte,
  b3               As Byte,
  b4               As Byte

Private Dim
  time             As m_Time,
  date             As m_Date
}

// JM - removed these private PORT pin definitions
// much better to use #options to define these outside the module
// that way they're not hidden and can easily be changed
{
Private Dim
  red              As PORTA.7,
  green            As PORTA.6,
  mem_cs           As PORTB.2,
  rtc_cs           As PORTB.3
}
   
Private Const
  sec_10_100_read   = $00,
  sec_10_100_write  = $80,
  sec_read          = $01,
  sec_write         = $81,
  min_read          = $02,
  min_write         = $82,
  hour_read         = $03,
  hour_write        = $83,
  dow_read          = $04,
  dow_write         = $84,
  dom_read          = $05,
  dom_write         = $85,
  month_read        = $06,
  month_write       = $86,
  year_read         = $07,
  year_write        = $87,
  alm_10_100_read   = $08,
  alm_10_100_write  = $88,
  alm_sec_read      = $09,
  alm_sec_write     = $89,
  alm_min_read      = $0A,
  alm_min_write     = $8A,  
  alm_hour_read     = $0B,
  alm_hour_write    = $8B,
  alm_dow_read      = $0C,
  alm_dow_write     = $8C,
  control_read      = $0D,
  control_write     = $8D,
  status_read       = $0E,
  status_write      = $8E,
  trickle_read      = $0F,
  trickel_write     = $8F
  
'****************************************************************************
Public Sub INIT_RTC()
  SPI.Open(SPI_MODE_0,spiOscDiv64,spiSampleEnd)

  Low(rtc_cs)
  SPI.Transfer(status_write)           '
  SPI.Transfer($00)                    ' Clear Osc and Alarm flags
  High(rtc_cs)
  
  Low(rtc_cs)
  SPI.Transfer(control_write)          ' Enable osc, int on batt, enable int, AIE disabled (enabled on alarm set) 
  SPI.Transfer($24)
  High(rtc_cs)

  Low(rtc_cs)
  SPI.Transfer(trickel_write)
'  SPI.Transfer($A5)                    ' No diode, 250 ohm resistor  
  SPI.Transfer($A6)                    ' No diode, 2K resistor
'  SPI.Transfer($A7)                    ' No diode, 4K resistor
  High(rtc_cs)

End Sub
'****************************************************************************
Public Function READ_SECONDS() As Byte
  Low(rtc_cs)
  SPI.Transfer(sec_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_SECONDS(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(sec_10_100_write)
  SPI.Transfer($00)                    ' Set 10ths and 100ths seconds to 0
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_SECONDS
End Sub
'****************************************************************************
Public Function READ_MINUITES() As Byte
  Low(rtc_cs)
  SPI.Transfer(min_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_MINUITES(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(min_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_MINUITES
End Sub
'****************************************************************************
Public Function READ_HOUR() As Byte
  Low(rtc_cs)
  SPI.Transfer(hour_read)
  result = SPI.Transfer
  High(rtc_cs)
 End Function  
'****************************************************************************
Public Sub SET_HOUR(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(hour_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_HOUR
End Sub
'****************************************************************************
Public Function READ_DOW() As Byte
  Low(rtc_cs)
  SPI.Transfer(dow_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_DOW(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(dow_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_DOW
End Sub
'****************************************************************************
Public Function READ_DOM() As Byte     ' Day of the month
  Low(rtc_cs)
  SPI.Transfer(dom_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_DOM(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(dom_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_DOM
End Sub
'****************************************************************************
Public Function READ_MONTH() As Byte
  Low(rtc_cs)
  SPI.Transfer(month_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_MONTH(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(month_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_MONTH
End Sub
'****************************************************************************
Public Function READ_YEAR() As Byte
  Low(rtc_cs)
  SPI.Transfer(year_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_YEAR(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(year_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_YEAR
End Sub
'****************************************************************************
Public Sub SET_H_M_S(pHour As Byte,pMin As Byte,pSec As Byte)
  SET_HOUR(pHour)
  SET_MINUITES(pMin)
  SET_SECONDS(pSec)
End Sub
'****************************************************************************
Public Sub SET_D_M_Y(pDate As Byte,pMonth As Byte,pYear As Byte)
  SET_DOM(pDate)
  SET_MONTH(pMonth)
  SET_YEAR(pYear)
End Sub
'****************************************************************************
Public Sub SHOW_TIME()
  dim time as m_Time

  time.t_seconds = READ_SECONDS
  time.t_minutes = READ_MINUITES
  time.t_hours   = READ_HOUR
  USART.Write(DecToStr(HighNibble(time.t_hours)),DecToStr(LowNibble(time.t_hours)),":",DecToStr(HighNibble(time.t_minutes)),
        DecToStr(LowNibble(time.t_minutes)),":",DecToStr(HighNibble(time.t_seconds)),DecToStr(LowNibble(time.t_seconds)),
        "  ")
  DelayMS(2)
End Sub
'****************************************************************************
Public Sub SHOW_DATE()
  dim date as m_Date

  date.d_month   = READ_MONTH
  date.d_date    = READ_DOM
  date.d_year    = READ_YEAR
  USART.Write(DecToStr(HighNibble(date.d_month)),DecToStr(LowNibble(date.d_month)),"/",DecToStr(HighNibble(date.d_date)),
        DecToStr(LowNibble(date.d_month)),"/",DecToStr(HighNibble(date.d_year)),DecToStr(LowNibble(date.d_year)),
        "         ")
  DelayMS(2)
End Sub
'****************************************************************************
Public Sub SET_TIME()
  dim b1, b2 as byte
    
  USART.Write("ENTER HOUR IN 24 HOUR FORMAT",10,13)
  DelayMS(2)
  b1 = USART.ReadByte
  b2 = USART.ReadByte
  b2 = b2 - 48
  b1 = ((b1 - 48) * 16) + b2
  SET_HOUR(b1)
  
  USART.Write("ENTER MINUITES",10,13)
  DelayMS(2)
  b1 = USART.ReadByte
  b2 = USART.ReadByte
  b2 = b2 - 48
  b1 = ((b1 - 48) * 16) + b2
  SET_MINUITES(b1)  
  
  USART.Write("SECONDS",10,13)
  DelayMS(2)
  b1 = USART.ReadByte
  b2 = USART.ReadByte
  b2 = b2 - 48
  b1 = ((b1 - 48) * 16) + b2
  SET_SECONDS(b1)
End Sub
'****************************************************************************
'****************************************************************************
Public Function READ_ALM_10_100() As Byte
  Low(rtc_cs)
  SPI.Transfer(alm_10_100_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function  
'****************************************************************************
Public Sub SET_ALM_10_100(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(alm_10_100_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_10_100
End Sub
'****************************************************************************
Public Function READ_ALM_SEC() As Byte
  Low(rtc_cs)
  SPI.Transfer(alm_sec_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_SEC(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(alm_sec_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_SEC
End Sub
'****************************************************************************
Public Function READ_ALM_MIN() As Byte
  Low(rtc_cs)
  SPI.Transfer(alm_min_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_MIN(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(alm_min_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_MIN
End Sub
'****************************************************************************
Public Function READ_ALM_HOUR() As Byte
  Low(rtc_cs)
  SPI.Transfer(alm_hour_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_HOUR(pVal As Byte)
  Low(rtc_cs)
  SPI.Transfer(alm_hour_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_HOUR
End Sub
'****************************************************************************
Public Function READ_ALM_DOW() As Byte
  Low(rtc_cs)
  SPI.Transfer(alm_dow_read)
  result = SPI.Transfer
  High(rtc_cs)
End Function
'****************************************************************************
Public Sub SET_ALM_DOW(pVal As Byte)
  pVal = pVal + $40                    ' Make the register DOW instead of Date
  Low(rtc_cs)
  SPI.Transfer(alm_dow_write)
  SPI.Transfer(pVal)
  High(rtc_cs)
  READ_ALM_DOW
End Sub
'****************************************************************************
Public Sub CLEAR_OSC_FLAG()
  dim b1 as byte
  
  Low(rtc_cs)
  SPI.Transfer(status_read)
  b1 = SPI.Transfer
  High(rtc_cs)
  If b1.7 = 1 Then                     ' Osc flag set?
    b1.7 = 0
  EndIf
  Low(rtc_cs)
  SPI.Transfer(status_write)           ' Clear it
  SPI.Transfer(b1)
  High(rtc_cs)

  Low(rtc_cs)
  SPI.Transfer(status_read)
  b1 = SPI.Transfer
  High(rtc_cs)
End Sub
'****************************************************************************
Public Sub CLEAR_ALM_FLAG()
  dim b1 as byte

  Low(rtc_cs)
  SPI.Transfer(status_read)
  b1 = SPI.Transfer
  High(rtc_cs)
  If b1.0 = 1 Then                     ' Alm flag set?
    b1.0 = 0
  EndIf
  Low(rtc_cs)
  SPI.Transfer(status_write)           ' Clear it
  SPI.Transfer(b1)
  High(rtc_cs)

  Low(rtc_cs)
  SPI.Transfer(status_read)
  b1 = SPI.Transfer
  High(rtc_cs)
End Sub
'****************************************************************************
Public Function READ_ALM_Flag() As Boolean
  dim b1 as byte

  Low(rtc_cs)
  SPI.Transfer(status_read)
  b1 = SPI.Transfer
  High(rtc_cs)
  If b1.0 = 1 Then                     ' Alm flag set?
    result = true
   Else 
    result = false
  EndIf
End Function
'****************************************************************************
Public Sub ENABLE_ALM()
  dim b1 as byte

  CLEAR_ALM_FLAG

  Low(rtc_cs)
  SPI.Transfer(control_read)
  b1 = SPI.Transfer
  High(rtc_cs)
'  USART.Write("ENABLE ALARM = ",BinToStr(b1,8),". NEEDS TO BE 0010 0101.",10,13)
'  DelayMS(2)

  If b1.0 = 0 Then                     ' Enable ALM if need be
    b1.0 = 1
    Low(rtc_cs)
    SPI.Transfer(control_write)
    SPI.Transfer(b1)
    High(rtc_cs)
  EndIf
End Sub
'****************************************************************************
Public Sub DISABLE_ALM()
  dim b1 as byte

  Low(rtc_cs)
  SPI.Transfer(control_read)
  b1 = SPI.Transfer
  High(rtc_cs)
'  USART.Write("DISABLE ALARM = ",BinToStr(b1,8),". NEEDS TO BE 0010 0100.",10,13)
'  DelayMS(2)

  If b1.0 = 1 Then
    b1.0 = 0
    Low(rtc_cs)
    SPI.Transfer(control_write)
    SPI.Transfer(b1)
    High(rtc_cs)
  EndIf
End Sub    
'****************************************************************************
Public Sub ALARM_ON_HOUR(pHr As Byte)  ' Number of hours to delay
  dim b1 as byte

  DISABLE_ALM
  b1 = READ_ALM_DOW                    ' Set AM4 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI.Transfer(alm_dow_write)
    SPI.Transfer(b1)
    High(rtc_cs)
  EndIf

  SET_ALM_10_100($00)                  ' Set second registers to 0
  SET_ALM_SEC($00)
  SET_ALM_MIN($00)                     ' Set alarm minuites to 0
        
  b1 = READ_ALM_HOUR                   '
  b1 =  b1 + pHr

  If HighNibble(b1) > 2 Then
    b1 = LowNibble(b1)
  EndIf
  
  SET_ALM_HOUR(b1)                     ' Set the hour alarm
  ENABLE_ALM                           ' Start the timer
End Sub
'****************************************************************************
Public Sub ALARM_ON_MIN(pMin As Byte)  ' Number of minuites to delay
  dim b1 as byte

  DISABLE_ALM
    
  b1 = READ_ALM_DOW                    ' Set AM4 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI.Transfer(alm_dow_write)
    SPI.Transfer(b1)
    High(rtc_cs)
  EndIf
  b1 = READ_ALM_HOUR                   ' Set AM3 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI.Transfer(alm_hour_write)
    SPI.Transfer(b1)
    High(rtc_cs)
  EndIf

  SET_ALM_10_100($00)                  ' Set second registers to 0
  SET_ALM_SEC($00)
  
  b1 = READ_MINUITES
'  USART.write("CURRENT MINUITES - ",HexToStr(b1),10,13)
'  DelayMS(1)
  b1 = b1 + pMin
  If LowNibble(b1) > 9 Then            ' Adjust the minuites alarm reg
    b1 = (b1 + $10) - 10
  EndIf
  If HighNibble(b1) > 5 Then
    b1 = b1 - (HighNibble(b1) * $10)
  EndIf
  
'  USART.write("CALCULATED ALARM MINUITES - ",HexToStr(b1),10,13)
'  DelayMS(1)
  SET_ALM_MIN(b1)
  ENABLE_ALM                           ' Start the timer
End Sub
'****************************************************************************
Public Sub ALARM_ON_SEC(pSec As Byte)  ' Number of minuites to delay
  dim b1 as byte

  DISABLE_ALM
  b1 = READ_ALM_DOW                    ' Set AM4 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI.Transfer(alm_dow_write)
    SPI.Transfer(b1)
    High(rtc_cs)
  EndIf
  b1 = READ_ALM_HOUR                   ' Set AM3 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI.Transfer(alm_hour_write)
    SPI.Transfer(b1)
    High(rtc_cs)
  EndIf
  b1 = READ_ALM_MIN                    ' Set AM2 to 1
  If b1.7 = 0 Then                
    b1.7 = 1
    Low(rtc_cs)
    SPI.Transfer(alm_min_write)
    SPI.Transfer(b1)
    High(rtc_cs)
  EndIf 

  SET_ALM_10_100($00)                  ' Set second registers to 0
  SET_ALM_SEC($00)
  SET_ALM_MIN($00)                     ' Set alarm minuites to 0
'  b1 = READ_MINUITES
'  USART.write("CURRENT MINUITES - ",HexToStr(b1),10,13)
'  DelayMS(1)
  b1 = b1 + pSec

  b1 = READ_ALM_SEC                   ' 
  b1 = b1 + pSec
  If LowNibble(b1) > 9 Then            ' Adjust the minuites alarm reg
    b1 = (b1 + $10) - 10
  EndIf
  If HighNibble(b1) > 5 Then
    b1 = b1 - (HighNibble(b1) * $10)
  EndIf
  
  SET_ALM_SEC(b1)                      ' Set the second alarm
  ENABLE_ALM                           ' Start the timer
End Sub
'****************************************************************************
// JM - commented out so I could compile w/out MEM64K.bas
{
Public Sub WAKE_RTC_ALARM()
  dim b3, b4  as byte

  b3 = MEM_64K.READ_BYTE($0000)
  b4 = MEM_64K.READ_BYTE($0004)

'  USART.write(10,13,"H M S - ",DecToStr(b3),"  DELAY - ",DecToStr(b4),10,13)
'  DelayMS(2)
  
  Select b3
    Case 1
      ALARM_ON_SEC(b4)
    Case 2
      ALARM_ON_MIN(b4)
    Case 3
      ALARM_ON_HOUR(b4)
  End Select
End Sub
}

end module
main.bas (using SPI1)

Code: Select all

device = 18F27Q84
clock = 64

include "intosc.bas"        // assumes using the int osc
include "setdigitalio.bas"

'PPS Tool version: 0.0.6.4
'PinManager data: v1.81.7b
include "pps.bas"
#option USART_RX = PORTC.6
#option USART_TX = PORTC.7
include "USART.bas"

#option SPI_SCK = PORTC.3
#option SPI_SDI = PORTC.4
#option SPI_SDO = PORTC.5
include "SPIxv.bas"

// assign rtc cs IO pin
#option RTC_SPI_CS = PORTB.3
include "ds1394.bas"

// from PPS tool
public sub InitPPS()
    pps.unlock()

    'Module: SPI1
    RC3PPS = $31        'SCK1 > RC3
    SPI1SCKPPS = $13    'RC3 > SCK1 (bidir)
    SPI1SDIPPS = $14    'RC4 > SDI1
    RC5PPS = $32        'SDO1 > RC5

    'Module: UART pin directions
    input(PORTC.6)     ' Make RX1 pin an input
    output(PORTC.7)    ' Make TX1 pin an output
    'Module: UART1
    U1RXPPS = $16      'RC6 > RX1
    RC7PPS = $20       'TX1 > RC7

    pps.lock()
end sub

main:
    SetAllDigital()
    InitPPS()

    USART.SetBaudrate(br9600)
    ds1394.INIT_RTC()
    
    // probably want to set these first, but as an example...
    ds1394.show_time()
    ds1394.show_date()

end program

As to the use of defining the SPI_CS as an option in ds1934, by using the following:

Code: Select all

#option RTC_SPI_CS = PORTB.3    // assign a default for rtc_cs
dim rtc_cs as RTC_SPI_CS.RTC_SPI_CS@
You can easily change the CS pin just by changing the #option setting in the main program without having to change anything in the module itself.
Say you wanted to use PORTC.1 instead you'd just change the lines in main to:

Code: Select all

// assign rtc cs IO pin
#option RTC_SPI_CS = PORTC.1
include "ds1394.bas"
ds1934 defines a default setting that will be used if the user doesn't over-ride the #option before including the file.
You could always leave that part out and force the user to define one, but I usually like to include it so you get an
idea what options can be changed, and what the settings are.

The strange syntax 'dim rtc_cs as RTC_SPI_CS.RTC_SPI_CS@' is used to get a 'port.pin' definition from a #option into a dim format...
the first part ('RTC_SPI_CS') gets you the port, and the second part ('.RTC_SPI_CS@') gets you the pin number.

In the original version you have a number of private declarations for IO pins. This can end up being hard to troubleshoot/keep track of, and makes it difficult to reuse the module somewhere else. If you have multiple files in the project, imagine a year from now trying to find out why the heck PORTC.4 is toggling somewhere in the program among the 20 some different include files.

Instead of using options you could always create a little module with nothing but public pin definitions in it and include that in all your files, but that can be a headache too.

And, if I am using the default input ports, such as RC3 for SCK1, do I still need to map it? It seems the Jxx parts have very long lead times, so I need to understand the differences to the Kxx and Qxx parts.
Given a choice I'd go with the Q family. The J parts are older so more expensive (and are 3.3V only), while the Q is the newest so probably more available and cheaper (and many run from 5V down to 1.8V). Most of the K family is in between somewhere.

Regarding PPS mapping, some older parts may default, but on all the more recent parts there are typically defaults for PPS inputs but none for PPS outputs. Since you have to map the outputs anyway I like to go ahead and specify everything that gets PPS mapped... that way it's clearer what's being used for what.


There are a number of different ways to change ds1394.bas so it can be set to use either SPIxv.bas (SPI1) or SPI2xv.bas (SPI2), but that involves getting rid of all the 'SPI.' module references, or creating aliases to all the spi calls and using those instead. Better to leave that to another day unless you have an urgent need right now.

Post Reply