📄 rf_remote.asm
字号:
; $Id: rf_remote.asm,v 1.5 2003/10/03 00:45:36 dwalters Exp $; Copyright (C) 2003 Dafydd Walters <dwalters@users.sourceforge.net>;; This program is free software; you can redistribute it and/or modify; it under the terms of the GNU General Public License as published by; the Free Software Foundation; either version 2 of the License, or; (at your option) any later version.;; This program is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program (COPYING.SOFTWARE); if not, write to the ; Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, ; MA 02111-1307 USA; ---------------------------------------------------------------------- title "rf_remote.asm - RF Remote Module" processor pic16f84 list r=dec ; set radix to decimal include "p16f84.inc"; ----------------------------------------------------------------------; Inputs (internal pull-ups enabled on port B):; RB0 - Pushbutton Keypad Matrix Input #1; RB1 - Pushbutton Keypad Matrix Input #2; RB2 - Pushbutton Keypad Matrix Input #3; RB3 - Pushbutton Keypad Matrix Input #4; RB4 - Pushbutton Keypad Matrix Input #5; RB5 - Pushbutton Keypad Matrix Input #6;; Outputs:; RA0 - Pushbutton Keypad Matrix Strobe Output Column #1; RA1 - Pushbutton Keypad Matrix Strobe Output Column #2; RA2 - Pushbutton Keypad Matrix Strobe Output Column #3; RA3 - Pushbutton Keypad Matrix Strobe Output Column #4; RA4 - Transmitter Power Control; RB6 - LED Control; RB7 - Transmitter Data Signal;; To conserve power, the Transmitter Power Control will be left in Hi-Z; (input) mode most of the time, and only turned on (output set to 0); when transmitting. The Transmitter Data Signal will also be left in Hi-Z; (input) mode while not transmitting.;; Data is sent using a slightly modified version of the protocol used by; Sony IR remotes. Normally, data words in each packet are 12-bits long,; 7 bits corresponding to a command code, and 5 bits to a device code.; However, we will be sending only 8 bit words, comprised of a 5 bit command; code, and a 3 bit Robot ID. The purpose of the Robot ID is to allow each; pair of RF Remote and Input Modules to be "tuned" or set to a particular; ID to prevent conflicts when there's more than one robot operating in the; same vicinity.;; One button on the keypad, labeled 'SET ROBOT CODE' is assigned to setting ; the Robot ID to be sent out in data packets by the transmitter. This button; must be held down for at least 2.5 seconds, and then one of the digit keys; 1 through 7 pressed to select the ID number. The Robot ID is then saved ; to EEPROM.;; The initial default value of the Robot ID code is 1.;; A single LED provides user feedback as follows:;; * On power up - 3 flashes.; * When a normal key is pressed - LED is illuminated during RF transmission.; * After 'SET ROBOT CODE' button has been held down 2.5 seconds - 2 flashes.; * After robot code has been selected (1 through 7) and set - 2 flashes.; * Error (e.g. key other than 1-7 while waiting for code) - 5 flashes.;; For more notes relating to this program, please see the README file.; ----------------------------------------------------------------------; Constants#define LED PORTB,6#define TX_POWER PORTA,4#define TX_DATA PORTB,7#define TX_POWER_DIR TRISA^0x080,4#define TX_DATA_DIR TRISB^0x080,7#define PORTA_DIR_BITS 0x01F#define ROBOT_CODE_EE_ADDR 0#define KEY_INPUT1 PORTB,0#define KEY_INPUT2 PORTB,1#define KEY_INPUT3 PORTB,2#define KEY_INPUT4 PORTB,3#define KEY_INPUT5 PORTB,4#define KEY_INPUT6 PORTB,5#define KEYCODE_0 9#define KEYCODE_1 0#define KEYCODE_2 1 #define KEYCODE_3 2 #define KEYCODE_4 3 #define KEYCODE_5 4 #define KEYCODE_6 5 #define KEYCODE_7 6 #define KEYCODE_8 7 #define KEYCODE_9 8 #define KEYCODE_ENTER 11#define KEYCODE_RIGHT 16#define KEYCODE_LEFT 17#define KEYCODE_UP 18#define KEYCODE_DOWN 19#define KEYCODE_ESCAPE 20 #define KEYCODE_NONE 0x0FF#define KEYCODE_PROGRAM_ID 0x0FE; ----------------------------------------------------------------------; Variable Declarations (GPR) starting at data address 0x020 cblock 0x020 HiCount DelayCounter StrobeBit ColumnPrefix KeyCode SendBuffer BitCount SendCount endc; ----------------------------------------------------------------------; Configuration bits: ;; - Code Protection off; - Crystal oscillator; - Power-Up Timer on; - Watchdog Timer off __CONFIG _CP_OFF & _XT_OSC & _PWRTE_ON & _WDT_OFF; ----------------------------------------------------------------------; Program entry point at device reset org 0 goto MainStart; ----------------------------------------------------------------------; Interrupt Handler entry point org 4 retfie; ----------------------------------------------------------------------; TablesKeyTable addwf PCL,f dt KEYCODE_ESCAPE dt KEYCODE_LEFT dt KEYCODE_1 dt KEYCODE_4 dt KEYCODE_7 dt KEYCODE_NONE dt KEYCODE_UP dt KEYCODE_DOWN dt KEYCODE_2 dt KEYCODE_5 dt KEYCODE_8 dt KEYCODE_0 dt KEYCODE_ENTER dt KEYCODE_RIGHT dt KEYCODE_3 dt KEYCODE_6 dt KEYCODE_9 dt KEYCODE_PROGRAM_ID dt KEYCODE_NONE dt KEYCODE_NONE dt KEYCODE_NONE dt KEYCODE_NONE dt KEYCODE_NONE dt KEYCODE_NONE IF ((HIGH($)) != (HIGH(KeyTable))) ERROR("Table crosses page boundary!") ENDIF; ----------------------------------------------------------------------; Main Program start pointMainStart call CheckEEPROMSettings ; Check if nonvolatile settings are valid call InitIO ; Initialize IO ports call FlashLED call FlashLED call FlashLED ; Flash LED 3 times at power onMainKeyLoop call WaitKey movlw KEYCODE_PROGRAM_ID subwf KeyCode,w btfss STATUS,Z goto NotProgram; PROGRAM ID button pressed movlw 250 movwf DelayCounterProgIDDelayLoop call Delay10ms decfsz DelayCounter,f goto ProgIDDelayLoop ; Wait 2.5 seconds call GetKeyNoWait movlw KEYCODE_PROGRAM_ID subwf KeyCode,w btfss STATUS,Z goto NotProgram; PROGRAM ID button still pressed call FlashLED call FlashLED ; Flash LED twice to indicate program mode call WaitKey movlw KEYCODE_1 subwf KeyCode,w btfss STATUS,Z goto Main3; Set robot RF remote ID to 1 movlw 1<<5 goto SetRobotCodeMain3 movlw KEYCODE_2 subwf KeyCode,w btfss STATUS,Z goto Main4; Set robot RF remote ID to 2 movlw 2<<5 goto SetRobotCodeMain4 movlw KEYCODE_3 subwf KeyCode,w btfss STATUS,Z goto Main5; Set robot RF remote ID to 3 movlw 3<<5 goto SetRobotCodeMain5 movlw KEYCODE_4 subwf KeyCode,w btfss STATUS,Z goto Main6; Set robot RF remote ID to 4 movlw 4<<5 goto SetRobotCodeMain6 movlw KEYCODE_5 subwf KeyCode,w btfss STATUS,Z goto Main7; Set robot RF remote ID to 5 movlw 5<<5 goto SetRobotCodeMain7 movlw KEYCODE_6 subwf KeyCode,w btfss STATUS,Z goto Main8; Set robot RF remote ID to 6 movlw 6<<5 goto SetRobotCodeMain8 movlw KEYCODE_7 subwf KeyCode,w btfss STATUS,Z goto Main9; Set robot RF remote ID to 7 movlw 7<<5 goto SetRobotCodeMain9 call FlashLED call FlashLED call FlashLED call FlashLED call FlashLED ; Flash LED 5 times to indicate error goto MainKeyLoopNotProgram movlw KEYCODE_NONE subwf KeyCode,w btfsc STATUS,Z goto MainKeyLoop ; Unassigned button was pressed - ignore bcf LED call TransmitKey bsf LED goto MainKeyLoopSetRobotCode call StoreRobotCodeInEEPROM call FlashLED call FlashLED ; Flash LED twice to indicate program code set goto MainKeyLoop; ----------------------------------------------------------------------; Subroutines; ----------------------------------------------------------------------; Global interrupts are assumed to be disabled before this subroutine is calledCheckEEPROMSettings call GetRobotCodeFromEEPROM andlw 0x01F btfss STATUS,Z ; Robot Code invalid? goto EEPROMCorrupt call GetRobotCodeFromEEPROM iorlw 0 btfss STATUS,Z goto CheckDoneEEPROMCorrupt movlw 0x020 ; Corresponds to Robot ID Code = 1 call StoreRobotCodeInEEPROMCheckDone return; ----------------------------------------------------------------------; Global interrupts are assumed to be disabled before this subroutine is calledStoreRobotCodeInEEPROM movwf EEDATA movlw ROBOT_CODE_EE_ADDR movwf EEADR bsf STATUS,RP0 bsf EECON1^0x080,WREN movlw 0x055 movwf EECON2^0x080 movlw 0x0AA movwf EECON2^0x080 bsf EECON1^0x080,WR btfsc EECON1^0x080,WR goto $-1 bcf EECON1^0x080,WREN bcf STATUS,RP0 return; ----------------------------------------------------------------------GetRobotCodeFromEEPROM movlw ROBOT_CODE_EE_ADDR movwf EEADR bsf STATUS,RP0 bsf EECON1^0x080,RD bcf STATUS,RP0 movf EEDATA,w return; ----------------------------------------------------------------------WaitKeyUp movlw 1 movwf StrobeBitKeyUpLoop movlw PORTA_DIR_BITS xorwf StrobeBit,w movwf PORTA bsf STATUS,RP0 movwf TRISA^0x80 bcf STATUS,RP0 movlw 0x03F andwf PORTB,w xorlw 0x03F btfss STATUS,Z goto WaitKeyUp rlf StrobeBit,f bcf StrobeBit,0 movlw 0x010 subwf StrobeBit,w btfss STATUS,Z goto KeyUpLoop return; ----------------------------------------------------------------------WaitKey call Delay10ms call WaitKeyUpStrobeAgain call Delay10ms movlw 1 movwf StrobeBit clrf ColumnPrefixKeyLoop movlw PORTA_DIR_BITS xorwf StrobeBit,w movwf PORTA bsf STATUS,RP0 movwf TRISA^0x80 bcf STATUS,RP0 btfsc KEY_INPUT1 ; Row 1 button pressed? goto Key2; Row 1 button pressed movlw 0 goto KeyDownKey2 btfsc KEY_INPUT2 ; Row 2 button pressed? goto Key3; Row 2 button pressed movlw 1 goto KeyDownKey3 btfsc KEY_INPUT3 ; Row 3 button pressed? goto Key4; Row 3 button pressed movlw 2 goto KeyDownKey4 btfsc KEY_INPUT4 ; Row 4 button pressed? goto Key5; Row 4 button pressed movlw 3 goto KeyDownKey5 btfsc KEY_INPUT5 ; Row 5 button pressed? goto Key6; Row 5 button pressed movlw 4 goto KeyDownKey6 btfsc KEY_INPUT6 ; Row 6 button pressed? goto Key7; Row 6 button pressed movlw 5 goto KeyDownKey7 movlw 6 addwf ColumnPrefix,f rlf StrobeBit,f bcf StrobeBit,0 movlw 0x010 subwf StrobeBit,w btfss STATUS,Z goto KeyLoop goto StrobeAgainKeyDown addwf ColumnPrefix,w call KeyTable movwf KeyCode return; ----------------------------------------------------------------------GetKeyNoWait movlw 1 movwf StrobeBit clrf ColumnPrefixNWKeyLoop movlw PORTA_DIR_BITS xorwf StrobeBit,w movwf PORTA bsf STATUS,RP0 movwf TRISA^0x80 bcf STATUS,RP0 btfsc KEY_INPUT1 ; Row 1 button pressed? goto NWKey2; Row 1 button pressed movlw 0 goto NWKeyDownNWKey2 btfsc KEY_INPUT2 ; Row 2 button pressed? goto NWKey3; Row 2 button pressed movlw 1 goto NWKeyDownNWKey3 btfsc KEY_INPUT3 ; Row 3 button pressed? goto NWKey4; Row 3 button pressed movlw 2 goto NWKeyDownNWKey4 btfsc KEY_INPUT4 ; Row 4 button pressed? goto NWKey5; Row 4 button pressed movlw 3 goto NWKeyDownNWKey5 btfsc KEY_INPUT5 ; Row 5 button pressed? goto NWKey6; Row 5 button pressed movlw 4 goto NWKeyDownNWKey6 btfsc KEY_INPUT6 ; Row 6 button pressed? goto NWKey7; Row 6 button pressed movlw 5 goto NWKeyDownNWKey7 movlw 6 addwf ColumnPrefix,f rlf StrobeBit,f bcf StrobeBit,0 movlw 0x010 subwf StrobeBit,w btfss STATUS,Z goto NWKeyLoop movlw KEYCODE_NONE movwf KeyCode returnNWKeyDown addwf ColumnPrefix,w call KeyTable movwf KeyCode return; ----------------------------------------------------------------------TransmitKey; Power up the transmitter bcf TX_POWER bsf TX_DATA ; Data HI initially bsf STATUS,RP0 bcf TX_POWER_DIR bcf TX_DATA_DIR bcf STATUS,RP0 call Delay10ms call Delay10ms movlw 10 movwf SendCount SendRepeatLoop call SendCode decfsz SendCount,f goto SendRepeatLoop movlw 10 movwf SendCount SilenceRepeatLoop call Delay10ms decfsz SendCount,f goto SilenceRepeatLoop; Power down the transmitter bsf STATUS,RP0 bsf TX_DATA_DIR bsf TX_POWER_DIR bcf STATUS,RP0 return; ----------------------------------------------------------------------SendCode; Send HI for 10ms bsf TX_DATA ; HI call Delay10ms bcf TX_DATA ; LO call Delay0_7ms call Delay0_7ms call Delay0_7ms ; Start bit - low for 2.1ms bsf TX_DATA ; HI call GetRobotCodeFromEEPROM iorwf KeyCode,w movwf SendBuffer movlw 8 movwf BitCountSendLoop call Delay0_7ms ; Sync gap - high for 0.7ms bcf TX_DATA ; LO rrf SendBuffer,f btfss STATUS,C goto SendZero; Send One call Delay0_7ms call Delay0_7ms goto SentBitSendZero call Delay0_7msSentBit bsf TX_DATA ; HI decfsz BitCount,f goto SendLoop call Delay10ms call Delay10ms ; Finish with 20ms delay return; ----------------------------------------------------------------------FlashLED bcf LED ; LED on movlw 25 movwf DelayCounterFlashLoop call Delay10ms decfsz DelayCounter,f goto FlashLoop ; Delay 250ms bsf LED ; LED off movlw 25 movwf DelayCounterFlashLoop2 call Delay10ms decfsz DelayCounter,f goto FlashLoop2 ; Delay 250ms return; ----------------------------------------------------------------------Delay10ms movlw HIGH((10000 / 5) + 256) movwf HiCount movlw LOW((10000 / 5) + 256)DelayLoop2 addlw 0x0FF btfsc STATUS, Z decfsz HiCount, f goto DelayLoop2 return; ----------------------------------------------------------------------Delay0_7ms movlw HIGH((700 / 5) + 256) movwf HiCount movlw LOW((700 / 5) + 256)DelayLoop3 addlw 0x0FF btfsc STATUS, Z decfsz HiCount, f goto DelayLoop3 return; ----------------------------------------------------------------------InitIO; Set B initial output data: 01000000 movlw 0x040 movwf PORTB bsf STATUS,RP0 bcf OPTION_REG^0x080,NOT_RBPU ; Enable Port B internal pull-up resistors.; Set port A and B initial data directions; Port A data directions: 00011111; Port B data directions: 10111111 movlw PORTA_DIR_BITS ; Set Port A data direction bits. movwf TRISA^0x080 movlw 0x0BF ; Set Port B data direction bits. movwf TRISB^0x080 bcf STATUS,RP0 return; ----------------------------------------------------------------------; End end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -