Content originally posted in LPCWare by mhjerde on Wed Mar 24 16:56:33 MST 2010
Hi CodeRedSupport, thanks for your reply.
The lack of attention to detail that leaves "Preliminary" and "2008" in the header is evident throughout the rest of the code and examples.
Please contemplate for a minute "what is the purpose of a code example?" One typical purpose would be to convey information as clearly and understandable as possible to someone who is unfamiliar with it.
And then have a look at at this typical example from the lpcxpresso kit. There is barely commenting at all and plenty of "magic numbers". In order to understand the code below you would have to go through it line by line with the UM in hand to try and deconstruct what is going on. I'm sure you can easily see for yourself a number of other issues with the code below.
I believe we're in the target group for the LPCxpresso. We're new to the part, we're building a prototype that hopefully will lead to mass production and sales of a meaningful number of MCU's. I thought lpcxpresso would be a quick way to get up and running, but that was a mistake. The xpresso part of the name does not seem to refer to speed of development, but rather to the amount of coffee you have to drink while trying to get the thing running.
Quote:
/*****************************************************************************
** Function name:I2CInit
**
** Descriptions:Initialize I2C controller
**
** parameters:I2c mode is either MASTER or SLAVE
** Returned value:true or false, return false if the I2C
**interrupt handler was not installed correctly
**
*****************************************************************************/
uint32_t I2CInit( uint32_t I2cMode )
{
/* It seems to be bit0 is for I2C, different from
UM. To be retested along with SSP reset. SSP and I2C
reset are overlapped, a known bug, for now, both SSP
and I2C use bit 0 for reset enable. Once the problem
is fixed, change to "#if 1". */
#if 1
LPC_SYSCON->PRESETCTRL |= (0x1<<1);
#else
LPC_SYSCON->PRESETCTRL |= (0x1<<0);
#endif
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);
LPC_IOCON->PIO0_4 &= ~0x3F;/* I2C I/O config */
LPC_IOCON->PIO0_4 |= 0x01;/* I2C SCL */
LPC_IOCON->PIO0_5 &= ~0x3F;
LPC_IOCON->PIO0_5 |= 0x01;/* I2C SDA */
/*--- Clear flags ---*/
LPC_I2C->CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
/*--- Reset registers ---*/
#if FAST_MODE_PLUS
LPC_IOCON->PIO0_4 |= (0x1<<9);
LPC_IOCON->PIO0_5 |= (0x1<<9);
LPC_I2C->SCLL = I2SCLL_HS_SCLL;
LPC_I2C->SCLH = I2SCLH_HS_SCLH;
#else
LPC_I2C->SCLL = I2SCLL_SCLL;
LPC_I2C->SCLH = I2SCLH_SCLH;
#endif
if ( I2cMode == I2CSLAVE )
{
LPC_I2C->ADR0 = PCF8594_ADDR;
}
/* Enable the I2C Interrupt */
NVIC_EnableIRQ(I2C_IRQn);
LPC_I2C->CONSET = I2CONSET_I2EN;
return( TRUE );
}
Contrast the above to a typical snippet from one of NXP's competitors:
Quote:
//
//! Initializes the I2C Master block.
//!
//! \param ulBase is the base address of the I2C Master module.
//! \param ulI2CClk is the rate of the clock supplied to the I2C module.
//! \param bFast set up for fast data transfers
//!
//! This function initializes operation of the I2C Master block. Upon
//! successful initialization of the I2C block, this function will have set the
//! bus speed for the master, and will have enabled the I2C Master block.
//!
//! If the parameter \e bFast is \b true, then the master block will be set up
//! to transfer data at 400 kbps; otherwise, it will be set up to transfer data
//! at 100 kbps.
//!
//! The peripheral clock will be the same as the processor clock. This will be
//! the value returned by SysCtlClockGet(), or it can be explicitly hard coded
//! if it is constant and known (to save the code/execution overhead of a call
//! to SysCtlClockGet()).
//!
//! This function replaces the original I2CMasterInit() API and performs the
//! same actions. A macro is provided in <tt>i2c.h</tt> to map the original
//! API to this API.
//!
//! \return None.
//
//*****************************************************************************
void
I2CMasterInitExpClk(unsigned long ulBase, unsigned long ulI2CClk,
tBoolean bFast)
{
unsigned long ulSCLFreq;
unsigned long ulTPR;
//
// Check the arguments.
//
ASSERT((ulBase == I2C0_MASTER_BASE) || (ulBase == I2C1_MASTER_BASE));
//
// Must enable the device before doing anything else.
//
I2CMasterEnable(ulBase);
//
// Get the desired SCL speed.
//
if(bFast == true)
{
ulSCLFreq = 400000;
}
else
{
ulSCLFreq = 100000;
}
//
// Compute the clock divider that achieves the fastest speed less than or
// equal to the desired speed. The numerator is biased to favor a larger
// clock divider so that the resulting clock is always less than or equal
// to the desired clock, never greater.
//
ulTPR = ((ulI2CClk + (2 * 10 * ulSCLFreq) - 1) / (2 * 10 * ulSCLFreq)) - 1;
HWREG(ulBase + I2C_O_MTPR) = ulTPR;
}