📄 ds1629.asm
字号:
; ds1629.asm
; Program to demonstrate various operations on the DS1629 device. For more info, see
; the data sheet
LIST P=16F877, R=DEC
INCLUDE "P16F877.inc"
; Definitions for the DS1629
DEVADD_1629 EQU 0x9E ; I2C device address for DS 1629
; Commands that the DS 1629 supports
ACCESS_CONFIG EQU 0xAC ; Access the config register for read or write
START_CONVERT EQU 0xEE ; Start a temperature conversion
STOP_CONVERT EQU 0xEE ; Stop a temperature conversion
TEMP_READ_CMD EQU 0xAA ; Read the temp, 1 or 2 bytes
READ_COUNTER EQU 0xA8 ; Read the count_remain register
READ_SLOPE EQU 0xA8 ; Read the count_per_c register
ACCESS_CLOCK EQU 0xC0 ; Access the clock/calendar register
ACCESS_ALARM EQU 0xC7 ; Access the alarm register
ACCESS_THERM_H EQU 0xA1 ; Access the thermostat register high register
ACCESS_THERM_L EQU 0xA2 ; Access the thermostat register high register
ACCESS_RAM EQU 0x17 ; Access the onboard RAM
; Definitions for the PIC
SDA EQU 4 ; PORT C bit for SDA
SCL EQU 3 ; PORT C bit for SCL
I2CRW EQU 2 ; R/_W bit in SSPSTAT
RAM EQU 0x20
Temp EQU RAM+6
Counter EQU RAM+7
DTemp1 EQU RAM+8
DTemp2 EQU RAM+9
Temper1 EQU RAM+10
Temper2 EQU RAM+11
Status EQU RAM+12
RamAddress EQU RAM+13
RamValue EQU RAM+14
DTemp3 EQU RAM+15
; Start of the Program
ORG 3
goto Start
ORG 0x20
Start
; Initialize the TRIS registers. Importantly, SDA and SCL must be inputs
bsf STATUS, RP0
clrf TRISA ; for led bar
clrf TRISD ; for led bar
bsf TRISC,SDA
bsf TRISC,SCL
bcf STATUS, RP0
; Initialize the I2C control
call I2CConfig
; This tests three things - read the status, read and write memory and read the temperature
; You should see the default status 0xC0, then 0xA3 and finally the two bytes of the
; temperature with one second displays before starting over. The temperature at 70 degrees F
; displays as 0x17 and then 0x80
mainloop
call TestStatus
movlw 1
call Delay_sec
call TestMem
movlw 1
call Delay_sec
call TestTemp
movlw 1
call Delay_sec
goto mainloop
TestMem
movlw 0xA3
movwf RamValue
movlw 0x10
movwf RamAddress
call WriteRam
movwf 100
call Delay_ms
call ReadRam
movf RamValue,W
call DispLedBar
return
; Get and display the status byte
TestStatus
call ReadStatus
movf Status,W
call DispLedBar
return
; Now read the temperature.
TestTemp
call TempRead
call TempDisplay
return
; Reading the temperature is a two byte operation (if accuracy is desired)
; The sequence is:
; Start, Send Address, Send Command, Restart, Send Address, Read MSB,
; Send Ack, Read LSB, Send Nack, Stop
TempRead
call I2CStart
; Send the control byte
movlw DEVADD_1629
andlw 0xFE ; make it a write
call I2CSend
; Send the read temperature command
movlw TEMP_READ_CMD
call I2CSend
; Restart for read of data
call I2CRestart
; Send the address again
movlw DEVADD_1629
iorlw 0x01 ; make it a read
call I2CSend
; and read the data with an ACK between the bytes
call I2CReceive
movwf Temper1
call I2CAck
call I2CReceive
movwf Temper2
call I2CNack
; Bring a merciful end to this
call I2CStop
return
TempDisplay
movf Temper1,W
call DispLedBar
movlw 1
call Delay_sec
movf Temper2,W
call DispLedBar
movlw 1
call Delay_sec
return
; Reading that status can be either one or two bytes. Here, do only 1 byte
; Start, Send devaddr (write), send command, restart, send devaddr (read), read MSB
; send Nack, stop
ReadStatus
call I2CStart
; Send the control byte
movlw DEVADD_1629
andlw 0xFE ; make it a write
call I2CSend
; Send the read status command
movlw ACCESS_CONFIG
call I2CSend
; Restart for read of data
call I2CRestart
; Send the address again
movlw DEVADD_1629
iorlw 0x01 ; make it a read
call I2CSend
; and read the MSB
call I2CReceive
movwf Status
call I2CNack
call I2CStop
return
; ---------------------------------------------------------
; Write to RAM has the following sequence
; Start, send control (write), send address, send data, stop
WriteRam
call I2CStart
; Send the control byte
movlw DEVADD_1629
andlw 0xFE ; make it a write
call I2CSend
; Send the command
movlw ACCESS_RAM
call I2CSend
; Send the address
movf RamAddress,W
call I2CSend
; Send the data
movf RamValue,W
call I2CSend
; Stop
call I2CStop
return
; ---------------------------------------------------------
; Reading RAM has the following sequence
; Start, send control (write), send address, Restart, send control (read), read data,
; send Nack, stop
ReadRam
call I2CStart
; Send the control byte
movlw DEVADD_1629
andlw 0xFE ; make it a write
call I2CSend
; Send the command
movlw ACCESS_RAM
call I2CSend
; Send the address
movf RamAddress,W
call I2CSend
; Restart
call I2CRestart
; Send the control byte
movlw DEVADD_1629
iorlw 0x01 ; make it a read
call I2CSend
; Read the data
call I2CReceive
movwf RamValue
; Ack the data
call I2CNack
; Stop
call I2CStop
return
;----------------------------------------------------------------------------------
; I2C control routines
I2CConfig
; movlw b'00111011' ; enable SSP and set mode to Master/Slave Idle
movlw b'00111000' ; to be used when SPADD is used to set the speed
movwf SSPCON
bsf STATUS, RP0
; the following three or do none of these and accept the defaults.
; clrf SSPCON2
; bcf SSPSTAT, SMP
; bcf SSPSTAT, CKE
; If using SPADD, calculate SPADD = (Fosc/(i2c_clock_speed * 4)) - 1
; e.g. the DS1629 has a maximum clock rate of 400 kHz, so
; SPADD = 20x10^6/(4x10^5 * 4) - 1 = 11.5
movlw 12
movwf SSPADD
bcf STATUS, RP0
return
; Issue a start
I2CStart
bsf STATUS, RP0
bsf SSPCON2, SEN ; initiate a start condition
bcf STATUS, RP0
call I2CWait
return
; Issue a restart
I2CRestart
bsf STATUS, RP0
bsf SSPCON2, RSEN ; initiate a restart condition
bcf STATUS, RP0
call I2CWait
return
; Issue a stop
I2CStop
bsf STATUS, RP0
bsf SSPCON2, PEN ; initiate a stop condition
bcf STATUS, RP0
call I2CWait
return
; Send a byte
I2CSend
movwf SSPBUF ; Start a write op
call I2CWait
return
; Receive a byte
I2CReceive
bsf STATUS, RP0
bsf SSPCON2, RCEN ; Start receive
bcf STATUS, RP0
call I2CWait
movf SSPBUF, W ; return in W
return
; Initiate an Ack response from the master
I2CAck
bsf STATUS, RP0
bcf SSPCON2, ACKDT ; setup ACK
bsf SSPCON2, ACKEN ; send ACK
bcf STATUS, RP0
call I2CWait
return
; Initiate a Nack response from the master
I2CNack
bsf STATUS, RP0
bsf SSPCON2, ACKDT ; setup NACK
bsf SSPCON2, ACKEN ; send NACK
bcf STATUS, RP0
call I2CWait
return
; -----------------------------------------------------------------
; Various I2C wait operations
; Wait for an operation end by waiting for the BF bit in SSPSTAT
I2CBFWait
bsf STATUS, RP0
btfsc SSPSTAT, BF
goto $-1
bcf STATUS, RP0
return
; Wait for an operation end by waiting for the R/W bit
I2CRWWait
bsf STATUS, RP0
btfsc SSPSTAT, I2CRW
goto I2CRWWait
bcf STATUS, RP0
return
; Wait for an operation end by waiting for the BF bit in SSPSTAT
I2CAckWait
bsf STATUS, RP0
btfsc SSPSTAT, ACKSTAT
goto $-1
bcf STATUS, RP0
return
; Wait for end of I2C operation by watching the SSPIF flag
I2CWait
btfss PIR1, SSPIF
goto I2CWait
bcf PIR1, SSPIF ; clear for next operation
return
; ----------------------------------------------------------
; Display routines
; Routine to display something on the LED bank
DispLedBar
; Enable the led bar and put the value in W there.
movwf Temp ; save W
movlw 0x12
movwf PORTA
comf Temp,W
movwf PORTD
return
; Display something on the Led Bar and wait for one second -
; handy for debugging
DisplayDebug
call DispLedBar
movlw 1
call Delay_sec
; -------------------------
; Delay routines
; Delay microseconds (usec)
Delay_us
movwf DTemp1
dloop_u1 ; one loop = about 1 usec
fill (nop), 3
decfsz DTemp1,F
goto dloop_u1
return;
; Delay milliseconds
Delay_ms
movwf DTemp1
dloop_0 ; number of ms to delay
movlw 250
movwf DTemp2
dloop_1 ; 1 ms delay (approximately)
fill (nop), 17
decfsz DTemp2,F
goto dloop_1
decfsz DTemp1,F
goto dloop_0
return
; Delay seconds
Delay_sec
movwf DTemp1 ; number of seconds to delay
dloop_s0
movlw 250 ; 1 second delay
movwf DTemp2
dloop_s1
movlw 250 ; 4 ms delay
movwf DTemp3
dloop_s2
fill (nop), 78
decfsz DTemp3,F
goto dloop_s2
decfsz DTemp2,F
goto dloop_s1
decfsz DTemp1,F
goto dloop_s0
return
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -