Hi guys,
I'm still on my i2c problem... I've localized the problem: it's in the
software master. For testing purpose, I've setup a 2 PIC communnication (2
16f88), with an incredible added value: master reads serial and sends a char
through i2c, slave answers the same char + 1, master writes the result to
serial. So you enter "a", you get a "b"
The jallib migrated slave works perfectly (I thought that'd be the tricky
part, but...). I've tested it against my old not-migrated master (using
original Wouter's lib), everything works nice.
When I try to use my migrated master, it just doesn't work. The slave does not
produce any interrupts, as though the address were wrong. I'm probably doing
a nasty mistake, but I can't see which... maybe you'll see the problem.
Attached are my jal files for both master and slave. As you see, address
declared in slave (0x5C) is the same as in the master (as expected, IIUC).
Master uses i2c_level1 with tx/rx buffer.
Another question is: did i2c_software and i2c_level1 been tested with a PIC,
and not only a eeprom ? Joep, I know you did something similar, but it's not
converted yet to jallib. Maybe you have further information now :) ...
Thanks,
Seb
PS: once working, I'll put these 2 files as test files, and write a post to
jalliblog
:wq!
--
Sébastien LELONG
http://www.sirloon.net
http://sirbot.org
Le Thursday 18 December 2008 08:12:59 Joep Suijs, vous avez écrit :
> Have you tried my slave?
>
> Address is 0x70.
> i2c_receive_byteaddres(0x70, 0x80, 2) should work and give 0x3C 0x01
> as an answer (did not verify it though).
>
> Joep
>
> 2008/12/18, Sebastien LELONG <[email protected]>:
> > Hi guys,
> >
> > Thanks for your help on this. I tried the following:
> >
> > * enable RCIE interrupt (on receive usart): it works, so it means
> > interrupt (global) are enabled
> > * enable i2c interrupt on start/stop works too (but I don't use them
> > usually, only for debug purpose)
> > * switching back to i2c without start/stop interrupt, it doesn't work
> > (this is case at the beginning)
> >
> > In the last case, interrupts are triggered when there's an address match.
> > So this may mean there's a address problem. As they say: "i2c problems
> > are usually a matter of addressing". I've set "0x5C" for both slave and
> > master.
> >
> > I can't dig more right now, so to be continued.
> >
> > Seb
> > --
> > Sébastien LELONG
> > http://www.sirloon.net
> > http://sirbot.org
>
>
--
Sébastien LELONG
http://www.sirloon.net
http://sirbot.org
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"jallib" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/jallib?hl=en
-~----------~----~----~----~------~----~------~--~---
include 16f88
enable_digital_io()
-- We'll use internal oscillator. It work @ 8MHz
pragma target clock 8_000_000
pragma target OSC INTOSC_NOCLKOUT
-- no watchdog, please
pragma target WDT disabled
-- we want to use USART/RS232, not SPI
const usart_hw_serial = true -- true = RS232, false = SPI
-- setup speed. Standard values are: 57_600, 19_200, 9_600, 2_400, ...
const serial_hw_baudrate = 19_200
include serial_hardware
serial_hw_init()
serial_hw_write("!")
include delay
var volatile bit i2c_scl is pin_b4
var volatile bit i2c_scl_direction is pin_b4_direction
-- b3 is pin-compatible with 16f648a board file, b1 is on hardware pins
;var volatile bit i2c_sda is pin_b3
;var volatile bit i2c_sda_direction is pin_b3_direction
var volatile bit i2c_sda is pin_b1
var volatile bit i2c_sda_direction is pin_b1_direction
-- i2c setup
const word _i2c_bus_speed = 1 ; * 100kHz
const bit _i2c_level = true ; i2c levels (not SMB)
include i2c_software
var byte i2c_tx_buffer[10]
var byte i2c_rx_buffer[10]
include i2c_level1
include print
var byte pc_char
var byte ic_char
var bit r
-- Slave address, 7bits
-- the LSb bit corresponding to read/write operation
-- is *not* included in this address. It'll be put
-- by i2c_put_{read,write}_address procedure
var byte icaddress = 0x5C -- slave address
serial_hw_write("M") -- as Master
forever loop
if serial_hw_read(pc_char)
then
serial_hw_write(pc_char) -- echo
-- transmit to slave
i2c_tx_buffer[0] = pc_char
r = i2c_send_receive(icaddress, 1, 1)
print_bit_truefalse(serial_hw_data, r)
ic_char = i2c_rx_buffer[0]
serial_hw_write(ic_char)
;;i2c_start()
;;i2c_transmit_byte(icaddress & 0xFE) -- i2c address for write
(for memory address, within eeprom)
;;i2c_transmit_byte(pc_char)
;;i2c_transmit_byte(icaddress | 0x01) -- i2c address for read
(of memory from eeprom)
;;ic_char = i2c_receive_byte(true)
;;i2c_stop()
;;serial_hw_write(ic_char)
end if
end loop
include 16f88
enable_digital_io()
-- We'll use internal oscillator. It work @ 8MHz
pragma target clock 8_000_000
pragma target OSC INTOSC_NOCLKOUT
-- no watchdog, please
pragma target WDT disabled
-- we want to use USART/RS232, not SPI
const usart_hw_serial = true -- true = RS232, false = SPI
-- setup speed. Standard values are: 57_600, 19_200, 9_600, 2_400, ...
const serial_hw_baudrate = 19_200
include serial_hardware
serial_hw_init()
serial_hw_write("!")
include delay
-- AppNote says must be configured as input first
pin_b4_direction = input
pin_b1_direction = input
-- For testing purpose (checking if slave is responding to START/STOP signals)
-- you may want to activate 7bits address with interrupts (see spec)
;;SSPCON = 0b_0011_1110 -- slave 7bit address, start/stop interrupt
SSPCON1 = 0b_0011_0110 -- slave 7bit address
-- I2C slave hardware
-- Careful: we're in 7bits i2c address, *but* PIC
-- wants an address coded on 8bits, that is, with read/write bit
-- In master, slave address is:
-- 0x2E <=> 0b_0010_1110
-- So, in slave, by left-shifting once, we have:
-- 0x5C <=> 0b_0101_0110
SSPADD = 0x5C
-- init SSPSTAT
SSPSTAT_BF = false
SSPCON1_WCOL = false
SSPCON1_SSPOV = false
PIR1_SSPIF = false
-- enable interrupts
PIE1_SSPIE = true
INTCON_GIE = true
INTCON_PEIE = true
-- "Ready !" LED
var bit ready_led_direction is pin_b0_direction
var bit ready_led is pin_b0
ready_led_direction = output
-- Error LED
var bit error_led_direction is pin_b3_direction
var bit error_led is pin_b3
error_led_direction = output
var byte tmpstat
var byte tmpbuf
var byte data
-- test to set SSPBUF to see if it's changed while receiving
-- the first byte address
SSPBUF = "A"
function read_i2c() return byte is
tmpbuf = SSPBUF
return tmpbuf
end function
procedure write_i2c(byte in what) is
-- wait 'til buffer is empty
while SSPSTAT_BF loop end loop
var bit dosend = true
while dosend
loop
SSPCON1_WCOL = false
-- try to write into buffer, checking collision
SSPBUF = what
if ! SSPCON1_WCOL
then
-- ok, done
dosend = false
end if
-- else continue trying
end loop
SSPCON1_CKP = 1
end procedure
procedure proceed_state_1() is
serial_hw_write("1")
-- state 1:write operation, last byte is address, buffer full
-- byte is an address, it we get here, we just know master
-- wants to talk to us...
-- and we also know address is recognized (BF is set, see spec)
-- anyway, we must read buffer to reset BF bit
read_i2c()
end procedure
procedure proceed_state_2() is
serial_hw_write("2")
-- state 2: write operation, last byte is data, buffer full
-- got data, need to echo char + 1
data = read_i2c()
-- ultimate data processing... :)
data = data + 1
end procedure
procedure proceed_state_3() is
serial_hw_write("3")
-- state 3: read operation, last byte is address, buffer empty
-- master wants to get a value from us
write_i2c(data)
end procedure
procedure proceed_state_4() is
serial_hw_write("4")
-- state 4: read operation, last byte is data, buffer empty
-- master still wants to get a value from us
write_i2c(data)
-- note: this shouldn't occur
end procedure
procedure proceed_state_5() is
serial_hw_write("5")
-- state 5: nack
-- master doesn't want to talk with us anymore
-- reset slave logic
-- AN734 does not talk about setting CKP, whereas spec says
-- it must be set. Some people say it can be error prone.
SSPCON1_CKP = 1
data = 0
end procedure
procedure proceed_error() is
-- something went wrong, that is, XOR operations did not match
-- SSPSTAT bits
-- Just log current status
serial_hw_write("E")
serial_hw_write(SSPSTAT)
end procedure
procedure ssp_handler() is
pragma interrupt
serial_hw_write("I")
if PIR1_SSPIF
then
PIR1_SSPIF = false
tmpstat = SSPSTAT
-- mask out unimportant bit
tmpstat = tmpstat & 0b_0010_1101
-- check state 1: write operation, last byte is address, buffer
full
if (tmpstat ^ 0b_0000_1001) == false
then
proceed_state_1()
-- check state 2: write operation, last byte is data, buffer
full
elsif (tmpstat ^ 0b_0010_1001) == false
then
proceed_state_2()
-- check state 3: read operation, last byte is address, buffer
empty
elsif (tmpstat ^ 0b_0000_1100) == false
then
proceed_state_3()
-- check state 4: read operation, last byte is data, buffer
empty
elsif (tmpstat ^ 0b_00101100) == false
then
proceed_state_4()
-- check state 5: nack
elsif (tmpstat ^ 0b_0010_1000) == false
then
proceed_state_5()
-- check only got a start signal (when using interrupts)
else
proceed_error()
end if
else
-- another interrupt. Weird...
ready_led = low
delay_100ms(10)
ready_led = high
serial_hw_write("*")
end if
end procedure
ready_led = low
error_led = high
delay_1ms(250)
error_led = low
delay_1ms(250)
error_led = high
delay_1ms(250)
error_led = low
delay_1ms(250)
error_led = high
delay_1ms(250)
error_led = low
ready_led = high
forever loop
-- just loop until interrupt is raised
end loop