|
|
View previous topic :: View next topic |
Author |
Message |
tems
Joined: 26 Nov 2008 Posts: 8
|
dual HW I2C on 18F23K22 |
Posted: Thu Jan 09, 2014 2:48 pm |
|
|
I've got a 18F23k22 that i want to use the HW i2c ports. One used for an eeprom ( master ) the other for communications ( slave ). I can't seem to get it to work properly. The master never gets enabled ( SSPEN ). I contacted CCS and they said to use the I2C_INIT functions but I'm not sure how that is done. Has anyone else used the dual I2C ports? Has anyone got them to work. Any help would be appreciated.
Code: |
#include <18F23K22.h>
#device ADC=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES BROWNOUT //brownout reset
#FUSES BORV29
//#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST
#Fuses PLLEN
#fuses intrc_IO
#device ICD=TRUE
#use delay(int=64MHz,restart_wdt)
#use fast_IO(B)
#use fast_IO(A)
#use fast_IO(C)
#use i2c(Slave,Fast,I2C1,restart_wdt,force_hw,address=0x20,stream=com)
#use i2c(Master,Fast,I2C2,restart_wdt,force_hw,stream=eemem)
#define EEPROM_SCL pin_B1
#define EEPROM_SDA pin_B2
#define i2c_eemem_address 0xa0
#ZERO_RAM
#opt 11
#int_ssp
void int_ssp()
{
//! int8 i;
//! i2c_write(com,0);
clear_interrupt(int_ssp);
}
void main()
{
int8 data;
set_tris_a (0x00); // a0, a1, a2, a3, a4 as outputs
set_tris_b (0x07); // b0 through b2 as inputs
set_tris_c (0x98); // c3 and c4 as inputs
output_c (00);
output_B (00); //set the pwm outputs all low
output_A (00);
i2c_init(eemem,1);
i2c_init(com,1);
init_ext_eeprom();
data=read_ext_eeprom(0xA0,0);
enable_interrupts(int_ssp);
enable_interrupts(global);
}
// And the modified 24256 code
///////////////////////////////////////////////////////////////////////////
//// Library for a 24LC256 serial EEPROM ////
//// ////
//// init_ext_eeprom(); Call before the other functions are used ////
//// ////
//// write_ext_eeprom(a, d); Write the byte d to the address a ////
//// ////
//// d = read_ext_eeprom(a); Read the byte d from the address a ////
//// ////
//// The main program may define eeprom_sda ////
//// and eeprom_scl to override the defaults below. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////
//#ifndef EEPROM_SDA
//#define EEPROM_SDA PIN_B1
//#define EEPROM_SCL PIN_B0
//#endif
//#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL)
#define EEPROM_ADDRESS long int
#define EEPROM_SIZE 65536
void init_ext_eeprom()
{
output_float(EEPROM_SCL);
output_float(EEPROM_SDA);
}
void write_ext_eeprom(int8 wa, long int address, BYTE data,int8 check)
{
short int status;
i2c_start(eemem);
wa=wa & 0xfe; // make sure r/w bit is low
i2c_write(eemem,wa);
i2c_write(eemem,address>>8);
i2c_write(eemem,address);
i2c_write(eemem,data);
i2c_stop(eemem);
if (check==1)
{
i2c_start(eemem);
status=i2c_write(eemem,wa);
while(status==1)
{
i2c_start(eemem);
status=i2c_write(eemem,wa);
}
i2c_stop(eemem);
}
}
void write_ext_eeprom_page(int8 wa,long int address, int8 *data,int8 length)
{
short int status;
int8 i;
int8 value;
i2c_start(eemem);
wa=wa & 0xfe; // make sure r/w bit is low
i2c_write(eemem,wa);
i2c_write(eemem,address>>8);
i2c_write(eemem,address);
for( i=0;i<length;i++)
{
value=*data;
i2c_write(eemem,value);
data++;
}
i2c_stop(eemem);
i2c_start(eemem);
status=i2c_write(eemem,wa);
while(status==1)
{
i2c_start(eemem);
status=i2c_write(eemem,wa);
}
i2c_stop(eemem);
}
BYTE read_ext_eeprom(int8 wa,long int address)
{
BYTE data;
i2c_start(eemem);
wa=wa & 0xfe; // make sure r/w bit is low
i2c_write(eemem,wa);
i2c_write(eemem,address>>8);
i2c_write(eemem,address);
i2c_start(eemem);
i2c_write(eemem,wa+1);
data=i2c_read(eemem,0);
i2c_stop(eemem);
return(data);
}
void read_ext_eeprom_page(int8 wa,long int address, int8 *data,int8 length)
{
int8 i;
i2c_start(eemem);
wa=wa & 0xfe; // make sure r/w bit is low
i2c_write(eemem,wa);
i2c_write(eemem,address>>8);
i2c_write(eemem,address);
i2c_start(eemem);
i2c_write(eemem,wa+1);
for( i=0;i<length-1;i++)
{
*data=i2c_read(eemem,1);
data++;
}
*data=i2c_read(eemem,0);
i2c_stop(eemem);
return;
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 09, 2014 3:30 pm |
|
|
I don't think you need to use streams. The CCS #use i2c() parameters
stay in effect for all i2c code called after that line, until a new #use i2c()
line is encountered by the compiler. This is stated in the CCS manual.
So, you can place the #include for the 24LC256 driver first. It contains
its own #use i2c() line, which you can edit. You should probably make
a local copy of the 24256.c driver file and put it in your CCS project folder.
Then edit that file and #include it. Rename it as shown below.
After that point, you can put in the #use i2c() line for your i2c slave, and
follow it with the slave interrupt routine.
Here is an outline of how to do this:
Code: |
#include <18F23K22.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)
// Edit the following file and change only the #use i2c() line to:
// #use i2c(Master,Fast,I2C2,Force_hw)
#include "my24256.c"
//----------------------------
// i2c slave code:
#use i2c(Slave,I2C1,address=0x20)
unsigned int8 address, buffer[16];
#int_ssp
void ssp_interrupt()
{
unsigned int8 incoming, state;
state = i2c_isr_state();
.
.
.
// Put in code from CCS Ex_slave.c example file here
.
.
}
//=======================================
void main()
{
write_ext_eeprom(0, 0x55);
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while(1);
} |
Your posted code has a large number of newbie mistakes, such as
overriding the TRIS on hardware i2c pins (setting them to low-level
outputs when the compiler has already set them to be inputs).
Also you let your code fall off the end of main(). Also you put return
statements at the end of functions that don't return a value. All functions
automatically return anyway. Also, you have set it to #opt 11. I wouldn't
do that. Changing the #opt will cause more bugs than you need.
#zero_ram is probably not needed.
The most important advice is to first get each i2c bus working separately.
Make the master program. Prove that it works. Make the slave program
(without any master code). Prove that the slave works. Then combine
them as shown above. |
|
|
tems
Joined: 26 Nov 2008 Posts: 8
|
|
Posted: Fri Jan 10, 2014 2:47 pm |
|
|
This code was chopped from a fairly large single I2C master program 4000+ lines. Its been used for many years and adapted to the newer pics. When do you need to use streams. I'm an example person so if there is an example dual HW i2c it would help a bunch. |
|
|
|
|
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
|