This slave relies on the work of many others, but I have added some bug fixes and extra features. For example, you can write
0xAA,0X55,0x00,**your new address here**,0x00
and you can change the address of the slave.
Like my other stuff, it ONLY works on 18F chips. It should be "plug and play" in virtually any 18F chip.
ASM ifndef __18F2321 error "18F2321 not selected" endif ENDASM ASM movlw 0x62 ; %0110 0010 = 4 Mhz, internal osc block movwf OSCCON movlw 0x80 ; %1000 0000 = PLL disabled movwf OSCTUNE ENDASM DATA @0,$38 ; Default I2C address if not determined in HW DEFINE OSC 4 Define USE_LFSR 1 ;---------------- Alias the bits ------------------------------------ SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag SSPIE VAR PIE1.3 ' Int Enable SSPUA VAR SSPSTAT.1 SSPS VAR SSPSTAT.3 SSPP VAR SSPSTAT.4 SSPSMP VAR SSPSTAT.7 BF VAR SSPSTAT.0 ' SSP (I2C) Buffer Full R_W VAR SSPSTAT.2 ' SSP (I2C) Read/Write D_A VAR SSPSTAT.5 ' SSP (I2C) Data/Address CKP VAR SSPCON1.4 ' SSP (I2C) SCK Release Control SSPEN VAR SSPCON1.5 ' SSP (I2C) Enable SSPOV VAR SSPCON1.6 ' SSP (I2C) Receive Overflow Indicator WCOL VAR SSPCON1.7 ' SSP (I2C) Write Collision Detect MasterClock VAR WORD BANKA SYSTEM '------------------- Buffer defintion -------------------- RxBufferLEN con 10 RxBuffer var BYTE[Rxbufferlen + 1] TxBufferLEN CON 10 TXBuffer VAR BYTE[TxBufferLEN + 1] GeneralCall VAR BIT RXBufferOverFlow VAR BIT TxBufferUnderFlow VAR BIT HWAddress VAR BIT RXBufferPointer VAR Byte TXBufferPointer VAR Byte address VAR BYTE x VAR BYTE dummy var byte I2CAddress VAR BYTE WCOLCounter VAR BYTE I2CDeviceAddress VAR BYTE Holdoff VAR WORD ; retry timer HWAddress = 0 ; Get address from EEPROM, not pins TestArray VAR BYTE [200] IF !HWAddress THEN ;----------- Get our Address from EEPROM -------------- READ 0,I2CAddress ;----------------------------------------------------- ELSE ;----------------OR Get our address from PORT B0..2----------- I2CDeviceAddress = PORTB & %00000111 I2CMajorAddress CON $3 ; upper 4 bits I2CAddress = (I2CMajorAddress <<4) | I2CDeviceAddress <<1 ; bit 0 is R/W ;--------------------------------------------------------------- Endif SSPADD = I2Caddress ' Move our address into the proper reg SSPCON2.0 = 1 ; Allow clock stretching SSPCON2.1 = 0 ; Set to 1 to enable masking of address 1 ; 0 is R/W bit SSPCON2.2 = 0 ; Set to 1 to enable masking of address bit 2 SSPCON2.3 = 0 ; Set to 1 to enable masking of address bit 3 SSPCON2.4 = 0 ; Set to 1 to enable masking of address bit 4 SSPCON2.5 = 0 ; Set to 1 to enable masking of address bit 5 SSPCON2.6 = 0 ; Not used in slave SSPCON2.7 = 1 ; General Call enabled SSPSTAT = 0 SSPEN = 1 SSPIE = 1 SSPIF = 0 SSPCON1 = $36 ' Set to I2C slave with 7-bit address ;--------------------------------------------------------------- TRISA = %11111111 TRISB = %11111111 TRISC = %11111111 ' -------------- Turn on Ints ------------------------ INTCON.7 = 1 ; global ints INTCON.6 = 1 ; peripheral ints IPR1.3 = 1 ; high priority ;------------------ Clear parameters -------------- RXBufferPointer = 0 TxBufferPointer = 0 GeneralCall = 0 RxBufferOverFlow = 0 TXBufferUnderFlow = 0 WCOLCounter = 0 ;----------------Timer Setup----------------------------------- T0CON = %10000011 ; /16 prescaler ;-------- ------------------------------------------- WDTCON = 1 ; Turn on the WDT ;-------------------------------------------------------------- INCLUDE "DT_INTS-18.bas" ' Thanks Darrel! INCLUDE "ReEnterPBP-18.bas" ' ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler SSP_INT, _I2C_Int, PBP, yes INT_Handler TMR0_INT, MainTimer, ASM, yes endm INT_CREATE ; Creates the interrupt processor endasm ''----------------- Initialization Done! ----------------------------- Goto OverInt ; jump over ISR, don't execute it. ;----------------------- Timer INt ------------------------------------ ASM MainTimer movlw 0x00 ; 10 mSec movwf TMR0H movlw 0x63 movwf TMR0L infsnz MasterClock incf MasterClock + 1 ; This is a good place to pick up pin changes INT_ENABLE TMR0_INT INT_RETURN ENDASM ;--------------------------------------------------------------------- '------------------------- I2C subroutine -------------------------------- I2C_Int: ; We don't get here uless someone has matched our address register. If R_W = 0 then 'This is a WRITE by the master to us IF BF = 0 Then goto i2CEXIT ; Nothing for us! if D_A = 0 then 'We have an address address = SSPBUF 'Need to READ Address from buffer to clear it. IF Address = 0 THEN GeneralCall = 1 ; Set flag if we got a general call address ELSE GeneralCall = 0 ENDIF else IF WCOL OR SSPOV THEN I2CExit IF RXBufferPointer < RxBufferLen - 1 THEN RXBuffer [RxBufferPointer] = SSPBuf ; RxBufferPointer = RXBufferPointer + 1 ELSE Dummy = SSPBuf ; Grab the data but don't overwrite old RXBufferOverFlow = 1 ENDIF ENDIF else ' R_W = 1 Master wants to read FROM us IF !D_A Then TxBufferPointer = 0 ' Mark as first read RXBufferPointer = 0 EndIF IF CKP THEN I2CExit dummy = SSPBUF ;NECESSARY! SENDI2C: WCOL = 0 SSPBUF = TXBuffer[TXBufferPointer] ' Get data from array IF WCOL THEN WCOLCounter = WCOLCounter + 1 ; Don't hang the bus with infinite WRITES! IF WColCounter >= 7 Then goto I2CExit ; 7 RANDOM Holdoff Pauseus Holdoff >> 3 ; wait 0-8 msec Goto SendI2C ; Retry ELSE WColCounter = 0 ENDIF TXBufferPointer = TXBufferPointer + 1 If TXBufferPointer = TXBufferLen THEN TXBufferUnderflow = 1 TXBufferPointer = TXBufferLen - 1 ; Repeat last if req made again, but set flag now ENDIF ENDIF I2CEXIT: SSPOV = 0 BF = 0 sspif = 0 CKP = 1 @ INT_ENABLE SSP_INT ; probably don't need this, but I like to be certain it gets restarted @ INT_RETURN ' -------------------------end I2C subroutine -------------------------------- '--------------------[End ISRs]--------------------------------------- OverInt: @ INT_ENABLE SSP_INT @ INT_ENABLE TMR0_INT '--------------------[ main program loop]--------------------------------------- Main: IF RXBuffer[0] = $AA THEN IF RXBuffer[1] = $55 and RXBuffer[2] = 0 And RxBuffer[4] = 0 THEN Dummy = RXBuffer[3] WRITE 0,Dummy ; Write a new address Pause 10 @ RESET ; and pick up the new address ENDIF ENDIF ;------------------- Load the input buffer to the output buffer for test ----------- For X = 0 to TXBufferLen - 1 TxBuffer[X] = RXBuffer[X] next x ;---------------------------------------------------------------------- goto main end ASM ORG 0x0FF0 ; Keep track of pgm size in case we want to use it on a smaller chip NOP ENDASM
Re: Voltage regulation circuit 12V to 5V in 5A range
-
amgen Today, 02:08not trying to 'rain on your parade'..... it is possible that isn't where your noise is coming from...... if you haven't already, put a 10 or 100 microfarad electrolytical and a couple of .1 or .01...