Jump to content
 
  • 0

I need help with I2C on a PIC16F1 device


Orunmila

Question

3 answers to this question

Recommended Posts

  • Member

I think the easiest way to learn how to use I2C on those boards is to use MCC to generate the I2C code for you. I have created a project using the MCC "I2CSIMPLE" driver which is part of the "Foundation Services" package in MCC.

The easiest way to generate an example using this library is probably to use a MikroElektronika Click board. I happened to have a TouchPad click board (this one https://www.mikroe.com/touchpad-click)

The TouchPad Click is a I2C Slave device. It contains a MTCH6102 from Microchip which presents itself on I2C address 0x25

Control is performed using a number of registers on the device, so e.g. if I want to read the state of touch of the board I need to read the register at address 0x10. So this means in terms of I2C what I need to do is do an I2C ADDR write (write 0x25 as address) and then write the register address (which is 0x10) and then do an I2C read to read the data from this location.

I can do all of this using the MCC generated function as follows

touch_state = i2c_read1ByteRegister(0x25, 0x10);

I attach the project here for you to look at to get you going. The project includes the MC3 file containing the MCC configuration, so if you have MCC v3.66 or later you should be able to open MCC and look at the configuration.

The example code checks for a touch state, and if there is one it clears the 4 LED's on the HPC board and then turns on the LED corresponding to the touch position. The MTCH6102 provides 32 locations on the X-axis, so we divide this range in 4, the first 8 pixels will turn on D2, next are turns on D3 up to D5.

TouchpadExample.zip

RightLED.png.c98cb8ac7bcee2a21e063603b8dd96a3.pngLeftLED.png.e0357a79306589eb38c58ea0f7787071.png


At masters 2018 Microchip had a class with a LAB Manual to step you through this process step by step. The class also contained a couple of other labs such as using the TIMER driver in MCC and the BLE Click board from Mikro Elektronika.

LAB 3 in this manual has screenshots and explains step by step how to reproduce the above example

I uploaded this lab manual here :

 

 

 

 

Link to comment
Share on other sites

  • Member

Some advanced information about Interrupts.

That I2C driver from MCC can opererate either in "Interrup Driven" mode or a blocking "Polled Mode". You will notice that I2C operations are executed by the function masterOperation(), which looks as follows in this project:

i2c_error_t i2c_masterOperation(bool read)
{
    i2c_error_t ret = I2C_BUSY;
    if(!i2c_status.busy)
    {
        i2c_status.busy = true;
        ret = I2C_NOERR;
        
        if(read)
        {
            i2c_status.state = I2C_SEND_ADR_READ;
        }
        else
        {
            i2c_status.state = I2C_SEND_ADR_WRITE;
        }
        i2c1_driver_start();
        
        if(! mssp1_IRQisEnabled())
            i2c_poller();
    }
    return ret;
}

Notice the last part is checking if the mssp1_IRQisEnabled(). If the interrupt is enabled the function returns immediately with the value I2C_Busy, but if the interrupt is NOT enabled it will call i2c_poller(). This function looks like this :

inline void i2c_poller(void)
{
    while(i2c_status.busy)
    {
        mssp1_waitForEvent(NULL);
        i2c_ISR();
    }
}

So as you can see this will keep on calling waitForEvent as long as the i2c_status is busy. This means the function will only return after the I2C operation is completed.

Using this method this driver can be switched between interrupt driven and polled even at runtime by simply enabling or disabling the I2C interrupt.

The exact bit is revealed by the implementation of  the function mssp1_IRQisEnabled()

inline __bit mssp1_IRQisEnabled(void)
{
    return PIE3bits.SSP1IE;
}

 

 

Link to comment
Share on other sites

  • Member

Your pro-tip for the day.  If you use this code from MCC on a PICmicrocontroller, the function i2c_ISR must be duplicated due to the way the C stack is implemented on a PICmcu.  If you want to save code space, simply decide how you want your code to run (interrupt or polled) and remove the call to i2c_isr from the master interrupt code or remove the test in master_operation.  Either one will remove the duplication because the function i2c_ISR will not exist in both contexts. (interrupt and "main")

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

 


×
×
  • Create New...