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

Reply via email to