Right, I have finally fixed this problem, so here is the corrected code for anyone who wants to try and get started with this pair of boards using C++.
The main error was down in the Case statement where the contents of the address pointer were mistakenly passed to the data out, meaning that a byte of zero was sent first. This code is not very helpful in it's current format, and needs restructuring to make it do anything useful, but maybe it helps someone get started. In it's current form, I am using the 10k pull ups on the BV511, and I've added two more on the 4213 end also. I have about 15cm of unscreened wire 4off ~19/0.2 and I'm running test LEDs out of each output (Y1/2/3/4) on the same 5V supply, with ~330R resistors.
The code enables all outputs, and switches on Y2 and Y3 (High), Y1 and Y4 remain off (low). Good Luck. Jeremy
/************************************************************/
/* PROJECT: I2C test platform */
/************************************************************/
#include <LPC213x.H>
#include <stdarg.h>
void I2CISR (void) __irq ; //I2C interrupt routine
void I2CTransferByte(unsigned int I2CAddr,unsigned char MemAddr,unsigned char count,...);
//Background call to start master send and receive byte transfers
unsigned char enable1[2] = {0x01,0x01}; //enable command for motor controller outputs Y1 and Y2
unsigned char enable2[2] = {0x02,0x01}; //enable command for motor controller outputs Y3 and Y4
unsigned char turnon1[2] = {0x12,0x01}; //switches output Y2 to 1
unsigned char turnon2[2] = {0x13,0x01}; //switches output Y3 to 1
unsigned char step1[1] = {0x20}; //continuous step
unsigned char messageIn[4]; //used to read in from swithes - unused
unsigned char *I2CData,
I2Counter,
I2CAddress,
MemAddress,
lock; //Define Function prototypes and Global variables
// delay added for between command and data bytes needed by BV4213
void delay (void)
{
unsigned int count = 0;
for ( count = 0; count <= 0xFFF; count++){
}
return;
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX MAIN XXXXXXXXXXXXXXXXXXXXXXXXXXXXx
int main(void)
{
lock = 0; //Initilise the lock flag
// this block sets up the pins, and the clock rate, it used to be after the VIC setup block
PINSEL0 = 0x50; //Switch GPIO to I2C pins
I2C0CONCLR = 0x0000002C; //Clear all I2C settings - JF added here, but also in transfer byte
I2C0CONSET = 0x00000040; //Enable the I2C interface set I2EN - JF added here, but also in transfer byte
I2C0SCLH = 0x1F0; //Set bit rate 14.7456Mhz/VPBDIV+SCLH+SCLL = 14.7456/4+8+8 = 57.6Khz
I2C0SCLL = 0x1F0; // Changed to 1F0 ~24khz, seems to be speed limited, poss due to 10k pull ups
// Vectored interrupt control setup block
VICVectCntl1 = 0x00000029; //select priority 1 for I2C0 interupt and enable it
VICIntEnable = 0x00000200; //enables the I2C0 interupt
VICVectAddr1 = (unsigned)I2CISR; //pass the address of the IRQ into the VIC slot
// Block writes data to the I2C
I2CTransferByte(0x42,0,2,enable1); //write data to the I2C Memory - write to device 0x42, start at byte 0 of the message, send 2 bytes.
I2CTransferByte(0x42,0,2,enable2); //write data to the I2C Memory - write to device 0x42, start at byte 0 of the message, send 2 bytes.
//I2CTransferByte(0x42,0,0); //set address to zero - doesn't seem to do anything..?
//delay (); //delay 1
I2CTransferByte(0x42,0,2,turnon2); //write data to the I2C Memory - write to device 0x42, start at byte 0 of the message, send 2 bytes.
I2CTransferByte(0x42,0,2,turnon1); //write data to the I2C Memory - write to device 0x42, start at byte 0 of the message, send 2 bytes.
//I2CTransferByte(0x42,0,0); //set address to zero
while(1)
{
;
}
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Transfer XXXXXXXXXXXXXXXXXXXXXXXXXXXX
void I2CTransferByte(unsigned int I2CAddr,unsigned char MemAddr,unsigned char count,...)
{
va_list ap; // allows variable arguments to be passed in i.e. data volume to be sent
va_start(ap,count);
while(lock == 1) //Wait for interrupt to signal end of I2C activity
{
;
}
lock = 1; //Set I2C bus as active
I2CAddress = I2CAddr; //Place address and data in Globals to be used by the interrupt
if(count >0)
{
I2CData = va_arg(ap,unsigned char *);
}
I2Counter = count;
MemAddress = MemAddr;
I2C0CONCLR = 0x0000002C; //Clear all I2C settings - was FF but user manual reserves some bits
I2C0CONSET = 0x00000040; //Enable the I2C interface set I2EN
I2C0CONSET = 0x00000020; //Start condition set STA
va_end(ap);
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX I2CISR XXXXXXXXXXXXXXXXXXXXXXXXXXXXx
void I2CISR (void) __irq //I2C interrupt service routine
{
switch (I2C0STAT) //Read Status code and switch to next action
{
case ( 0x08): //Start Condition has been sent
I2C0CONCLR = 0x20; //Clear start bit
I2C0DAT = I2CAddress; //Now send the Target address and write bit
break;
case (0x18): //Target address and write bit were sent and acknowledged by target
I2C0DAT = *I2CData; //Send the first byte of data
I2Counter--;
delay (); //This delay seems to be needed by the BV4213 - not sure why yet...
break;
case (0x20): //Target address was sent but Not acknowledged by target
I2C0DAT = I2CAddress; //Resend the target address and write bit
break;
case (0x28):
if(I2Counter-->0) //Data was sent, and acknowledged by target
{
I2CData++;
I2C0DAT = *I2CData; //Write data to tx register
}
else
{
I2C0CONSET = 0x10; //Stop condition
lock = 0; //Signal end of I2C activity
}
break;
case (0x30) : //Data was sent, but NOT Ack
I2C0DAT = *I2CData; //Send same data to tx register
break;
//Receive byte conditions
case (0x40) : //Slave Address +R, ACK
I2C0CONSET = 0x04; //Enable ACK for data byte
break;
case (0x48) : //Slave Address +R, Not Ack
I2C0CONSET = 0x20; //Resend Start condition
break;
case (0x50) : //Data Received, ACK
if(--I2Counter>0)
{
*I2CData = I2C0DAT;
I2CData++;
}
else
{
I2C0CONSET = 0x10; //Stop condition
lock = 0; //Signal end of I2C activity
}
break;
case (0x58): //Data Received, Not Ack
I2C0CONSET = 0x20; // Resend Start condition
break;
default :
break;
}
I2C0CONCLR = 0x08; //Clear I2C interrupt flag
VICVectAddr = 0x00000000; //Clear interrupt in
}