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

📄 head_control_module.asm

📁 这个开发机器人项目源码
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;    $Id: head_control_module.asm,v 1.10 2003/10/15 06:03:35 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 "head_control_module.asm - OAP Head Control Module" processor pic16f819 list r=dec ; set radix to decimal include "p16f819.inc"; ----------------------------------------------------------------------; Analog Inputs;  AN0 - Eltec 442-3 infrared body-heat detector;; Digital Outputs:;  RA2 - Pan RC Servo PWM signal;  RB2 - Tilt RC Servo PWM signal;  ; I2C (initially inputs):;  RB4 - SCL;  RB1 - SDA;; Not Used:;  RA1;  RA3;  RA4;  RA5;  RA6;  RA7;  RB0;  RB3;  RB5;  RB6;  RB7; RC PWM:;; The PWM drive for RC servos has on on-time of between 500us and 2500us, ; repeated at 20ms intervals.;;; Timers:;; TMR1 is used in conjuncton with the CCP Compare mode for timing the 500us ; "always on" period at the start of the PWM cycle, and TMR1 overflow is used; for timing the end of the 20ms repeat period.;; TMR0 is used for timing the remaining on-time of the Pan RC Servo output.;; TMR2 is used for timing the remaining on-time of the Tilt RC Servo output.; I2C and SMBus:; ; The SMBus protocol commands are handled entirely in the interrupt handling; code. The Head Control Module appears as a slave device on the I2C bus.; Each time an I2C interrupt is detected, the interrupt handler code; determines which of the following 5 states the I2C interface is in:; ; - State1: Host wants to write (send) a byte to us, and has just sent us ;           our device address. In this state, we must read (and discard) the;           address from the receive buffer. The device does not need to take;           any further action in response to this state. We should be seeing;           State2 next.;; - State2: Host has just finished sending a byte to us. We must read the data;           byte from the receive buffer, and act on it (what we do at this;           point depends on whether we were expecting a command byte from the;           host, or whether we had already recevied that, and are now waiting;           for data from the host).;; - State3: Host wants to read a byte from us, and has just sent us our device;           address. We must first read the address, and then write a byte to;           the buffer (this would typically be a response to host's request;           for data).;; - State4: Host has just read a byte from us, and is now expecting us to send;           another byte. This state is for transfers of more than one byte;           This state should never occur in this application. However, if we;           ever find ourselves in this state, we're obliged to send dummy ;           data to the host to satisfy protocol requirements.;; - State5: Host has just read a byte from us, and does NOT expect us to send;           any more. The device does not need to do anything in response to;           this state.;; The interrupt handler also keeps track of which of three states the SMBus; transfers are in as follows:;; - State 0: Waiting for a command byte from the host.;; - State 1: Transferring a data byte (either reading or writing) to/from host.;; - State 2: Transferring a second data byte (either reading or writing) ;            to/from host.;; We can sometimes set the SMBus state according to which state the I2C ; interface is in.  For example, in response to I2C State1 or State5, we know; that the next byte we receive from the host should be a SMBus command, so we; set the SMBus state to 0.;; See the README document for more information on the SMBus commands that; are implemented by this device.; ; ----------------------------------------------------------------------; Constants#define SERVO_CONTROL_PERIOD_MICROSECOND (20000-11)     ; Adjusted for latency#define SERVO_ALWAYS_ON_TIME_MICROSECOND (500-35)       ; Adjusted for latency#define MAX_CHANGE_PER_PERIOD_EE_ADDR 0#define IR_SENSOR_NEUTRAL_EE_ADDR 1#define IR_TRIGGER_THRESHOLD_EE_ADDR 2#define IR_TRIGGERED_EVENT_MODE_EE_ADDR 3#define CHECK_VALUE_EE_ADDR 4#define I2C_ADDRESS 88#define PAN_SERVO PORTA,2#define TILT_SERVO PORTB,2; SMBus commands from Host:#define READ_PAN_SERVO_SETPOINT_COMMAND 1               ; SMBus Read Byte#define READ_PAN_SERVO_ACTUAL_COMMAND 2                 ; SMBus Read Word#define READ_TILT_SERVO_SETPOINT_COMMAND 3              ; SMBus Read Byte#define READ_TILT_SERVO_ACTUAL_COMMAND 4                ; SMBus Read Word#define READ_MAX_CHANGE_PER_PERIOD 5                    ; SMBus Read Byte#define READ_RAW_ANALOG_IR_SENSOR 6                     ; SMBus Read Byte#define READ_IR_SENSOR_NEUTRAL_VALUE 7                  ; SMBus Read Byte#define READ_IR_SENSOR_TRIGGER_THRESHOLD 8              ; SMBus Read Byte#define READ_IR_EVENT_PAN_ACTUAL 9                      ; SMBus Read Byte#define READ_IR_EVENT_STATUS 10                         ; SMBus Read Byte#define READ_IR_EVENT_MODE 11                           ; SMBus Read Byte#define READ_IR_EVENT_ANALOG 12                         ; SMBus Read Byte#define READ_IR_EVENT_TIMER_COUNT 13                    ; SMBus Read Byte#define READ_CURRENT_TIMER_COUNT_COMMAND 14             ; SMBus Read Byte#define READ_PWM_OUTPUT_STATUS_COMMAND 15               ; SMBus Read Byte#define WRITE_PAN_SERVO_SETPOINT_COMMAND 100            ; SMBus Write Byte#define WRITE_TILT_SETPOINT_COMMAND 101                 ; SMBus Write Byte#define WRITE_MAX_CHANGE_PER_PERIOD 102                 ; SMBus Write Byte#define WRITE_IR_SENSOR_NEUTRAL_VALUE 103               ; SMBus Write Byte#define WRITE_IR_TRIGGER_THRESHOLD 104                  ; SMBus Write Byte#define RESET_IR_TRIGGERED_EVENT_COMMAND 105            ; SMBus Send Byte#define WRITE_IR_EVENT_MODE_COMMAND 106                 ; SMBus Write Byte#define RESET_TIMER_COUNT_COMMAND 107                   ; SMBus Send Byte#define ENABLE_PWM_OUTPUT_COMMAND 108                   ; SMBus Send Byte#define DISABLE_PWM_OUTPUT_COMMAND 109                  ; SMBus Send Byte; ----------------------------------------------------------------------; Variable Declarations (GPR) starting at data address 0x020 cblock 0x020MaxChangePerPeriod              ; Maximum PWM drive change per 20ms periodIRSensorNeutral                 ; Expected nominal ADC value of IR sensorIRSensorTriggerThreshold        ; Trigger deviation from IRSensorNeutralIRTriggeredEventMode            ; The capture mode for IR eventsRawAnalogIR                     ; ADC bitcount read from IR sensorTimer                           ; Free running 8-bit up timer counter (20ms)IRTriggeredEventStatus          ; 0 = no IR event stored, 1 = IR event storedIRTriggeredEventLocked          ; 0 = not locked, 1 = lockedIRTriggeredEventADC             ; Analog bitcount of stored IR eventIRTriggeredEventTimer           ; Timer count of stored IR eventIRTriggeredEventPan             ; Pan actual driven position of stored IR eventIRTriggeredEventMaxThreshold    ; Maximum threshold of stored eventIRDeviationFromNeutral          ; temp value of ir-threshold diffPanSetpoint                     ; Current Pan servo setpoint (target position)TiltSetpoint                    ; Current Tilt servo setpoint (target position)PanActual                       ; Current Pan servo actual driven positionTiltActual                      ; Current Tilt servo actual driven positionSMBusCommand                    ; Most recent SMBus command from hostSMBusState                      ; Current SMBus state (see comments above)SecondDataByte                  ; Value of 2nd data byte for Read Word (SMBus)I2CRxByte                       ; Most recent I2C byte received from hostSspStatSaved                    ; Temporary variable to hold SSPSTAT registerSavedW                          ; Variable to hold saved register during ISRSavedStatus                     ; Variable to hold saved register during ISRSavedFSR                        ; Variable to hold saved register during ISRSavedPCLATH                     ; Variable to hold saved register during ISR endc; ----------------------------------------------------------------------; Configuration bits: ;; - Flash Code Protection off; - CCP1 on RB3; - In-circuit Debugger disabled; - Flash program memory write enable off; - EE Code Protection off; - Low Voltage Programming Enable off, RB3 is I/O; - Brown-out Reset Enable on; - RA5/MCLR pin function is digital I/O; - Power-Up Timer on; - Watchdog Timer off; - Oscillator: INTRC, port I/O function of RA6 and RA7 __CONFIG _CP_OFF & _CCP1_RB3 & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO; ----------------------------------------------------------------------; Program entry point at device reset org 0 goto MainStart; ----------------------------------------------------------------------; Interrupt Handler entry point org 4 btfss INTCON,TMR0IF goto NotTimer0 btfss INTCON,TMR0IE goto NotTimer0; Timer 0 bcf INTCON,TMR0IE              ; Disable Timer 0 interrupt bcf PAN_SERVO                  ; Pan servo signal LOW goto FinishISRNotTimer0 btfss PIR1,TMR2IF              ; Timer 2 ? goto NotTimer2 bsf STATUS,RP0 btfss PIE1^0x080,TMR2IE goto NotTimer2; Timer 2 bcf PIE1^0x080,TMR2IE          ; Disable Timer 2 interrupt bcf STATUS,RP0 bcf TILT_SERVO                 ; Turn Tilt servo signal LOW goto FinishISRNotTimer2 bcf STATUS,RP0 btfss PIR1,TMR1IF goto NotTimer1 bsf STATUS,RP0 btfss PIE1^0x080,TMR1IE goto NotTimer1; Timer 1 bcf STATUS,RP0 bcf PIR1,TMR1IF                ; TMR1 interrupt call StartPWMCycle call UpdateActuals call SenseIR incf Timer,f                   ; Increment free running timer goto FinishISRNotTimer1 bcf STATUS,RP0 btfss PIR1,CCP1IF              ; Compare interrupt? goto NotCCP bsf STATUS,RP0 btfss PIE1^0x080,CCP1IE goto NotCCP; CCP interrupt bcf PIE1^0x080,CCP1IE          ; Disable CCP interrupt bcf STATUS,RP0 movf PanActual,w btfsc STATUS,Z movlw 1                        ; 1 is lower limit sublw 0 movwf TMR0 bcf INTCON,TMR0IF              ; Clear interrupt flag movf TiltActual,w btfsc STATUS,Z movlw 1                        ; 1 is lower limit bsf STATUS,RP0 movwf PR2^0x080 bsf PIE1^0x080,TMR2IE          ; Enable TMR2 interrupt bcf STATUS,RP0 clrf TMR2 bcf PIR1,TMR2IF                ; Make sure flag is clear bsf INTCON,TMR0IE              ; Enable TMR0 interrupt goto FinishISRNotCCP bcf STATUS,RP0 btfss PIR1,SSPIF goto FinishISR                 ; Not I2C; I2C bcf PIR1,SSPIF                 ; Clear interrupt flag btfsc SSPCON,SSPOV             ; Check overflow bit bcf SSPCON,SSPOV               ; Make sure overflow bit is clear bsf STATUS,RP0                 ; Select Page 1 movf SSPSTAT^0x080,w           ; Get I2C status (SSPSTAT register) bcf STATUS,RP0                 ; Back to page 0 andlw b'00101101'              ; Mask for interesting bits in SSPSTAT movwf SspStatSaved             ; Save the result in a variable movlw b'00001001'               subwf SspStatSaved,w btfss STATUS,Z                 ; Is it I2C State 1 (Write, last byte address)? goto I2CNotState1; Write, last byte is address (I2C State 1) movf SSPBUF,w                  ; Read receive buffer byte (clear BF) movwf I2CRxByte                ; Save received byte clrf SMBusState                ; Expecting SMBus command code next goto FinishISR                 ; Nothing more to do in this stateI2CNotState1 movlw b'00101001'              ; Is it I2C State 2 (Write, last byte data)? subwf SspStatSaved,w btfss STATUS,Z goto I2CNotState2              ; No; Write, last byte data (I2C State 2) movf SSPBUF,w                  ; Read receive buffer byte (clear BF) movwf I2CRxByte                ; Save received byte movlw HIGH($+4) movwf PCLATH movf SMBusState,w addwf PCL,f                    ; Jump table for SMBus state goto I2CState2SMBusState0 goto I2CState2SMBusState1 goto I2CState2SMBusState2 IF ((HIGH($)) != (HIGH($-3)))     ERROR("Table crosses page boundary!") ENDIFI2CState2SMBusState0            ; SMBus State 0 (expecting command byte next) movf I2CRxByte,w movwf SMBusCommand             ; Save SMBus command code sublw RESET_IR_TRIGGERED_EVENT_COMMAND btfss STATUS,Z goto NotResetEvent; Reset IR event call ResetEvent clrf SMBusState goto FinishISRNotResetEvent movf SMBusCommand,w sublw RESET_TIMER_COUNT_COMMAND btfss STATUS,Z goto NotZeroTimer; Zero Timer clrf Timer  clrf SMBusState goto FinishISRNotZeroTimer movf SMBusCommand,w sublw ENABLE_PWM_OUTPUT_COMMAND btfss STATUS,Z goto NotEnablePWM; Enable PWM Output bsf STATUS,RP0 bsf PIE1^0x080,TMR1IE          ; Enable timer 1 overflow interrupt bcf STATUS,RP0 bcf PIR1,TMR1IF clrf SMBusState goto FinishISRNotEnablePWM movf SMBusCommand,w sublw DISABLE_PWM_OUTPUT_COMMAND btfss STATUS,Z goto NotDisablePWM; Disable PWM Output bsf STATUS,RP0 bcf PIE1^0x080,TMR1IE          ; Disable timer 1 overflow interrupt bcf STATUS,RP0 clrf SMBusState goto FinishISRNotDisablePWM   movlw 1 movwf SMBusState               ; Next SMBus state = 1 goto FinishISRI2CState2SMBusState1 movf SMBusCommand,w sublw WRITE_PAN_SERVO_SETPOINT_COMMAND btfss STATUS,Z                 ; Is this command 100? goto NotWritePanSetpoint       ; No; Write Pan setpoint movf I2CRxByte,w movwf PanSetpoint clrf SMBusState                ; Expecting SMBus command code byte next goto FinishISRNotWritePanSetpoint movf SMBusCommand,w sublw WRITE_TILT_SETPOINT_COMMAND btfss STATUS,Z goto NotWriteTiltSetpoint; Write Tilt setpoint movf I2CRxByte,w movwf TiltSetpoint clrf SMBusState                ; Expecting SMBus command code byte next goto FinishISRNotWriteTiltSetpoint movf SMBusCommand,w sublw WRITE_MAX_CHANGE_PER_PERIOD btfss STATUS,Z goto NotWriteMaxChangePerPeriod; Write Max Change per Period setting movf I2CRxByte,w movwf MaxChangePerPeriod call WriteMaxChangePerPeriodEeprom clrf SMBusState                ; Expecting SMBus command code byte next goto FinishISRNotWriteMaxChangePerPeriod movf SMBusCommand,w sublw WRITE_IR_SENSOR_NEUTRAL_VALUE btfss STATUS,Z goto NotWriteIRSensorNeutral; Write IR Sensor Neutral setting movf I2CRxByte,w movwf IRSensorNeutral call WriteIRSensorNeutralEeprom clrf SMBusState                ; Expecting SMBus command code byte next goto FinishISRNotWriteIRSensorNeutral movf SMBusCommand,w sublw WRITE_IR_TRIGGER_THRESHOLD btfss STATUS,Z goto NotWriteIRSensorTriggerThreshold; Write IR Sensor Trigger Threshold setting movf I2CRxByte,w movwf IRSensorTriggerThreshold call WriteIRTriggerThresholdEeprom clrf SMBusState                ; Expecting SMBus command code byte next goto FinishISRNotWriteIRSensorTriggerThreshold movf SMBusCommand,w sublw WRITE_IR_EVENT_MODE_COMMAND btfss STATUS,Z goto NotWriteIRTriggeredEventMode; Write IR Triggered Event Mode setting movf I2CRxByte,w movwf IRTriggeredEventMode call WriteIRTriggeredEventModeEeprom clrf SMBusState                ; Expecting SMBus command code byte next goto FinishISRNotWriteIRTriggeredEventMode goto FinishISRI2CState2SMBusState2            ; Second data byte goto FinishISR                 ; Shouldn't be hereI2CNotState2 movlw b'00001100'              ; I2C state 3 (Read, last byte address)? subwf SspStatSaved,w btfss STATUS,Z goto I2CNotState3              ; No; Read, last byte address (I2C State 3) movlw HIGH($+4) movwf PCLATH movf SMBusState,w

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -