PDA

View Full Version : DS3231 code using hardware I2C capabilities?



CuriousOne
- 10th December 2025, 06:03
Hello.
I'm using DS3231, but I'm also running MIBAM on the same chip, so it screws up I2CREAD/I2CWRITE statements. Have anyone succeed with using MSSP for interacting with DS3231 ?

richard
- 10th December 2025, 07:55
http://support.melabs.com/forum/picbasic-pro-compiler-3-0-and-later/working-code-examples/7062-example-code-for-using-pic-hardware-i2c

CuriousOne
- 10th December 2025, 20:17
The connection for this site is not secure
support.melabs.com uses an unsupported protocol.
ERR_SSL_VERSION_OR_CIPHER_MISMATCH

Tried different browsers/proxies/etc.

richard
- 10th December 2025, 23:04
it works spasmodically theses days. [one more nail in pbp coffin]

i find it will work with edge or chrome , sometimes incognito window works better




;************************************************* ***************
;* Name : I2C EEPROM *
;* Author : Daniel T. Barber *
;* Notice : Copyright (c) 2018 *
;* : No expressed or implied reliability *
;* Date : 1/25/2018 *
;* Version : 1.0 *
;* Notes : Written for PIC16F1877. If using a differnt PIC *
;* : adjust MSSP Module Variables consistent with *
;* : the specific PIC datasheet *
;* : Written for use with LabX-1 development board *
;* : and 24LC64 EEPROM (WORD size memory addressing) *
;* : Adjust CTRL address value as necessary *
;* : Software I2C routines are for debugging *
;* : If necessary, uncommment routines in Main Code *
;* *
;************************************************* ***************


@ ERRORLEVEL -306 ; turn off crossing page boundary message

#CONFIG
CONFIG FOSC = INTIO67
CONFIG PLLCFG = ON
CONFIG PRICLKEN = OFF
CONFIG FCMEN = OFF
CONFIG IESO = OFF
CONFIG PWRTEN = OFF
CONFIG BOREN = SBORDIS
CONFIG BORV = 190
CONFIG WDTEN = ON
CONFIG WDTPS = 32768
CONFIG CCP2MX = PORTC1
CONFIG PBADEN = OFF
CONFIG CCP3MX = PORTB5
CONFIG HFOFST = ON
CONFIG T3CMX = PORTC0
CONFIG P2BMX = PORTB5
CONFIG MCLRE = EXTMCLR
CONFIG STVREN = ON
CONFIG LVP = OFF
CONFIG XINST = OFF
CONFIG DEBUG = OFF
CONFIG CP0 = OFF
CONFIG CP1 = OFF
CONFIG CP2 = OFF
CONFIG CP3 = OFF
CONFIG CPB = OFF
CONFIG CPD = OFF
CONFIG WRT0 = OFF
CONFIG WRT1 = OFF
CONFIG WRT2 = OFF
CONFIG WRT3 = OFF
CONFIG WRTC = OFF
CONFIG WRTB = OFF
CONFIG WRTD = OFF
CONFIG EBTR0 = OFF
CONFIG EBTR1 = OFF
CONFIG EBTR2 = OFF
CONFIG EBTR3 = OFF
CONFIG EBTRB = OFF
#ENDCONFIG





define OSC 64
OSCCON = %11110000
osctune.6=1
ANSELb = 0
ANSELA = 0
ANSELC = 0

DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 0
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 5
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 4
Define LCD_Bits 4
DEFINE LCD_LINES 4
Define LCD_Commandus 2000
Define LCD_DATAUS 50




;************ LCD Instruction Constants & Variables *************
Cmd Con $FE ;Used to send instructions to LCD
CLR Con $01 ;Clears LCD & Homes Cursor
Cursor_Off Con $0C ;Turns OFF Cursor
Cursor_Underline Con $0E ;Turns on Underline cursor
Cursor_Block Con $0F ;Turns on Blinking block cursor
Cursor_Right Con $14 ;Advance cursor 1 space to right
Cursor_Left Con $10 ;Advance cursor 1 space to left
Home Con $02 ;Sends Cursor to Home position
'LCD_PWR VAR PORTD.7 ;Connects LCD to VCC
Line_1 Con $80 ;Position Cursor at beginning of line 1
Line_2 Con $C0 ;Position Cursor at beginning of line 2
Scroll_Left Con $18 ;Scroll all lines 1 space to left
Scroll_Right Con $1C ;Scroll all lines 1 space to right
Blank_Display Con $08 ;Blank display without clearing
Restore_Display Con $0C ;Restores display with cursor hidden (same as Cursor_Off)
CG_RAM Con $40 ;Special-character RAM, address 0.
DD_RAM Con $80 ;Display RAM, address 0


;************ I2C Variables ************
SCL VAR PORTC.3 ; Clock pin
SDA VAR PORTC.4 ; Data pin


;**************** General Variables ****************
I VAR word ;General purpose counter


;**************** I2C Controller Variables ****************
CTRL Con $A0 ;Specific address for this I2C device
Address_B Var byte ;Use with EEPROM using byte memory addresses
Address_W Var Word ;Use with EEPROM using word memory addresses
Data_Out_B VAR byte ;Byte Data to be shifted out
Data_Out_W VAR word ;Word Data to be shifted out
Data_In_B Var byte ;Byte Data to be shifted In
Data_In_W Var word ;Word Data to be shifted In
I2C_DATA var byte ;Hardare I2C variable
tries var byte
i2c_error var byte




;**************** Hardware I2C Variables ****************
CTRL_W con $A0
CTRL_R con $A1


;************ MSSP Module Variables *************
WCOL var SSP1CON1.7 ;Write collision indicator
SSPOV var SSP1CON1.6 ;Receive overflow indicator
SSPEN var SSP1CON1.5 ; I2C Serial Port Enable
ACKSTAT var SSPCON2.6 ;Slave ACK Response: 1 = ACK received, 0 NACK received
ACKDT var SSPCON2.5 ;Master ACK Response: 1 = send ACK, 0 send NACK
ACKEN var SSPCON2.4 ;Send the Master ACK Response
RCEN var SSPCON2.3 ;Set Master to Receive Mode - Auto clears at end of receive
PEN var SSPCON2.2 ;Send Stop Sequence
RSEN var SSPCON2.1 ;Send Repeated Start Sequence
SEN var SSPCON2.0 ;Send Start Sequence
TX_Stat var SSPSTAT.2 ;Status of TX Sequence: 1 = TX in progress, 0 = TX finished
BF var SSPSTAT.0 ;Buffer Full Status bit: 1 = Receive Complete, 0 = Receive not complete
SSPIF var PIR1.3 ;Serial Port Interrupt flag: 1 = operation complete


;************ Configure MSSP Module *************
SSP1CON1 = $28 ;Master Mode
SSPEN = 1 ; I2C enabled
SSPSTAT = $80 ;100 KHz bus
SSPADD = $26 ;Set Baud Rate


;************ Initialize *************
PAUSE 1000
Gosub Initialize_LCD
PAUSE 100


;************ Main Code *************
Main:
do
;Software I2C routines
;Gosub Software_I2C_WB ;Write byte sized data using PPB commands
;Gosub Software_I2C_RB ;Read byte sized data using PPB commands
;Gosub Software_I2C_WW ;Write Word sized data using PPB commands
;Gosub Software_I2C_RW ;Read Word sized data using PPB commands


;Hardware I2C routines
gosub Hardware_I2C_WB ;Write byte sized data using MSSP
gosub Hardware_I2C_RB ;Read byte sized data using MSSP
gosub Hardware_I2C_WW ;Write word sized data using MSSP
gosub Hardware_I2C_Rw ;Read word sized data using MSSP
loop


;************ Sub-Routines ************
;************ Initialize LCD ************
Initialize_LCD:
' high LCD_PWR ;Turn on LCD
pause 1000 ;Wait for LCD to power up
Lcdout Cmd, Clr
lcdout CMD,Cursor_off
lcdout CMD, Line_1 + 5, "I2C Demo"
Pause 3000 ;Display message for 3 seconds
lcdout CMD,clr ;Clear display
Return


;************ Software I2C Byte Write *************
Software_I2C_WB: ;Write byte sized data using PPB commands


SSPEN = 0 ;MSSP module off

Lcdout Cmd, Clr
lcdout CMD, Line_1 + 2,"Software I2C"
lcdout CMD, Line_2, "Write Byte Variables"
pause 2000

For I = 0 to 5 Step 1
address_W = I ;Address_W is a word size variable
Data_Out_B = I * 10 ;Data_Out_B is byte size variable
i2cwrite SDA, SCL, $A0, address_W,[Data_Out_B]
Pause 10
Lcdout Cmd, Clr
lcdout CMD, Line_1, "Write Address = ", dec address_W
lcdout CMD, Line_2, "Byte Data = ", dec Data_Out_B
pause 1000
next I
return


;************ Software I2C Byte Read *************
Software_I2C_RB: ;Read byte sized data using PPB commands


SSPEN = 0 ;MSSP module off

Lcdout Cmd, Clr
lcdout CMD, Line_1 + 2,"Software I2C"
lcdout CMD, Line_2, "Read Byte Values"
pause 2000

For I = 0 to 5 step 1
address_W = I
i2cread SDA, SCL, $A0, address_W,[Data_In_B]
Pause 10
Lcdout Cmd, Clr
lcdout CMD, Line_1, "Read Address = ", dec address_W
lcdout CMD, Line_2, "Byte Data = ", dec Data_In_B
pause 1000
next I
Return

;************ Hardware I2C Write Byte Sized Variables *************
Hardware_I2C_WB:


SSPEN = 1 ;MSSP module on

Lcdout Cmd, Clr
lcdout CMD, Line_1 + 2,"Hardware I2C"
lcdout CMD, Line_2 + 2, "Byte Variables"
pause 2000

;************ Write to EEPROM *************
For I = 0 to 5 Step 1
address_W = I ;Address_W is a word size variable
Data_Out_B = (I * 10) + 1 ;Data_Out_B is byte size variable

Lcdout Cmd, Clr
lcdout CMD, Line_1, "Write Address = ", dec address_W
lcdout CMD, Line_2, "Byte Data = ", dec Data_Out_B

gosub I2C_START ;Begin I2C sequence


I2C_DATA = CTRL_W ;Send Control + write command
gosub I2C_TX


'I2C_DATA = address_W.byte1 ;Address high byte
'gosub I2C_TX

I2C_DATA = address_W.byte0 ;Address low byte
gosub I2C_TX


I2C_DATA = Data_Out_B ;Data byte
gosub I2C_TX


gosub I2C_STOP ;Stop Write sequence


pause 1000 ;Delay for LCD display of values


Next I


return


;************ Hardware I2C Read Byte Sized Variables *************
Hardware_I2C_RB: ;Read byte sized data using hardware I2C


SSPEN = 1 ;MSSP module on

Lcdout Cmd, Clr
lcdout CMD, Line_1 + 2,"Hardware I2C"
lcdout CMD, Line_2 + 1, "Read Byte Values"
pause 2000

For I = 0 to 5 step 1
address_W = I

gosub I2C_START ;Begin I2C sequence


I2C_DATA = CTRL_W ;Send Control + write command
gosub I2C_TX


'I2C_DATA = address_W.byte1 ;Address high byte
'gosub I2C_TX

I2C_DATA = address_W.byte0 ;Address low byte
gosub I2C_TX


gosub I2C_Restart ;Reset bus before sending Read control byte


I2C_DATA = CTRL_R ;Send Control + read command
gosub I2C_TX


gosub I2C_RX ;Clock data into MSSP buffer


gosub I2C_NACK ;Terminate EPPROM sending data


gosub I2C_STOP ;Stop Read sequence


Data_IN_B = SSPBUF ;Read data from MSSP buffer


Lcdout Cmd, Clr
lcdout CMD, Line_1, "Read Address = ", dec address_W
lcdout CMD, Line_2, "Byte Data = ", dec Data_In_B
pause 1000
Next I


return


;************ Software I2C Word Write *************
Software_I2C_WW: ;Write word sized data using PPB commands


SSPEN = 0 ;MSSP module off

Lcdout Cmd, Clr
lcdout CMD, Line_1 + 2,"Software I2C"
lcdout CMD, Line_2, "Write Word Variables"
pause 2000

For I = 0 to 10 Step 2
address_W = I ;Address_W is a word size variable
Data_Out_W = I * 1000 ;Data_Out_W is word size variable
i2cwrite SDA, SCL, $A0, address_W,[Data_Out_W.byte1,Data_Out_W.byte0]
Pause 10
Lcdout Cmd, Clr
lcdout CMD, Line_1, "Write Address = ", dec address_W
lcdout CMD, Line_2, "Word Data = ", dec Data_Out_W
pause 1000
next I
return


;************ Software I2C Read Word *************
Software_I2C_RW: ;Read byte sized data using PPB commands
SSPEN = 0 ;MSSP module off

Lcdout Cmd, Clr
lcdout CMD, Line_1 + 2,"Software I2C"
lcdout CMD, Line_2, "Read Word Values"
pause 2000

For I = 0 to 10 step 2
address_W = I
i2cread SDA, SCL, $A0, address_W,[Data_In_W.byte1,Data_In_W.byte0]
Pause 10
Lcdout Cmd, Clr
lcdout CMD, Line_1, "Read Address = ", dec address_W
lcdout CMD, Line_2, "Word Data = ", dec Data_In_W
pause 1000
next I
Return

;************ Hardware I2C Write Word Sized Variables *************
Hardware_I2C_WW:


SSPEN = 1 ;MSSP module on

Lcdout Cmd, Clr
lcdout CMD, Line_1 + 2,"Hardware I2C"
lcdout CMD, Line_2 + 2, "Word Variables"
pause 2000

;************ Write to EEPROM *************
For I = 0 to 10 Step 2 ;Word values require 2 bytes
address_W = I ;Address_W is a word size variable
Data_Out_W = I * 1000 ;Data_Out_W is word size variable

Lcdout Cmd, Clr
lcdout CMD, Line_1, "Write Address = ", dec address_W
lcdout CMD, Line_2, "Word Data = ", dec Data_Out_W
pause 1000

gosub I2C_START ;Begin I2C sequence


I2C_DATA = CTRL_W ;Send Control + write command
gosub I2C_TX


'I2C_DATA = address_W.byte1 ;Address high byte
'gosub I2C_TX

I2C_DATA = address_W.byte0 ;Address low byte
gosub I2C_TX


I2C_DATA = Data_Out_W.byte1 ;Word value high byte
gosub I2C_TX


I2C_DATA = Data_Out_W.byte0 ;Word value low byte
gosub I2C_TX


gosub I2C_STOP ;Stop Write sequence


Next I


return


;************ Hardware I2C Read Word Sized Variables *************
Hardware_I2C_RW: ;Read word sized data using hardware I2C
;Word is the result of seqentially reading two consecutive memory addresses
SSPEN = 1 ;MSSP module on

Lcdout Cmd, Clr
lcdout CMD, Line_1 + 2,"Hardware I2C"
lcdout CMD, Line_2 + 1,"Read Word Values"
pause 2000

For I = 0 to 10 step 2 ;Word values occupy two bytes
address_W = I

gosub I2C_START ;Begin I2C sequence


I2C_DATA = CTRL_W ;Send Control + write command
gosub I2C_TX


'I2C_DATA = address_W.byte1 ;Address high byte
'gosub I2C_TX

I2C_DATA = address_W.byte0 ;Address low byte
gosub I2C_TX


gosub I2C_Restart ;Reset I2C bus before sending read command


I2C_DATA = CTRL_R ;Send Control + read command
gosub I2C_TX


gosub I2C_RX ;receive byte
Data_IN_w.byte1 = SSPBUF ;High byte of word variable


gosub I2C_ACK ;Signal EEPROM to send next byte


gosub I2C_RX ;receive byte
Data_IN_w.byte0 = SSPBUF ;Low byte of word variable
gosub I2C_nACK
gosub I2C_STOP ;Stop Read sequence


Lcdout Cmd, Clr
lcdout CMD, Line_1, "Read Address = ", dec address_W
lcdout CMD, Line_2, "Word Data = ", dec Data_In_W
pause 1000
Next I


return


;**************** I2C Hardware Subroutines ****************


I2C_Restart: ;Send Restart Sequence
RSEN = 1 ; RSEN - Repeat Start Condition Enable Bit
SSPIF = 0; Reset Interrupt flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by Re-start sequence
RETURN


;=====================================
I2C_START: ;Send Start Sequence
SEN = 1 ; SEN - Start Condition Enable Bit
SSPIF = 0; Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by Start sequence
RETURN


;=====================================
I2C_RX:
RCEN = 1 ; RCEN - Enable receive mode
SSPIF = 0; Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by Receive sequence
;pause 1
Return


;=====================================
I2C_TX:
;tries=5 ;see below
SSPBUF = I2C_DATA ; Move data to SSPBUF
WHILE TX_Stat : WEND
WHILE ACKSTAT : WEND ;or use something like this for a timeout
;timeout if no ack
'WHILE (ACKSTAT&&tries) ;wait for slave to respond
'tries=tries-1
'pauseus 15
'WEND
'if !tries then i2c_error=1
Return






;=====================================
I2C_STOP: ;Send Sotp Sequence
PEN = 1 ; PEN - send stop bit
SSPIF = 0; Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by Stop sequence
;pause 1
Return


;=====================================
I2C_NACK: ;Send NACK
ACKDT = 1 ; ACKDT - Set Ack bit to NotAck
ACKEN = 1 ; ACKEN - send ACKDT bit
SSPIF = 0; Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by NACK sequence
Return


;=====================================
I2C_ACK: ;Send ACK
ACKDT = 0 ; ACKDT - Set Ack bit to Ack
ACKEN = 1 ; ACKEN - send ACKDT bit
SSPIF = 0; Must reset flag
WHILE SSPIF = 0 : WEND ; Wait for SSPIF to be set to 1 by ACK sequence
'pause 1
Return