Исходник GSM «жучка» на PIC16F648A v1.0
Реверс инжиниринг демо-прошивки радиомикрофона на PIC16F648A/PIC16F628A и древнем GSM модуле SIM300DZ.
Также см. исходники GSM радиомикрофонов на других модулях: SIM800C (PIC12F1822, очень глючная), SIM900 (PIC24FJ64GA004, очень глючная).
В отличие от «Трешки», ножек контроллера хватит и для дистанционного управления по SMS, а программа кажется гораздо более вменяемой.
Антенну GSM используйте заводускую, а не такую, как у автора, а то Ротхаммель будет вертеться в гробу, как волчок. Помните о противовесе.
Печатная плата «Трешки» является причиной страшных глюков. В этом GSM радиомикрофоне плата получше, особенно если светодиод с длинными выводами заменить бескорпусным, а микрофон применить от гарнитуры, как советует Eddy71.
Я не анализировал эту прошивку так подробно, как «Трешку», поэтому за надежность не ручаюсь. Но идея хранить номер на SIM карте и проверять по имени гарантирует отсутствие ложных срабатываний и глюков от наводок, от чего так страдает «Трешка», судя по обсуждению на VRTP.
Ни «Трешку», ни эту схему я не собирал, поэтому неприятные неожиданности возможны.
Вместо халтурных проверок ответов SIM300 по одному-двум символам нужно сделать полноценные сравнения, как с "+CMT" (см. not_a_ring).
Авторская прошивка является демонстрационной и содержит ограничения на длительность и количество звонков. Интересные места прокомментированы.
Если вдруг окажется, что микропрограмма качественная, я советую связаться с автором и купить полную версию с управлением по SMS.
Полная прошивка распространяется уже прошитая в микроконтроллер – спрашивайте у автора.
Если у Вас нету опыта и Вы собрали программатор самостоятельно, то не рискуйте, прошивая внутрисхемно. Вы можете потерять сотовый модуль.
Устройство отвечает только хозяину. Чтобы прописать его номер в международном формате (+7905……….) Вам надо записать на сим-карту его номер под имеем Ph1. Обязательно отмените ввод пин-кода. Программирование осуществляется с помощью мобильника. Будьте внимательны – некоторые телефоны дописывают индексы к имени, это приведет к сбою работы. Например, так делают Sony Ericson.
За полной прошивкой обращайтесь к автору по ICQ: 288449055 или пишите на мыло device@open.by. Автор принимает заказы на разработку устройств с применением контроллеров, GSM и GPS технологий.
Оригинальная прошивка без исходников (говносайт «Паяльник» удалил все мои комментарии):
https://web.archive.org/web/20240512090900/https://cxem.net/radiomic/radiomic123.php
Страница с обсуждением на форуме cxem net:
https://web.archive.org/web/20251203165751/https://forum.cxem.net/topic/50702-%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B9-gsm-%D0%BC%D0%B8%D0%BA%D1%80%D0%BE%D1%84%D0%BE%D0%BD-%D0%BD%D0%B0-sim300d/
Руководство по работе с GSM/GPRS модемом SIM300 на русском языке:
https://www.macrogroup.ru/content/data/store/images/f_158_213_1.pdf
Правильная работа с UART от Microchip (AN774):
https://ww1.microchip.com/downloads/en/appnotes/00774a.pdf
https://github.com/trygvis/pic16/blob/master/application-notes/an774-Asynchronous%20Communications%20with%20the%20PICmicro%20USART/Appendix%20A%20for%20PIC16/p16_tiri.asm
Блок-схема авторского обработчика прерывания
Довольно сильно отличается от рекомендованного Microchip:
Блок-схема примененного в прошивке алгоритма работы с SIM300
Оранжевый — опрос кнопки и сенсора зарядки.
Желтый — ограничения демонстрационной версии.
Зеленый — переход в спящий режим.
Синий — отправка AT-команд модулю SIM300.
Темно-синий — управление кнопкной включения SIM300.
Фиолетовый — анализ ответов GSM модуля.
Исходный код прошивки
processor p16f648a
radix dec
include p16f648a.inc
; The recognition of labels and registers is not always good, therefore
; be treated cautiously the results.
CONFIG WDTE = ON
CONFIG PWRTE = OFF
CONFIG FOSC = INTOSCIO
CONFIG MCLRE = OFF
CONFIG BOREN = OFF
CONFIG LVP = OFF
CONFIG CPD = OFF
CONFIG CP = ON
#define MAX_CALLS 10
#define MAX_TIME 114
#define BUFSZ 49
#define TRUE 1
#define FALSE 0
#define BAUD 9600
#define F_OSC 4000000
;===============================================================================
; DATA address definitions
#define EEPROM_CALLS_COUNTER 0x64
STATUS_TEMP equ 0x21
FSR_TEMP equ 0x22
PCLATH_TEMP equ 0x28
bufptr equ 0x29
buffer equ 0x2a
after_buffer equ 0x5b ; first byte after buffer
state equ 0x5c ; finite state machine
#define STATE_OFF 0
#define STATE_READY 1
#define STATE_RESET 3
calls_counter equ 0x5d
time_counter equ 0x5e
flags equ 0x5f
#define FLAG_CALL 0
commaptr equ 0x63 ; позиция ',' в буфере с СМС
regcnt equ 0x63 ; network registration
a equ 0x63
i equ 0x63
slotptr equ 0x64 ; sms slot offset
c equ 0x64
blink_arg equ 0x64
quotes equ 0x64
namepos equ 0x64
sms_slot equ 0x65 ; sms slot value
d equ 0x65
dtr_arg equ 0x66
tmp4 equ 0x66
cmgd_arg1 equ 0x66
delay_arg equ 0x67
cmgd_arg2 equ 0x67
itoabuf0 equ 0x68
itoabuf1 equ 0x69
itoabuf2 equ 0x6a
itoabuf3 equ 0x6b
arg1 equ 0x6c
arg2 equ 0x6d
j equ 0x6e
Common_RAM equ 0x0070 ; size: 16 bytes
k equ (Common_RAM + 7)
INTCON_TEMP equ (Common_RAM + 7)
result equ (Common_RAM + 8)
button_state equ (Common_RAM + 8)
clipptr equ (Common_RAM + 8)
highbanks equ (Common_RAM + 10)
;===============================================================================
; PINS usage definitions
LED equ RA1
PWRKEY equ RB0
PIN_DTR equ RB3
CHARGER equ RB4
BUTTON equ RB5
;===============================================================================
; Macroses
Bank0 MACRO
bcf STATUS, RP0
ENDM
Bank1 MACRO
bsf STATUS, RP0
ENDM
BSF1 MACRO file, bit ; установить бит регистра из банка 1
Bank1
bsf (file), (bit)
ENDM
BCF1 MACRO file, bit ; сбросить бит регистра из банка 1
Bank1
bcf (file), (bit)
ENDM
SETPC MACRO ; для отправки AT команды
bcf PCLATH, 0
bcf PCLATH, 1
bcf PCLATH, 2
addwf PCL, F
ENDM
MOVLF MACRO value, file
movlw (value)
movwf (file)
ENDM
MOVLF0 MACRO value, file
movlw (value)
Bank0
movwf (file)
ENDM
MOVLF1 MACRO value, file
movlw (value)
Bank1
movwf (file)
ENDM
MOVFF MACRO src, dst
movf (src), W
movwf (dst)
ENDM
IFG MACRO var, n, label ; если больше
movf (var), W
sublw (n)
btfss STATUS, C
goto (label)
ENDM
IFL MACRO var, n, label ; если меньше
movf (var), W
sublw (n)
btfsc STATUS, C
goto (label)
ENDM
IFNE MACRO var, n, label ; если не равно
movf (var), W
sublw (n)
btfss STATUS, Z
goto (label)
ENDM
IFEQ MACRO var, n, label ; если равно
movf (var), W
sublw (n)
btfsc STATUS, Z
goto (label)
ENDM
DTR0 MACRO ; сбросить DTR
bcf PORTB, PIN_DTR
BCF1 TRISB, PIN_DTR
ENDM
DTRP MACRO ; дернуть DTR
bsf PORTB, PIN_DTR
BCF1 TRISB, PIN_DTR
ENDM
DELAY MACRO n ; задержка
MOVLF0 (n), delay_arg
call function_delay
ENDM
LDELAY MACRO n, file ; длинная задержка
MOVLF (n), (file)
MOVLF 250, delay_arg
call function_delay
decfsz (file), F
goto $-4
ENDM
BLINK MACRO n ; мигание светодиодом
MOVLF (n), blink_arg ; Bank0 уже выбран
call function_blink
ENDM
BLINKP MACRO n ; мигание светодиодом
MOVLF0 (n), blink_arg ; Bank0
call function_blink
ENDM
SEND MACRO char ; отправить символ
movlw (char)
btfss PIR1, TXIF
goto $-1
movwf TXREG
ENDM
SENDF MACRO file ; отправить "файл"
movf (file), W
btfss PIR1, TXIF
goto $-1
movwf TXREG
ENDM
TXSTR MACRO m, proc, n ; отправить строку
LOCAL next_char
clrf (m)
next_char:
movf (m), W
call (proc)
incf (m), F
movwf (Common_RAM + 7)
SENDF (Common_RAM + 7)
movlw (n)
subwf (m), W
btfss STATUS, Z
goto next_char
ENDM
; отправить AT-команду
ATCMDB MACRO tmp, proc, length, delay
; очистить буфер до отправки
call function_clear_buffer
TXSTR (tmp), (proc), (length)
LDELAY (delay), (tmp)
ENDM
ATCMDA MACRO tmp, proc, length, delay
TXSTR (tmp), (proc), (length)
; очистить буфер после
call function_clear_buffer
LDELAY (delay), (tmp)
ENDM
;===============================================================================
; CODE area
; code
org __CODE_START
vector_reset:
MOVLF 0, PCLATH ; select program memory page 0
goto reset_vector
nop
vector_int: ; обработчик прерываний
movwf (Common_RAM + 15)
swapf STATUS, W
clrf STATUS
movwf STATUS_TEMP
MOVFF (Common_RAM + 15), 0x20
MOVFF PCLATH, PCLATH_TEMP
clrf PCLATH
swapf 0x20, F
MOVFF FSR, FSR_TEMP
MOVFF (Common_RAM + 7), 0x23
MOVFF (Common_RAM + 8), 0x24
MOVFF (Common_RAM + 9), 0x25
MOVFF (Common_RAM + 10), 0x26
MOVFF (Common_RAM + 11), 0x27
bcf STATUS, IRP ; 0 = Bank 0, 1 (00h - FFh)
Bank0
MOVLF PIE1, FSR ; IRP:FSR<7> = 01 = Bank 1
btfss INDF, RCIE ; 1 = Enables the USART receive interrupt
goto check_timer
btfsc PIR1, RCIF ; test RCIF receive interrupt
goto byte_arrived
check_timer:
MOVLF PIE1, FSR
btfss INDF, TMR1IE ; TMR1 Overflow Interrupt Enable bit
goto restore
btfsc PIR1, TMR1IF ; TMR1 Overflow Interrupt Flag bit
goto timer_interrupt
restore: ; выход из обработчика прерывания
MOVFF FSR_TEMP, FSR
MOVFF 0x23, (Common_RAM + 7)
MOVFF 0x24, (Common_RAM + 8)
MOVFF 0x25, (Common_RAM + 9)
MOVFF 0x26, (Common_RAM + 10)
MOVFF 0x27, (Common_RAM + 11)
MOVFF PCLATH_TEMP, PCLATH
swapf STATUS_TEMP, W
movwf STATUS
swapf (Common_RAM + 15), F
swapf (Common_RAM + 15), W
retfie
byte_arrived:
bcf PCLATH, 3
goto byte_arrived2
timer_interrupt:
bcf PCLATH, 3
goto timer_interrupt2
function_ATE0:
SETPC
dt "ATE0\r", 0
function_ATCREG: ; registration status
SETPC
dt "AT+CREG?\r", 0
function_ATCMGF: ; SMS text mode
SETPC
dt "AT+CMGF=1\r", 0
function_ATCMGD: ; delete SMS
SETPC
dt "AT+CMGD=%d\r", 0
function_ATCHFA: ; set the audio channel to Half-Duplex
SETPC
dt "AT+CHFA=1\r", 0
function_ATCMIC:
SETPC
dt "AT+CMIC=1,15\r", 0
function_ATCLIP:
SETPC
dt "AT+CLIP=1\r", 0
function_ATCSCLK:
; enable the Serial Command Mode for SMS message waiting indications (SMS-CB)
; This command informs the module to send SMS-CB (Cell Broadcast) messages to the connected terminal.
SETPC
dt "AT+CSCLK=1\r", 0
function_ATA:
SETPC
dt "ATA\r", 0
function_ATH:
SETPC
dt "ATH\r", 0
function_ATCMGDC: ; delete SMS
SETPC
dt "AT+CMGD=%c\r", 0
function_ATCBC: ; report the battery charge status of the module
SETPC
dt "AT+CBC\r", 0
byte_arrived2:
; принятый ответ на AT-команду сохраняется в буфере:
; buffer[bufptr++] = RCREG;
IFG bufptr, BUFSZ, buffer_full
movf bufptr, W
incf bufptr, F
addlw buffer
movwf FSR
; Register Bank Select bit (used for indirect addressing)
; 0 = Bank 0, 1 (00h - FFh)
bcf STATUS, IRP
; источник зависаний
; правильный алгоритм работы с USART от Microchip см. в p16_tiri.asm
btfss PIR1, RCIF
goto $-1
MOVFF RCREG, INDF
goto the_end
buffer_full:
; источник зависаний
btfss PIR1, RCIF
goto $-1
; правильное поведение: при переполнении буфера лишние символы игнорируются
movf RCREG, W
the_end:
; ошибка, см. стр. 81 даташита
; Flag bit RCIF is a read-only bit, which is cleared by the hardware.
bcf PIR1, RCIF
bcf PCLATH, 3
goto restore
timer_interrupt2:
btfsc flags, FLAG_CALL
incf time_counter, F
; 1 = TMR1 register overflowed (must be cleared in software)
bcf PIR1, TMR1IF
bcf PCLATH, 3
goto restore
function_delay:
MOVLF delay_arg, FSR
bcf STATUS, IRP
movf INDF, W
btfsc STATUS, Z
goto label_015
label_011:
MOVLF 1, (Common_RAM + 8)
label_012:
MOVLF 191, (Common_RAM + 7)
clrwdt
decfsz (Common_RAM + 7), F
goto $-2
decfsz (Common_RAM + 8), F
goto label_012
MOVLF 74, (Common_RAM + 7)
decfsz (Common_RAM + 7), F
goto $-1
nop
clrwdt
decfsz INDF, F
goto label_011
label_015:
retlw 0x00
function_blink:
movf blink_arg, F
btfsc STATUS, Z
goto label_016
bcf PORTA, LED
BCF1 TRISA, LED
DELAY 250
BSF1 TRISA, LED
DELAY 250
decf blink_arg, F
goto function_blink
label_016:
retlw 0
; 1 - DTR pulse, 0 - DTR low
function_DTR:
movf dtr_arg, F
btfss STATUS, Z
goto label_017
DTR0
DELAY 50
goto label_018
label_017:
DTRP
Bank0
label_018:
retlw 0
function_clear_buffer:
clrf bufptr
label_019:
IFG bufptr, BUFSZ, label_020
movlw buffer
addwf bufptr, W
movwf FSR
bcf STATUS, IRP
clrf INDF
incf bufptr, F
goto label_019
label_020:
clrf bufptr
retlw 0
start:
; To allow the bit rate to be synchronized simply issue an "AT" or "at" string.
; This is necessary when you start up the module while autobauding is enabled
call function_clear_buffer
SEND 'A'
SEND 'T'
SEND '\r'
call function_clear_buffer
LDELAY 2, a
; кривая проверка на "OK"
IFEQ buffer, 'A', have_ok
IFEQ buffer + 2, 'O', have_ok
MOVLF FALSE, result
goto have_result
; unreachable code
goto have_result
have_ok:
MOVLF TRUE, result
goto have_result
have_result:
bcf PCLATH, 3
goto check_result
check_charger:
BSF1 TRISB, CHARGER
Bank0
; зарядка подключена?
btfss PORTB, CHARGER
goto no_charger
movf state, F
btfss STATUS, Z
goto check_battery
; передаем несколько раз "AT\r"
clrf a
send_at:
IFG a, 2, check_battery
SEND 'A'
SEND 'T'
SEND '\r'
LDELAY 2, c
incf a, F
goto send_at
check_battery:
ATCMDB c, function_ATCBC, 7, 4
; +CBC: <battery connected status>, <battery charging_loop level>, <voltage>
IFNE buffer + 15, '1', dont_blink
BLINK 1
dont_blink:
IFNE buffer + 15, '2', charger_disconnected
charging_loop:
; зацикливаемся на время зарядки
BSF1 TRISB, CHARGER
Bank0
btfss PORTB, CHARGER
goto charger_disconnected
; Для зарядки аккумулятора надо выключать устройство, подключить через
; шнур mini USB с соответствующему порту компьютера и дождаться
; постоянного горения светодиода.
bcf PORTA, LED
BCF1 TRISA, LED
DELAY 100
goto charging_loop
charger_disconnected:
goto charger_disconnected2
no_charger:
BSF1 TRISA, LED
Bank0
charger_disconnected2:
bcf PCLATH, 3
goto check_button
; Нажмите на кнопку и ждите короткой вспышки светодиода.
; Это означает, что контроллер обратил внимание на кнопку.
function_button:
BSF1 TRISB, BUTTON
Bank0
btfsc PORTB, BUTTON
goto label_048
bcf PORTA, LED
BCF1 TRISA, LED
DELAY 50
BSF1 TRISA, LED
DELAY 50
BSF1 TRISB, BUTTON
Bank0
btfsc PORTB, BUTTON
goto label_046
label_043:
BSF1 TRISB, BUTTON
Bank0
btfsc PORTB, BUTTON
goto label_045
LDELAY 2, a
goto label_043
label_045:
MOVLF TRUE, button_state
goto exit_button
goto label_047
label_046:
MOVLF FALSE, button_state
goto exit_button
label_047:
goto exit_button
label_048:
MOVLF FALSE, button_state
goto exit_button
exit_button:
retlw 0
function_SIM300D_power:
bcf PORTB, PWRKEY
BCF1 TRISB, PWRKEY
Bank0
; пауза
clrf c
label_050:
IFG c, 7, label_052
LDELAY 2, d
clrwdt
incf c, F
goto label_050
label_052:
BSF1 TRISB, PWRKEY
Bank0
retlw 0x00
power_on_continue:
clrf a
call function_clear_buffer
clrf a
label_054:
; кривая проверка на "OK"
IFEQ buffer, 'A', label_060
IFEQ buffer + 2, 'O', label_060
IFNE a, 7, label_055
call function_SIM300D_power
clrf a
label_055:
call function_clear_buffer
SEND 'A'
SEND 'T'
SEND '\r'
call function_clear_buffer
LDELAY 2, c
incf a, F
goto label_054
label_060:
call function_clear_buffer
ATCMDA c, function_ATE0, 5, 2
clrf regcnt
network_registration_loop:
; регистрация в сети
IFEQ buffer + 11, '1', registered
IFNE regcnt, 30, label_atcreg
call function_SIM300D_power
clrf regcnt
goto label_054
label_atcreg:
incf regcnt, F
ATCMDA c, function_ATCREG, 9, 2
goto network_registration_loop
registered:
bcf PCLATH, 3
goto after_registration
function_018:
movf arg2, W
clrf (Common_RAM + 8)
subwf arg1, W
btfsc STATUS, C
goto label_070
MOVFF arg1, (Common_RAM + 7)
goto label_072
label_070:
clrf (Common_RAM + 7)
MOVLF 8, j
label_071:
rlf arg1, F
rlf (Common_RAM + 7), F
movf arg2, W
subwf (Common_RAM + 7), W
btfsc STATUS, C
movwf (Common_RAM + 7)
rlf (Common_RAM + 8), F
decfsz j, F
goto label_071
label_072:
retlw 0
itoa:
; преобразование числа в строку
movlw ' '
btfss cmgd_arg2, 4
MOVLF '0', itoabuf0
MOVFF cmgd_arg1, (Common_RAM + 7)
btfss cmgd_arg1, 7
goto label_074
comf (Common_RAM + 7), F
incf (Common_RAM + 7), F
MOVFF (Common_RAM + 7), cmgd_arg1
MOVLF '-', itoabuf0
bsf cmgd_arg2, 7
label_074:
MOVFF cmgd_arg1, arg1
MOVLF 100, arg2
call function_018
MOVFF (Common_RAM + 7), cmgd_arg1
movlw '0'
addwf (Common_RAM + 8), W
movwf itoabuf1
MOVFF cmgd_arg1, arg1
MOVLF 10, arg2
call function_018
movlw '0'
addwf (Common_RAM + 7), W
movwf itoabuf3
movlw '0'
addwf (Common_RAM + 8), W
movwf itoabuf2
MOVFF itoabuf0, (Common_RAM + 7)
btfss cmgd_arg2, 0x3
goto $+3
btfss cmgd_arg2, 0x7
bcf cmgd_arg2, 0x2
btfsc cmgd_arg2, 0x4
goto label_076
btfss cmgd_arg2, 0x7
goto label_078
btfsc cmgd_arg2, 0x2
goto label_078
MOVFF (Common_RAM + 7), itoabuf1
btfsc cmgd_arg2, 0x1
goto label_078
MOVFF (Common_RAM + 7), itoabuf2
goto label_078
label_076:
movlw '0'
subwf itoabuf1, W
btfss STATUS, Z
goto label_078
MOVFF (Common_RAM + 7), itoabuf1
MOVLF ' ', itoabuf0
btfss cmgd_arg2, 0x3
goto label_077
bcf cmgd_arg2, 0x2
bsf cmgd_arg2, 0x1
btfss cmgd_arg2, 0x7
bcf cmgd_arg2, 0x1
label_077:
movlw '0'
subwf itoabuf2, W
btfss STATUS, Z
goto label_078
MOVFF (Common_RAM + 7), itoabuf2
MOVLF ' ', itoabuf1
btfss cmgd_arg2, 0x3
goto label_077
bcf cmgd_arg2, 0x1
btfss cmgd_arg2, 0x7
bcf cmgd_arg2, 0x0
label_078:
btfss cmgd_arg2, 0x2
goto label_080
SENDF itoabuf0
label_080:
btfss cmgd_arg2, 0x1
goto label_082
SENDF itoabuf1
label_082:
btfss cmgd_arg2, 0x0
goto label_084
SENDF itoabuf2
label_084:
SENDF itoabuf3
bcf PCLATH, 3
goto return_from_itoa
remove_all_sms:
ATCMDB d, function_ATCMGF, 10, 2
MOVLF 1, i
delete_next:
IFG i, 19, delete_done
call function_clear_buffer
TXSTR d, function_ATCMGD, 8
MOVFF i, cmgd_arg1
MOVLF 31, cmgd_arg2
goto itoa
return_from_itoa:
SEND '\r'
LDELAY 2, d
incf i, F
goto delete_next
delete_done:
ATCMDB d, function_ATCHFA, 10, 2
ATCMDB d, function_ATCMIC, 13, 2
ATCMDB d, function_ATCLIP, 10, 2
ATCMDB d, function_ATCSCLK, 11, 2
bcf PCLATH, 3
goto ready
ringing:
clrf quotes
clrf i
parse_call_info:
; +CLIP: "number", "type", "alphaId"
IFEQ quotes, 5, parse_call_done
movlw buffer
addwf i, W
movwf FSR
bcf STATUS, IRP
movf INDF, W
; подсчет количества кавычек
sublw '\"'
btfsc STATUS, Z
incf quotes, F
incf i, F
goto parse_call_info
; выход за пределы буфера не проверяется!
parse_call_done:
MOVFF i, namepos
clrf i
; memmove(buffer, buffer + namepos, BUFSZ + 1 - namepos)
movename:
; end of buffer?
movf namepos, W
; W = BUFSZ + 1 - namepos
sublw BUFSZ + 1
; W = i - (BUFSZ + 1 - namepos)
subwf i, W
btfsc STATUS, C
goto check_callee
; clipptr = &buffer[i]
movlw buffer
addwf i, W
movwf clipptr
; select Bank 2, 3 if clipptr > 0xff?
clrf highbanks
btfsc STATUS, C
incf highbanks, F
; FSR = &buffer[namepos + i]
movf namepos, W
addwf i, W
addlw buffer
movwf FSR
; itoabuf0 = buffer[namepos + i]
bcf STATUS, IRP
MOVFF INDF, itoabuf0
; FSR = clipptr = buffer + i
MOVFF clipptr, FSR
; 1 = Bank 2, 3 (100h - 1FFh)
bcf STATUS, IRP
btfsc highbanks, 0
bsf STATUS, IRP
; buffer[i] = buffer[i + namepos]
MOVFF itoabuf0, INDF
incf i, F
goto movename
check_callee:
clrf c
; проверка имени контакта на SIM карте (Ph1)
IFNE buffer, 'P', label_ATH
IFNE buffer + 1, 'h', label_ATH
IFNE buffer + 2, '1', label_ATH
; очистить счетчик времени соединения
clrf time_counter
; принять звонок
ATCMDB d, function_ATA, 4, 2
; активен звонок
bsf flags, FLAG_CALL
; чтение счетчика удачных соединений из EEPROM
MOVLF1 EEPROM_CALLS_COUNTER, EEADR
bcf EECON1, 7 ; Unimplemented
bsf EECON1, RD
movf EEDATA, W
Bank0
; увеличение на единицу
movwf calls_counter
incf calls_counter, F
; запись нового значения
MOVLF1 EEPROM_CALLS_COUNTER, EEADR
Bank0
movf calls_counter, W
Bank1
movwf EEDATA
bsf EECON1, WREN
Bank0
MOVFF INTCON, INTCON_TEMP
bcf INTCON, GIE
Bank1
; Flash programming unlock sequence
MOVLF 0x55, EECON2
MOVLF 0xaa, EECON2
bsf EECON1, WR
btfsc EECON1, WR
goto $-1
bcf EECON1, WREN
movf INTCON_TEMP, W
Bank0
iorwf INTCON, F
goto label_121
label_ATH:
TXSTR d, function_ATH, 4
label_121:
LDELAY 2, d
bcf PCLATH, 3
goto not_a_ring
sms_received:
; пришло СМС
clrf dtr_arg
call function_DTR
clrf commaptr
find_comma:
movlw buffer
addwf commaptr, W
movwf FSR
bcf STATUS, IRP
IFEQ INDF, ',', comma_found
incf commaptr, F
goto find_comma
comma_found:
; пропустить запятую
movlw 1
addwf commaptr, W
; номер слота СМС после запятой
movwf slotptr
movlw buffer
addwf slotptr, W
movwf FSR
bcf STATUS, IRP
MOVFF INDF, sms_slot
; Команды отсылаются с телефона хозяина, все “чужие” смс просто удаляются.
; В демонстрационной версии отсутствует код чтения СМС и выполнения команды.
; Надеюсь, в полной версии номер отправителя проверяется?
; ...
call function_clear_buffer
; удаляем СМС
TXSTR tmp4, function_ATCMGDC, 8
SENDF sms_slot
SEND '\r'
LDELAY 2, 102
MOVLF 1, dtr_arg
call function_DTR
bcf PCLATH, 3
goto not_a_sms
reset_vector:
clrf FSR
; очистить IRP, RP1, RP0 - Bank0
bcf STATUS, IRP
movlw ~((1 << IRP) | (1 << RP1) | (1 << RP0))
andwf STATUS, F
; INTOSC oscillator frequency: 1 = 4 MHz typical
BSF1 PCON, OSCF
; Bank1
; Baud Rate Generator Register (BRGH = 1):
MOVLF (F_OSC / BAUD / 16 - 1), SPBRG
; CSRC: Clock Source Select bit
; Synchronous mode: 1 = Master mode (Clock generated internally from BRG)
; TXEN: Transmit Enable bit
; BRGH: High Baud Rate Select bit
; TRMT: Transmit Shift Register STATUS bit: 1 = TSR empty
MOVLF (1 << CSRC) | (1 << TXEN) | (1 << BRGH) | (1 << TRMT), TXSTA
; SPEN: Serial Port Enable bit
; CREN: Continuous Receive Enable bit
MOVLF0 (1 << SPEN) | (1 << CREN), RCSTA
; Bank0
; Comparators Off
MOVLF (1 << CM2) | (1 << CM1) | (1 << CM0), CMCON
clrf bufptr
MOVLF STATE_RESET, state
bcf flags, FLAG_CALL
; T0CS: TMR0 Clock Source Select bit
; T0SE: TMR0 Source Edge Select bit
; PSA: Prescaler Assignment bit: 1 = Prescaler is assigned to the WDT
; PS2:PS0: Prescaler Rate Select bits
; TMR0 Rate 1:256 WDT Rate 1:128
Bank1
movf OPTION_REG, W
andlw ~((1<<T0CS)|(1<<T0SE)|(1<<PSA)|(1<<PS2)|(1<<PS1)|(1<<PS0))
movwf OPTION_REG
; см. 6.3.1 SWITCHING PRESCALER ASSIGNMENT на стр. 39 даташита
MOVLF (1<<PSA)|(1<<PS2)|(1<<PS1)|(1<<PS0), (Common_RAM + 7)
movlw 7
Bank0
clrf TMR0
MOVLF OPTION_REG, FSR
bcf STATUS, IRP
movf INDF, W
andlw ~((1 << PSA) | (1 << PS2) | (1 << PS1) | (1 << PS0))
iorlw (1 << PS2) | (1 << PS1) | (1 << PS0)
movwf INDF
clrwdt
movf INDF, W
andlw ~(1 << PSA)
btfsc (Common_RAM + 7), (1 << PS1) | (1 << PS0)
andlw ~((1 << PSA) | (1 << PS2) | (1 << PS1) | (1 << PS0))
iorwf (Common_RAM + 7), W
movwf INDF
MOVLF 0x80|(1<<T1CKPS1)|(1<<T1CKPS0)|(1<<NOT_T1SYNC)|(1<<TMR1ON), T1CON
MOVLF 0, (Common_RAM + 8)
movwf T2CON
; Timer2 Period Register
MOVLF1 0, PR2
; ?
; Comparators Off
MOVLF0 (1 << CM2) | (1 << CM1) | (1 << CM0), CMCON
; ?
Bank1
movf PORTA, W
clrwdt
MOVLF 2, k
short_delay:
decfsz k, F
goto short_delay
goto $+1
; ?
Bank0
movf CMCON, W
; Clear pending interrupts
; CMIF: Comparator Interrupt Flag bit: 0 = Comparator output has not changed
bcf PIR1, CMIF
Bank1
clrf CMCON
; разрешить прерывания от таймера и последовательного порта
bsf PIE1, TMR1IE
bsf PIE1, RCIE
; GIE: Global Interrupt Enable bit
; PEIE: Peripheral Interrupt Enable bit
movlw (1 << GIE) | (1 << PEIE)
Bank0
iorwf INTCON, F
; OSCF: INTOSC oscillator frequency: 1 = 4 MHz typical
BSF1 PCON, OSCF
bsf PORTA, LED
bsf PORTB, CHARGER
MOVLF EEPROM_CALLS_COUNTER, EEADR
bcf EECON1, 7 ; Unimplemented
bsf EECON1, RD
IFNE EEDATA, 0xff, check_calls_counter
; инициализация счетчика удачных соединений (демо-прошивка)
MOVLF EEPROM_CALLS_COUNTER, EEADR
clrf EEDATA
bsf EECON1, WREN
Bank0
MOVFF INTCON, INTCON_TEMP
bcf INTCON, GIE
Bank1
; Flash programming unlock sequence
MOVLF 0x55, EECON2
MOVLF 0xaa, EECON2
bsf EECON1, WR
btfsc EECON1, WR
goto $-1
bcf EECON1, WREN
movf INTCON_TEMP, W
Bank0
iorwf INTCON, F
Bank1
check_calls_counter:
; проверка счетчика звонков
MOVLF EEPROM_CALLS_COUNTER, EEADR
bcf EECON1, 7 ; Unimplemented
bsf EECON1, RD
; достигли максимального количества звонков для свободной версии?
IFNE EEDATA, MAX_CALLS, have_free_calls
; достигли - зацикливаемся
BLINKP 5
LDELAY 6, a
Bank1
goto check_calls_counter
have_free_calls:
; еще не достигли
bcf OPTION_REG, NOT_RBPU ; PORTB Pull-up Enable bit
Bank0
clrf dtr_arg
call function_DTR
label_138:
movf state, W
sublw STATE_RESET
btfss STATUS, Z
goto bad_result
goto start
check_result:
movf result, F
btfss STATUS, Z
goto good_result
clrf state
goto bad_result
good_result:
MOVLF STATE_READY, state
bad_result:
BSF1 OPTION_REG, NOT_RBPU ; PORTB Pull-up Enable bit
Bank0
goto check_charger
check_button:
BCF1 OPTION_REG, NOT_RBPU ; PORTB Pull-up Enable bit
Bank0
movf state, F
btfss STATUS, Z
goto label_147
; state == STATE_OFF
call function_button
movf button_state, F
btfss STATUS, Z
goto power_on
sleep
goto go_sleep2
power_on:
; Затем после того как вы отпустите он моргнет один раз – это означает
; что начался процесс включения модуля.
DTR0
BLINKP 1
goto power_on_continue
after_registration:
; Затем светодиод моргнет два раза – это означает что модуль
; настроен и зарегистрировался в сети GSM.
BLINK 2
goto remove_all_sms
ready:
; После того как светодиод моргнет три раза – устройство готово к работе.
; Устройство перейдет в режим сна и будет ждать входящего звонка.
BLINK 3
DTRP
MOVLF0 STATE_READY, state
go_sleep2:
goto go_sleep
label_147:
call function_button
movf (Common_RAM + 8), F
btfss STATUS, Z
goto power_off
call function_clear_buffer
LDELAY 2, a
; "RING"
IFNE buffer + 2, 'R', not_a_ring
IFEQ buffer + 3, 'I', ringing
not_a_ring:
; пришло SMS
; <CR><LF>+CMTI: <mem>,<n><CR><LF>
; value of mem is the storage location where the sms was stored.
; Usually its value is SM, which stands for SIM memory.
; the value of n is the sms slot on which the incoming message was stored
IFNE buffer + 2, '+', not_a_sms
IFNE buffer + 3, 'C', not_a_sms
IFNE buffer + 4, 'M', not_a_sms
IFEQ buffer + 5, 'T', sms_received
not_a_sms:
btfss flags, FLAG_CALL
goto check_calls_counter2
; проверка максимальной длительности соединения
IFL time_counter, MAX_TIME, check_calls_counter2
clrf dtr_arg
call function_DTR
bcf flags, FLAG_CALL
clrf time_counter
; положить трубку
ATCMDB a, function_ATH, 4, 2
MOVLF 1, dtr_arg
call function_DTR
check_calls_counter2:
; проверка счетчика удачных соединений (демо-прошивка)
MOVLF1 EEPROM_CALLS_COUNTER, EEADR
bcf EECON1, 7
bsf EECON1, RD
; достигли максимума?
IFNE EEDATA, MAX_CALLS, have_free_calls2
; лимит исчерпан
BLINKP 5
; сбрасываем звонок
TXSTR a, function_ATH, 4
LDELAY 6, a
; зацикливаемся
goto check_calls_counter2
Bank1
have_free_calls2:
Bank0
goto label_138
; unreachable code
goto go_sleep
power_off:
; Выключение происходит как и включение.
; Нажмите на кнопку и держите покуда не моргнет светодиод, как отпустите
; он моргнет 2 раза. Это означает, что девайс выключен.
BLINK 2
call function_SIM300D_power
clrf state
go_sleep:
sleep
end
Если найдете ошибку, напишите в комментариях.
Подпишитесь на блог, чтобы узнавать о новых статьях сразу.
© Copyright 2025 Badradio. All rights reserved.
Все права защищены. Копирование материалов сайта запрещено.
При цитировании ставить кликабельную ссылку на первоисточник.