⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smscmd.asm

📁 Tiny Planet is small device connected to a GSM cell phone. When the mobile receives a predefined SMS
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;*********************** 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 + -