📄 smscmd.asm
字号:
;*********************** TINY PLANET ******** DL194 ************************
;*
;* (C) 2001 by Alberto Ricci Bitti & Claudio Lanconelli
;*
;* www.riccibitti.com www.lancos.com
;*
;*
;* The tiny AVR communicates with the phone via a rs232 line in half duplex.
;* Every command starts with the AT sequence and the reply terminates with the
;* OK string if the command complete with success.
;* On startup the tiny AVR sends a command to instruct the phone to use the
;* phone memory for SMS storage.
;* If you press the configuration/reset button the tiny AVR is resetted and
;* then it starts reading the SMS in the memory locations #3, #4, #5, #6 on
;* the phone.
;* The last six bytes of each messages are used as a sort of KEY to
;* identify the message. This KEY is stored on the tiny AVR eeprom and is
;* compared to every SMS that will be received by the phone. Each message
;* key brings a different action: send the SMS on memory #1 or #2 depending
;* on the status of the input; switch on the output; switch off the output;
;* send a pulse on the output. The tiny AVR keeps the memory #7 of the phone
;* free by deleting every message read. The phone stores every received
;* message in the first free location, in this case the first free location
;* is memory #7 bacause on memories #1 and #2 are stored the message to send,
;* and on memories #3,#4,#5,#6 are stored the configuration messages.
;* The tiny AVR also monitors the input pin, in case of a pin change it
;* sends the SMS stored in the following memories:
;* memory #1 in case of input low (Off)
;* memory #2 in case of input high (On)
;* The automatic send can be disabled by closing the autosend jumper.
;*
;**************************************************************************
.include "tn12def.inc"
;***** Pin definitions
.equ CONFIG_BUTTON = 5 ;Reset/configuration pin
.equ RXD_PIN = 4 ;RS232 Rx pin
.equ TXD_PIN = 2 ;RS232 Tx pin
.equ AUTOSEND_JP = 0 ;autosend jumper
.equ INPUT1 = 3 ;Input pin
.equ OUTPUT1 = 1 ;Output pin
;***** Register variables
;;Note R0, R30, R31 are used bye some instructions like ld data,Z and lpm
;;Buffer for the uart Rx routine
.def Buf0 =r1
.def Buf1 =r2
.def Buf2 =r3
.def Buf3 =r4
.def Buf4 =r5
.def Buf5 =r6
.def Buf6 =r7
.def Buf7 =r8
;;Bit delay register for uart Tx and Rx timing: this can't be a constant since the
;; oscillator frequency changes with the variations of VCC (battery powered)
.def old_delay =r14
.def bit_delay =r15 ;bit delay counter for UART timing
;;Temporary registers
.def temp =r16 ;temporary storage register
.def CounterL =r17 ;16 bit counter
.def CounterH =r18
.def Counter2 =r19
.def Index =r24 ;used by receive_sms() routine
.def DataReg =r26 ;UART and EEPROM data register
.def EepAdr =r27 ;Eeprom address
.def Arg1 =r28
.def Arg2 =r29
;; Global variables
.def wd_counter =r20 ;watchdog reset counter
.def in_pin =r21 ;save the status of Input pin
.def old_pin =r22 ;old status of the Input pin for a pin change notification
.def output_copy =r23 ;save the status of the Output pin (the output should be preserved after Watchdog reset)
;;******** Constants
.equ CR =0x0D
.equ LF =0x0A
.equ UART_RX_TIMEOUT = 0xffff ;timeout (65535 * 6 = 393210 --> about 393msec)
;;POLL_DELAY defines the interval between message polls
.equ POLL_DELAY = 10 ;1.9 sec units (delay = 1.9sec * POLL_DELAY)
.equ BDELAY = 16 ;9600 bps @ 1 MHz oscillator
.equ BDELAY_MIN = 10 ;minimum value for auto baud routine
.equ BDELAY_MAX = 30 ;maximum value for auto baud routine
;;***************************** EEPROM **************************************
.eseg ; Start eeprom data segment
.db 0xff ;skip first byte
bdelay_adr: .db BDELAY*2 ;default bit delay value (calculated for 5V calibrated osc)
.equ EEP_KEYSIZE = 6
first_key: .byte EEP_KEYSIZE
second_key: .byte EEP_KEYSIZE
third_key: .byte EEP_KEYSIZE
fourth_key: .byte EEP_KEYSIZE
end_key:
;;******************************* FLASH ************************************
.cseg
.org 0
;************** Vectors
rjmp reset
reti
reti
;;Command strings MUST be located within the first 256 bytes of flash to use only low 8bit address
cmd_init: .db 'A','T','+','C','P','M','S','=','"','M','E','"',',','"','M','E','"',0
cmd_msgread: .db "AT+CMGR=",0
cmd_msgsend: .db "AT+CMSS=",0
cmd_msgdel: .db "AT+CMGD=",0
cmd_at: .db "AT",0
;;*************************** MACROS ***************************************
;***************************************************************************
;* "eeprom_write"
;***************************************************************************
.MACRO EEPROM_WRITE ; Start macro definition
out EEAR, @0 ;output address
out EEDR, @1 ;output data
sbi EECR, EEMWE
sbi EECR, EEWE
sbic EECR, EEWE ; wait until EEWE flag is cleared (end of write)
rjmp PC-1
.ENDMACRO ; End macro definition
;***************************************************************************
;* "eeprom_read"
;***************************************************************************
.MACRO EEPROM_READ
out EEAR, @1 ;output address byte
sbi EECR, EERE ;set EEPROM Read strobe
;This instruction takes 4 clock cycles since
;it halts the CPU for two clock cycles
in @0, EEDR ;get data
.ENDMACRO
;***************************************************************************
;* Send AT command
;***************************************************************************
.MACRO SEND_AT
clr Arg2
ldi Arg1, cmd_at*2 ;we need to convert from word to byte address here
rcall send_cmd
.ENDMACRO
;***************************************************************************
;* Send SMS: the message sent depend on the input status
;* the SMS to be sent are stored in memory #1 and #2
;***************************************************************************
.MACRO SMS_SEND
ldi Arg1, cmd_msgsend*2 ;we need to convert from word to byte address here
ldi Arg2, '1'
tst in_pin
breq PC+2 ;leave '1' if in_pin is 0
inc Arg2
rcall send_cmd
.ENDMACRO
;***************************************************************************
;* Delete SMS: keep the phone memory free for the next message to receive
;***************************************************************************
.MACRO SMS_DEL
ldi Arg1, cmd_msgdel*2 ;we need to convert from word to byte address here
rcall send_cmd
.ENDMACRO
;***************************************************************************
;* Read SMS: Read a message from the phone memory
;***************************************************************************
.MACRO SMS_READ
ldi Arg1, cmd_msgread*2 ;we need to convert from word to byte address here
rcall send_cmd
.ENDMACRO
;***************************************************************************
;* Initialize SMS memory: use always the phone memory (don't use SIM card memory)
;***************************************************************************
.MACRO SMS_INIT
clr Arg2
ldi Arg1, cmd_init*2 ;we need to convert from word to byte address here
rcall send_cmd
.ENDMACRO
;***************************************************************************
;* Simple Multiply (in case of small multiplier)
;* @0 = @0 x @1
;* @2 temp register
;***************************************************************************
.MACRO MUL8
mov @2,@0
dec @1
add @0,@2
dec @1
brne PC-2
.ENDMACRO
;***************************************************************************
;* "UART_delay"
;***************************************************************************
;delay = 3 * (bit_delay - 1) + 2
.MACRO UART_DELAY_TX
mov @0,bit_delay
dec @0
dec @0
brne PC-1
.ENDMACRO
;************************** MAIN APPLICATION ******************************
;*
;* Initialize the hardware
;* check for the reason of the reset and take a different action
;* compare the input status with the previous one to notify any changes
;* enable pin change interrupt and watchdog before to go in power down mode
;* The pin change interrupt and Watchdog reset are used to wake up from the
;* power down mode
;*
;**************************************************************************
reset:
;Port init
ori output_copy, 0b00001101 ;force pull-up on inputs and TXD high
out PORTB, output_copy
ldi temp, 0b00000110
out DDRB, temp
;Enable watchdog with maximum timeout (about 1.9 sec)
wdr
ldi temp, (0 << WDDE)|(1 << WDE)|(1 << WDP2)|(1 << WDP1)|(1 << WDP0)
out WDTCR, temp
;Check for the cause of Reset:
; 1) External reset: launch configuration routine
; 2) Watchdog reset: polls the phone for a new SMS
; 3) PowerOn reset: initialize output and input pins
; 4) BrownOut reset: same of PowerOn reset
in temp,MCUSR
sbrs temp, EXTRF
rjmp res_wd
;;------------ External reset ------------------------
clr temp
out MCUSR, temp ;clear flag for next reset
;;Init the GSM (send CPMS command)
eres_0: SMS_INIT
rcall wait_for_ok
brcc eres_1
rcall auto_baud
brcs wres_4
rjmp eres_0
eres_1: ldi Counter2, 3+1 ;try to read the message three times before to give up
eres_loop1: dec Counter2
breq eres_3
rcall wait_for_ok
ldi Arg1, 1 ;1) FIRST message: request for input status
rcall receive_sms
brcs eres_loop1
eres_3: ldi Counter2, 3+1 ;try to read the message three times before to give up
eres_loop3: dec Counter2
breq eres_4
rcall wait_for_ok
ldi Arg1, 2 ;2) SECOND message: generate a pulse on output
rcall receive_sms
brcs eres_loop3
eres_4: ldi Counter2, 3+1 ;try to read the message three times before to give up
eres_loop4: dec Counter2
breq eres_5
rcall wait_for_ok
ldi Arg1, 3 ;3) THIRD message: switch output Off
rcall receive_sms
brcs eres_loop4
eres_5: ldi Counter2, 3+1 ;try to read the message three times before to give up
eres_loop5: dec Counter2
breq eres_6
rcall wait_for_ok
ldi Arg1, 4 ;4) FOURTH message: switch output On
rcall receive_sms
brcs eres_loop5
eres_6:
rjmp res_1
res_wd:
in temp, MCUSR
sbrs temp, WDRF
rjmp res_por
;;---------- Watchdog reset ------------------------
clr temp
out MCUSR, temp ;clear flag for next reset
dec wd_counter
brne res_1
ldi wd_counter, POLL_DELAY
wres_0:
;;Check for the presence of the phone with the AT command
SEND_AT ;send AT command and wait for OK
rcall wait_for_ok
brcc wres_1
rcall auto_baud ;if OK not received try the auto baud calibration
brcs res_1
rjmp wres_0
wres_1:
;check for any new message received...
ldi Arg1, 0
rcall receive_sms
brcs wres_4 ;don't delete the message if we can't read it or if there is no message
;..and delete it (mem #7)
ldi Arg2, '7'
SMS_DEL
wres_2: rcall wait_for_ok
brcs wres_2
wres_4: rjmp res_1
res_por: ;;-------- PowerOn or BrownOut reset --------------
clr temp
out MCUSR, temp ;clear flag for next reset
ldi output_copy, 0b00001101
out PORTB, output_copy
ldi wd_counter, POLL_DELAY
;;Read the bit delay value from EEPROM
ldi EepAdr, bdelay_adr
EEPROM_READ DataReg, EepAdr
;;Check for a valid value, otherwise load default value
cpi DataReg, BDELAY_MAX*2+1
brcc pres_0
cpi DataReg, BDELAY_MIN*2
brcc pres_1
pres_0:
ldi DataReg, BDELAY*2
pres_1:
mov bit_delay, DataReg
;;Init the GSM (issue CPMS command)
pres_2: SMS_INIT
rcall wait_for_ok
brcc pres_3
rcall auto_baud
brcs pres_3
rjmp pres_2
pres_3:
in old_pin,PINB
andi old_pin,(1<<INPUT1)
res_1: ;Enable PowerDown sleep mode
ldi temp, (0 << PUD)|(1 << SE)|(1 << SM)|(0 << ISC01)|(0 << ISC00)
out MCUCR, temp
;Enable pin change interrupt: we use this interrupt to wake up from
; powerdown mode.
ldi temp, (0 << INT0)|(1 << PCIE)
out GIMSK, temp
main_loop:
in in_pin, PINB
andi in_pin, (1<<INPUT1)
cp in_pin,old_pin
breq res_2
; if pin change event
mov old_pin,in_pin
; check for automatic send vs. send on request
sbis PINB, AUTOSEND_JP
rjmp res_2
SMS_SEND
;the Send SMS command may take some time, so
; call wait_for_ok() several times for a
; long timeout
ldi ZH, 8
res_loop1: rcall wait_for_ok
brcc res_2
dec ZH
brne res_loop1
res_2:
sei ;enable interrupt
nop ;give a chance to run the ISR
sleep ;go to powerdown mode to save battery power
nop ;give a chance to run the ISR
cli ;disable interrupt
res_3:
rjmp main_loop
;***************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -