Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 06:23 27 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Create an i2c device from a PIC MCU

Author Message
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 06:06pm 09 Dec 2012
Copy link to clipboard 
Print this post

Hi all,

As seen in a couple of my posts, I have "grown" my own i2c slave devices.

I wonder, is anyone interested in following up or maybe someone has done it already differently using MCUs other than F88 and F819?

I/ve also done F88 and F819 i2c masters where number crunching speed was required in the master and a picaxe was too slow. (e.g. my 125KHz cattle ear tag reader)


David M.
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 12:30am 10 Dec 2012
Copy link to clipboard 
Print this post

  MOBI said  
I/ve also done F88 and F819 i2c masters where number crunching speed was required in the master and a picaxe was too slow. (e.g. my 125KHz cattle ear tag reader)


Hi MOBI,
I'm (slowly) working on a 125KHz animal tag reader project using the Mini Maximite as the controller and the reader is a slave module made by Priority One here in Melbourne (Model RFIDRW-E-232 - Atmel Mega 168PA based). Communication uses RS232.

I'd be interested in your cattle reader project as a more embedded option than the RFIDRW-E-232 module. Where can I find information on the project?

Greg
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 12:59am 10 Dec 2012
Copy link to clipboard 
Print this post

  paceman said   Where can I find information on the project?


I originally did it on the Ozelectronic forum but I'm happy to do it here again stage by stage if you like. I had always intended to Atmel it (currently runs picf88 as master/number cruncher) as well I would like to "blue tooth" it so no download cable is needed - currently dumps into a usb-serial cable.




The prototype is a bit rough - works on 6 to 8 half flat AA cells with a read range of about 180 to 200mm. Good enough for yard work - works in a pen of cattle if you fit unit to a bamboo pole or the like and scan over the animal's heads. Unit will not record duplicate tags, and will hold up to 600+ tags with group separators (blank tag) for multiple herds.





David M.
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 01:40am 10 Dec 2012
Copy link to clipboard 
Print this post

  MOBI said  
  paceman said   Where can I find information on the project?


I originally did it on the Ozelectronic forum but I'm happy to do it here again stage by stage if you like. Currently dumps into a usb-serial cable.

The prototype is a bit rough - works on 6 to 8 half flat AA cells with a read range of about 180 to 200mm. Good enough for yard work - works in a pen of cattle if you fit unit to a bamboo pole or the like and scan over the animal's heads. Unit will not record duplicate tags, and will hold up to 600+ tags with group separators (blank tag) for multiple herds.


My need is pretty simple - your cattle reader is doing a lot! I'm reading a passive FDX-B implanted cat tag with a very short read range - like 20mm or so, at the entrance to a cat door! The RFIDRW-E-232 module continuously scans for a tag and transmits the reading as ASCII text when it finds one. It's a nice module, 35X65mm and $40 or so, and can accept about a dozen plain text commands but it's overkill for what I need. The Mini-Maximite controller will be quite close to the reader (about 300mm or so) and has to have other power/control wire circuitry, so serial via wire is easiest for me.

I'll check out your Ozelectronics project. At this stage I'm pretty well set up with what I have and the programming is underway in MMBasic but it would be nice to be able to put a few components on the Main board rather than piggy-back the module.

Greg
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 10:59am 10 Dec 2012
Copy link to clipboard 
Print this post

[quote=greg]I'm reading a passive FDX-B implanted cat tag [/quote]

He Greg,

My rfid device is HDX not FDX. Mind you I am interested in any data you have on hardware/protocol etc to read and decode FDX.

In any case, this topic is starting to wander from 'home grown i2c'. Might have to start a topic for rfid in case there is anyone else interested.


David M.
 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1329
Posted: 05:30pm 10 Dec 2012
Copy link to clipboard 
Print this post

  MOBI said  
My rfid device is HDX not FDX. Mind you I am interested in any data you have on hardware/protocol etc to read and decode FDX.
In any case, this topic is starting to wander from 'home grown i2c'. Might have to start a topic for rfid in case there is anyone else interested.


Hi MOBI,

The module I'm using also does HDX and several others. Check out this site:
Priority One Design
The module I'm using is their Product 10/24: "FDX-B/HDX RFID Reader Writer with external antenna & RS232 port". There's a lot of protocol information in the datasheet they have available for it on that module's page.

Don't worry about a new thread from my point of view, I haven't heard of much interest from others on TheBackShed re RFID.

Greg
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 01:11am 22 Feb 2013
Copy link to clipboard 
Print this post

It has been a while since I posted here on this topic and besides, it was getting a bit OT.

For anyone interested, I have put a PIC16F88 firmware for an i2c slave device in the attached zip file. I think it is a bit big to include in a code block directly but if it is easier to discuss, then I will.

It is just a template, i.e. it has no practical function other than to be able to write to or read from up to 8 device registers.

The user must develop and insert the code in the "main_loop" section to provide the i2c function required. e.g. I took the digital output from a simple frequency counter and sent it to the master via i2c. This meant that I didn't have to do any data processing, just send to the i2c LCD on the same bus. Simple and easy.

It is pretty self explanatory but questions are welcome.

2013-02-22_110953_i2c_master_latest.zip
David M.
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 06:23pm 22 Feb 2013
Copy link to clipboard 
Print this post

I'll put the firmware in assembly code in three sections (posts). The first is the variable block and configuration word.


; programme to use pic 16f88 as i2c slave

#include p16f88.inc
list p=p16f88
;
;

uSec10 equ h'20' ;delay variables - always included just in case
ms1 equ h'21'
sec1 equ h'22'
ms10 equ h'23'


delay_byte equ h'24' ;not used in this example
databyte equ h'25' ;register for data to o/p or i/p
buff_size equ 8 ;number of internal addresses
offset equ h'26' ;internal address pointer
addr0 equ h'27' ;internal memory locations
addr1 equ h'28' ;more or less as required or ram permits
addr2 equ h'29'
addr3 equ h'2a' ;eight should be plenty
addr4 equ h'2b'
addr5 equ h'2c'
addr6 equ h'2d'
addr7 equ h'2e'


;//// put slave variables here




tempw equ h'70' ;interrupt "stack"
status_temp equ h'71' ;independent of banks
fsr_temp equ h'72'


address equ b'00001000' ;i2c device base address /// change to suit your needs

sda equ 1 ;i2c pins
scl equ 4




__config config1, _lvp_off & _boden_off & _mclr_off & _wdt_off & _intrc_io ;& _cp_all

David M.
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 06:50pm 22 Feb 2013
Copy link to clipboard 
Print this post

This bit of the firmware sets up the PIC i/o and register configuration to act as a i2c slave (interrupt driven)



org 0
goto start
org 4
goto interrupt
org 6

start:
clrf porta ;get rid of any leftover data
clrf portb
bcf status,irp
bcf status,rp1
bsf status,rp0 ;bank 1
clrf ansel
movlw b'11110000'
movwf trisa ;port a inputs and outputs
movlw b'11111111'
movwf trisb ;port b inputs (PB1,PB2,PB3, and PB4) MUST be inputs
bsf trisb,1 ;scl and sda as inputs for i2c
bsf trisb,4
movlw b'01100000' ;set int rc osc to 4MHz
movwf osccon
clrf sspstat ;clear ssp status register
bcf status,rp0 ;select bank 0
movf portb,w ;read address select (1 of 4) bits PB2 and PB3
andlw b'00001100' ;mask for address bits
movwf tempw ;save bits in temp register
bcf status,c ;clear carry bit
rrf tempw,w ;sh*t bits to pos 1 and 2
iorlw address ;combine with base address
bsf status,rp0 ;bank 1
movwf sspadd ;set slave address
bsf pie1,sspie ;enable interrupts
bcf status,rp0 ;bank 0
bcf pir1,sspif
movlw b'00110110' ;set up for slave read no interrupt
movwf sspcon ;enable interrupts as required
bsf intcon,peie
bsf sspcon,sspen
bsf intcon,gie ;switch on global interrupt enable

;=========================================================== ========
; end of pic setup routine
; beginning of main-loop initialisation
;=========================================================== ========

David M.
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 07:03pm 22 Feb 2013
Copy link to clipboard 
Print this post

I was going to split it into 3 sections but think 4 might be better.

This section includes delay routines which always come in handy and a generic i2c to main_loop hand shaking routine - this my change depending on slave device requirements.


;=========================================================== ========
;
; main slave function programme starts here
;
;=========================================================== ========
;=========================================================== ========
clrf addr0 ;depending on the slave type, you may need to clear other addr registers
clrf addr1
clrf offset ;set up indirect address for slave regs


main_loop:
movf addr1,f
btfss status,z ;i.e addr1 = 0
goto main_loop ;this is part of the i2c - main_loop hand shaking
clrf addr0 ;it might be different for a different slave device
clrf addr1

;//// main part of slave gets written here//////

goto main_loop

;=========================================================== ========
; start of main_loop routines etc.
;=========================================================== ========


;=========================================================== ========
;delay routines - set for 4MHz clock speed
;=========================================================== ========


delay10: ;10uSec per loop
movwf usec10 ;come in with uSx10 count in w reg
delay10a:
nop ;pad out to 10uSecs
nop
nop
nop
nop
nop
decfsz usec10,f
goto delay10a ;loop count 10uSec loops
return

delayms:
movwf ms1 ;come in with mSec count in W reg
delaymsa:
movlw 100 ;set up for 100 x 10uSec = 1 mSec
call delay10
decfsz ms1,f
goto delaymsa
return

delayms10: ;come in with mSx10 count in W reg
movwf ms10
delayms10a:
movlw 10
call delayms
decfsz ms10,f
goto delayms10a
return

delaysec:
movwf sec1 ;come in with seconds count in W reg
delayseca:
movlw 100 ;1000 mSec
call delayms10
decfsz sec1,f
goto delayseca
return

;=========================================================== =============
; End of Main Loop Routines etc.
; Beginning of interrupt routines

David M.
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 07:07pm 22 Feb 2013
Copy link to clipboard 
Print this post

This is the last and most important part as it includes the interrupt handling and i2c functions.

This firmware can be installed in a PIC as it is but will only allow you to treat the device as an 8 byte i2c RAM.

You need to put a main_loop function in to do anything worth while. I'll dig up a simple example and include somewhere after this post. If I get any interest or not.


;=========================================================== =============
; this is the data i/o section - i2c slave main routine
;=========================================================== =============
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++

interrupt:
movwf tempw ;save contents of w reg
swapf status,w
movwf status_temp ;save contents of status reg
movf fsr,w
movwf fsr_temp ;save fsr register
clrf status ;bank 0
bcf pir1,sspif

movf sspbuf,w ;clear data buffer
movwf databyte ;save in databyte
bsf status,rp0 ;bank 1
btfsc sspstat,d_a ;check if data or address
goto data_mode

;=========================================================== =============
; get and process mode byte
;=========================================================== =============

btfsc sspstat,r_w ;check if we need a mode byte
goto send
call inbyte ;read mode byte
movlw buff_size ;get number of internal addresses
subwf databyte,w ;check if valid address
btfsc status,c ;valid if carry is 0
clrf databyte ;if bad address, assume address 0
movf databyte,w ;good address, so put it in <offset>
movwf offset
goto int_end

data_mode:

btfss sspstat,r_w ;check if read or write
goto receive ;input data
send:
bcf status,rp0 ;bank 0
movlw addr0 ;physical location of address block
addwf offset,w ;point to required address
movwf fsr ;put address in indirect address mode
movf indf,w ;get data to be output
btfsc sspcon,ckp ;check if another byte
goto int_end ;no so finish
movwf sspbuf ;send data to master
nop ;delay needed to correct timing
nop
nop
nop
nop
bsf sspcon,ckp
bcf pir1,sspif
incf offset,f
movlw buff_size
subwf offset,w
btfsc status,z
clrf offset
goto int_end

receive:
bcf status,rp0 ;bank 0
movlw addr0 ;physical location of address block
addwf offset,w ;point to required address
movwf fsr ;put address in indirect address mode
movf databyte,w
movwf indf ;put data in appropriate address
incf offset,f ;automatic increment of address
movlw buff_size
subwf offset,w ;check if exceeded address limit
btfsc status,z
clrf offset ;back to start of addresses
goto int_end

;=========================================================== =============


int_end:

bcf status,rp0 ;bank 0
movf fsr_temp,w
movwf fsr
bcf pir1,sspif ;clear the interrupt flag
swapf status_temp,w ;restore temps
movwf status
swapf tempw,f
swapf tempw,w

retfie


inbyte:
bcf status,rp0 ;bank 0
btfss pir1,sspif ;wait for databyte in
goto inbyte
movf sspbuf,w ;read data buffer and put in databyte reg
movwf databyte
bcf pir1,sspif ;clear interrupt flag
return

end ;mandatory instruction
Edited by MOBI 2013-02-24
David M.
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024