|
|
View previous topic :: View next topic |
Author |
Message |
silelis
Joined: 12 Jun 2007 Posts: 68 Location: Poland, podlaskie district
|
I2C PIC (master) to PIC (slave) routine |
Posted: Mon Sep 25, 2017 5:16 am |
|
|
Hello,
I've spent a lot of time on my project and one of the results is i2c_engine which I want to share with you.
It is PIC to PIC engine.
I2C_Engine.h
Code: |
/**************************************************************************/
/*!
@file i2c_engine.h
@author D. Bankowski ([email protected])
@brief Driver for i2c master.
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2017, D. Bankowski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#ifndef _I2C_ENGINE_
#define _I2C_ENGINE_
#define I2C_DELAY_US 20
#define I2C_INTERBYTE_DELAY_US 60
#define READ__EEPROM TRUE
#define normal__I2C FALSE
void i2cInit (void);
void i2cEngine (int1);
#endif
|
I2C_Engine.c
Code: |
/**************************************************************************/
/*!
@file i2c_engine.c
@author D. Bankowski ([email protected])
@brief Driver for i2c master.
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2017, D. Bankowski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#include </I2C_Engine.h>
#ifndef _TRANSMISSION_BUFFERS_
#include </MCU_include/core/transmission_buffers/transmission_buffers.c>
#endif
unsigned int32 I2CReadLength; //I2C zmieniŠ¤ na
unsigned int32 I2CWriteLength;
void i2cInit(void) {
output_float(_I2C_SCL);
output_float(_I2C_SDA);
}
int8 __i2cDeviceStatus() {
int8 ack;
i2c_start(); // If the write command is acknowledged,
delay_us(I2C_DELAY_US);
ack = i2c_write(MasterBuffer[0]&0xFE); // then the device is ready. PING should be always of write address so 0xFE 0b11111110 is required on ping
delay_us(I2C_DELAY_US);
i2c_stop();
delay_us(I2C_DELAY_US);
return ack; // 0 means ACK, 1 means NO ACK, 2 means there was a collision if in Multi_Master Mode. This does not return an ACK if using i2c in slave mode
}
int8 __try_i2c_bus(void)
{
int8 i2c_try=1;
unsigned int16 i2c_tryout_error = 0;
while(i2c_try!=0&&i2c_tryout_error <100) //i2c_tryout_error<100
{
i2c_try = __i2cDeviceStatus();
if (i2c_try!= 0)
{
dbg_printf("I2C w.addr:%x error try(s):%Lu status:%d", MasterBuffer[0], i2c_tryout_error, i2c_try);
dbg_return_carriage();
}
i2c_tryout_error = i2c_tryout_error +1;
delay_us(254);
}
return i2c_try;
}
void i2cEngine(int1 eeprom_read = FALSE) //, unsigned int8 = 0)
{
disable_interrupts(GLOBAL);
int8 i2c_ACK=__try_i2c_bus();
if (i2c_ACK==0)
{
i2c_start();
delay_us(I2C_DELAY_US);
unsigned int8 i;
if (I2CWriteLength>0)
{
for(i=0;i<I2CWriteLength; i++)
{
i2c_write(MasterBuffer[i]); //write to device from buffer
delay_us(I2C_DELAY_US);
}
}
if (eeprom_read == TRUE)
{
i2c_start();
delay_us(I2C_DELAY_US);
i2c_write(MasterBuffer[2]);
delay_us(I2C_DELAY_US);
}
if (I2CReadLength > 0)
{
int1 state;
for(i=0;i<I2CReadLength; i++)
{
if (i<(I2CReadLength-1))
state = TRUE;
else
state = FALSE;
SlaveBuffer[i]=i2c_read(state);
delay_us(I2C_INTERBYTE_DELAY_US);
}
}
i2c_stop();
delay_us(I2C_DELAY_US);
if (I2CReadLength == 0)
{
dbg_printf("I2C w.addr:%x ACK", MasterBuffer[0]);
dbg_return_carriage();
}
else
{
dbg_printf("I2C r.addr:%x ACK", MasterBuffer[0]);
dbg_return_carriage();
}
break;
}
else if (i2c_ACK==1)
{
dbg_printf("I2C addr:%x !ACK", MasterBuffer[0]);
dbg_return_carriage();
break;
}
else if (i2c_ACK==2)
{
dbg_printf("I2C adr:%x COLISION", MasterBuffer[0]);
dbg_return_carriage();
break;
}
I2CWriteLength = 0;
I2CReadLength = 0;
enable_interrupts(GLOBAL);
}
|
transmission_buffers.h
Code: |
#ifndef _TRANSMISSION_BUFFERS_
#define _TRANSMISSION_BUFFERS_
#define mcu_Transmission_BUFSIZE 65
#define mcu_Reception_BUFSIZE 257
unsigned int MasterBuffer[mcu_Transmission_BUFSIZE ];
unsigned int SlaveBuffer[mcu_Reception_BUFSIZE];
void ClearBuffers (unsigned int, short int);
void ClearMasterBuffer (void);
void ClearSlaveBuffers (void);
#endif
|
transmission_buffers.c
Code: |
#include </transmission_buffers.h>
void ClearBuffers (unsigned int *buffer, short int buffer_size)
{
unsigned int8 i;
for ( i = 0; i < buffer_size; i++ )
{
*(buffer+i)= 0x00;
}
}
void ClearMasterBuffer (void)
{
ClearBuffers(&MasterBuffer,mcu_Transmission_BUFSIZE);
}
void ClearSlaveBuffers (void)
{
ClearBuffers(&SlaveBuffer,mcu_Reception_BUFSIZE);
}
|
The whole idea is to use only one function to perform i2c which is i2c_engine.
based on information in:
I2CReadLength;
I2CWriteLength;
It reads and send MasterBuffer data and receive data to SlaveBuffer.
In excample to write data you should:
Code: |
MasterBuffer[0]= i2c_slave_wirte_addres;
MasterBuffer[1]= data1;
MasterBuffer[2]= data2;
I2CWriteLength=3;
I2CReadLength=0;
i2c_engine(false); //Generaly false is required. Only eeprom requires extra i2c_stat os TRUE only in case of eeprom
|
To read data you need:
Code: |
MasterBuffer[0]= i2c_slave_read_addres;
//MasterBuffer[1]= read_parameter; //if required - mostly not required
I2CWriteLength=1; //Because You have to write at least address
I2CReadLength=x; //x = number of bytes You want to read.
i2c_engine(false);
|
There is also some kind of ping function so if the device is broken it will not freeze routine. |
|
|
silelis
Joined: 12 Jun 2007 Posts: 68 Location: Poland, podlaskie district
|
|
Posted: Mon Sep 25, 2017 5:25 am |
|
|
Ok. Now something about slave PIC.
i2c_slave.h
Code: |
/**************************************************************************/
/*!
@file i2c_slave.h
@author D. Bankowski ([email protected])
@brief Driver for i2c slave.
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2017, D. Bankowski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#ifndef _I2C_ENGINE_SLAVE_
#define _I2C_ENGINE_SLAVE_
#if getenv("SFR_VALID:SSPSTAT")
#byte SSP1STAT = getenv("SFR:SSPSTAT")
#bit SSP1STAT_STOP_SEEN=SSP1STAT.4
#WARNING "PIC_SSPSTAT REGISTER CONFIGURED"
#else
#ERROR "PIC_SSPSTAT REGISTER SHOULD BE DEFINED in i2c_slave.h"
#endif
#define I2C_SLAVE_BUFSIZE 15
unsigned int8 Master_2_Slave_Buffer[I2C_SLAVE_BUFSIZE];
unsigned int8 Slave_2_Master_Buffer[I2C_SLAVE_BUFSIZE];
unsigned int i2c_buffer_counter;
void clr_SSPSTAT(void);
void ClearBuffers (unsigned int, short int);
void set_i2c_interrupt_ready(void);
void i2c_slave_interrupt (void);
#endif
|
i2c_slave.c
Code: |
/**************************************************************************/
/*!
@file i2c_slave.c
@author D. Bankowski ([email protected])
@brief Driver for i2c slave.
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2017, D. Bankowski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#include <i2c_slave.h>
void clr_SSPSTAT(void) //when data is counted by program and can read new data
{
SSP1STAT = 0;
i2c_buffer_counter = 0;
}
void ClearBuffers (unsigned int *buffer, short int buffer_size)
{
unsigned int8 i;
for ( i = 0; i < buffer_size; i++ )
{
*(buffer+i)= 0x00;
}
}
//unsigned int set_i2c_interrupt_ready(void)
void set_i2c_interrupt_ready(void)
{
clr_SSPSTAT();
i2c_slave_ready();
}
void i2c_slave_interrupt (void) //Interrupt hendler
{
unsigned int8 state; //, incoming;
state = i2c_isr_state();
if (state < 0x80)
{
Master_2_Slave_Buffer[i2c_buffer_counter]= i2c_read();
i2c_buffer_counter=i2c_buffer_counter+1;
}
if(state >= 0x80) //Master is requesting data do Your operations here
{
i2c_write(DATA_HERE);
}
if (SSP1STAT_STOP_SEEN==1)
{
i2c_slave_not_ready() ;
}
}
|
One of the problems that I appear was that my slave was calculating the received data, and the next one was coming. This is dangerous because You can not take next data before old was calculated.
To prevent this action after I receive data I have put to pic fake i2c adress and after calculation I put correct one like bellow:
Code: |
#define i2c_slave_address 0x10
#define i2c_slave_fake_address 0x12
#define i2c_slave_ready() I2C_SlaveAddr(i2c_slave_address)
#define i2c_slave_not_ready() I2C_SlaveAddr(i2c_slave_fake_address)
|
If slave is in fake address mode the master can not ping it and will not send data. |
|
|
silelis
Joined: 12 Jun 2007 Posts: 68 Location: Poland, podlaskie district
|
|
Posted: Mon Sep 25, 2017 5:29 am |
|
|
And last thing, debug functions are:
Code: |
#define dbg_printf(fmt,...) fprintf(LOG_PORT,fmt, __VA_ARGS__)//;
#define dbg_return_carriage() fprintf(LOG_PORT,"\r\n");
|
|
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu Sep 28, 2017 8:16 pm |
|
|
I dont know if this works, but your code looks pretty. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
silelis
Joined: 12 Jun 2007 Posts: 68 Location: Poland, podlaskie district
|
|
Posted: Thu Sep 28, 2017 11:19 pm |
|
|
It is working. I have spend a lot of time on it for my radio. The code is written in way that also allows to me to share sending/receiving buffer between multiple communication protocols (i2c, uart, etc). And to be honest that was the main reason to do that.
And here is an example of using it with TDA7418 equaliser.
Last edited by silelis on Thu Sep 28, 2017 11:32 pm; edited 1 time in total |
|
|
silelis
Joined: 12 Jun 2007 Posts: 68 Location: Poland, podlaskie district
|
|
Posted: Thu Sep 28, 2017 11:22 pm |
|
|
Oh and one more think. The code of slave to handle received data.
Code: |
main()
{
if (SSP1STAT_STOP_SEEN==1 && i2c_buffer_counter==1)
{
set_i2c_interrupt_ready(); //i2c_engine() test condition (ping) only - NO DATA WAS SENT
}
else if (SSP1STAT_STOP_SEEN==1&& i2c_buffer_counter>1)
{
// proceed recived data
}
}
|
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|