LPC8XX problem with I2C

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

LPC8XX problem with I2C

860 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dheide on Mon Oct 13 14:09:05 MST 2014
Hi there,

I have a problem using the I2C to communicate with a display. Below, I pasted the code which I destilled from the examples and the documentation.

I understand that the interrupt is enabled, but never called and the code hangs in the loop that waits for the interrupt.

I'm kind of stuck, so any help is appreciated!!!

Cheers, dheide



#define CLOCK_SETUP 1

#include "LPC8xx.h"

#define MASTER_STATE_MASK(0x7<<1)
#define STAT_MSTPEND  (1 << 0)
#define STAT_MSTRX (0x1 << 1)
#define STAT_MSTTX (0x2 << 1)
#define I2C_SMODE_PRE_DIV(90-1)
#define CFG_MSTENA(1 << 0)
#define STAT_MSTARBLOSS(1 << 4)
#define STAT_MSTSSERR (1 << 6)
#define TIM_MSTSCLLOW(d)((d) << 0)
#define TIM_MSTSCLHIGH(d)((d) << 4)

#define CTL_MSTCONTINUE(1 << 0)
#define CTL_MSTSTART(1 << 1)
#define CTL_MSTSTOP (1 << 2)


uint32_t I2CInterruptCount = 0;
uint32_t I2CMstRXCount = 0;
uint32_t I2CMstTXCount = 0;
uint32_t msttxrdy = 0;
uint32_t mstrxrdy = 0;

LPC_I2C_TypeDef *I2Cx = (LPC_I2C_TypeDef*) LPC_I2C_BASE;

void I2C_IRQHandler(void)
{
uint32_t active = LPC_I2C->INTSTAT;
uint32_t i2cmststate = LPC_I2C->STAT & MASTER_STATE_MASK;

I2CInterruptCount++;  <<--- Never called!!!

if ( active & STAT_MSTPEND )
{
LPC_I2C->INTENCLR = STAT_MSTPEND;

switch ( i2cmststate )
{
case STAT_MSTRX:
I2CMstRXCount++;
mstrxrdy = 1;
break;

case STAT_MSTTX:
I2CMstTXCount++;
msttxrdy = 1;
break;
}
}

}

int main(void)
{
uint32_t i, regVal;

SystemInit();
SystemCoreClockUpdate();

/* Initialize I2C pin connect */
/* connect the I2C SCL and SDA sigals to port pins(P0.10-P0.11)*/
regVal = LPC_SWM->PINASSIGN7 & ~(0xFFUL<<24);
LPC_SWM->PINASSIGN7 = regVal | (10 << 24);/* P0.10 is I2C SDA, ASSIGN0(31:24) */
regVal = LPC_SWM->PINASSIGN8 & ~(0xFF<<0);
LPC_SWM->PINASSIGN8 = regVal | (11 << 0);/* P0.11 is I2C SCL. ASSIGN0(7:0) */

/* Enable I2C clock */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);
/* Toggle peripheral reset control to I2C, a "1" bring it out of reset. */
LPC_SYSCON->PRESETCTRL &= ~(0x1<<6);
LPC_SYSCON->PRESETCTRL |= (0x1<<6);

/* setup I2C */
uint32_t dutycycle = 0;
I2Cx->DIV = I2C_SMODE_PRE_DIV;
I2Cx->CFG &= ~(CFG_MSTENA);
msttxrdy = mstrxrdy = 0;

I2Cx->MSTTIME = TIM_MSTSCLLOW(dutycycle) | TIM_MSTSCLHIGH(dutycycle);
I2Cx->INTENSET |= ( STAT_MSTARBLOSS | STAT_MSTSSERR );

NVIC_EnableIRQ(I2C_IRQn);

I2Cx->CFG |= CFG_MSTENA;

//
uint8_t addr = 0x3F << 1;

uint32_t len = 2;
uint8_t tx[len];
tx[0] = 0xFF; tx[1] = 0xFF;

I2Cx->MSTDAT = addr;
I2Cx->MSTCTL = CTL_MSTSTART;

msttxrdy = 0;
I2Cx->INTENSET = STAT_MSTPEND;

for ( i = 0; i < len; i++ )
{
while(!msttxrdy);   <<--- Here, the program hangs.

msttxrdy = 0;
I2Cx->MSTDAT = tx;
I2Cx->MSTCTL = CTL_MSTCONTINUE;
I2Cx->INTENSET = STAT_MSTPEND;
}

while(1);
return 0;
}

0 项奖励
回复
2 回复数

774 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dheide on Thu Oct 16 15:52:48 MST 2014
Thanks, good point!!!

This was just a test case since it did not work in the real programm (where the variables were volatile) but I'll correct that immediatly.
0 项奖励
回复

774 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by starblue on Tue Oct 14 00:26:57 MST 2014
For a start you should make I2CInterruptCount and the other variables volatile.
0 项奖励
回复