Как правильно описать прерывания от I2C в LPC2148? Достался вот такой кусок кода. Никак не могу заставить работать прерывания от I2C . Среда keil 3.70. В void i2c_ISR (void) входит только один раз при I2C0STAT = 0x08. Дальше висит.
type.h
#ifndef __TYPE_H__
#define __TYPE_H__
#ifndef NULL
#define NULL ((void *)0)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef TRUE
#define TRUE (1)
#endif
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;
#endif /* __TYPE_H__ */
i2c.c
#include "LPC214X.h"
#include "i2c.h"
#define I2C_EN (1<<6)
#define I2C_START (1<<5)
#define I2C_STOP (1<<4)
#define I2C_INT (1<<3)
#define I2C_ACK (1<<2)
BYTE I2C_address;
BYTE I2C_data;
struct {
UINT8 DevAddr;
UINT8 Addr;
UINT8 Counter;
UINT8 Data[2];
UINT8 Done;
} I2C;
void i2c_lpc_init(int Mode)
{
VICVectCntl1 = 0x00000029; //select a priority slot for a given interrupt
VICVectAddr1 = (unsigned)i2c_ISR; //pass the address of the IRQ into the VIC slot
VICIntEnable = 0x00000200; //enable interrupt
PINSEL0 = 0x50;
if(Mode == I2C_SPEED_400)
{
//--- I2C Timing for Pclk = 15 MHz
// 15/(19+19) = 0,394 Mhz
I2C0SCLH = 19;
I2C0SCLL = 19;
}
else //Slow
{
I2C0SCLH = 75;
I2C0SCLL = 75;
}
I2C0CONCLR = 0xFF; //-- Clear all flags
I2C0CONSET = 0x40; //-- Set Master Mode
}
void i2c_ISR (void) __irq //I2C interrupt routine
{
switch (I2C0STAT)
{
case (0x8): // START DONE
I2C0DAT = I2C.DevAddr; // Посылаем адрес и бит записи (0)
I2C0CONCLR = (I2C_INT | I2C_START); // Сбрасываем флаг состояния START и флаг прерывания
break;
case (0x20): // SLA+W, NACK
I2C0CONSET = I2C_STOP | I2C_START; // generate stop
I2C0CONCLR = I2C_INT;
//I2C0DAT = I2C_address;
break;
case (0x18): // Slave addr ACK
I2C0DAT = I2C.Addr;
I2C0CONCLR = I2C_INT;
break;
case (0x28): // Byte transfer ACK
if(I2C.DevAddr & (1<<0))
{
I2C0CONSET = I2C_START; // generate repeated start
I2C0CONCLR = I2C_INT;
}
else //write
{
if (I2C.Counter < 2)
{
I2C0DAT = I2C.Data[I2C.Counter];
I2C.Counter++;
}
else
{
I2C0CONSET = I2C_STOP;
I2C.Done = 1;
}
I2C0CONCLR = I2C_INT;
}
break;
case 0x10: // Repeated start done
I2C0DAT = I2C.DevAddr; // SEND SLA+R
I2C0CONCLR = (I2C_INT | I2C_START);
break;
case 0x40: // Slave ACKed SLA+R
if (I2C.Counter < 2)
{
I2C0CONSET = I2C_ACK; // send ACK if not last byte
}
I2C0CONSET = I2C_INT;
break;
case 0x50: // Byte received with ACK
I2C.Data[I2C.Counter] = I2C0DAT;
I2C.Counter++;
if (I2C.Counter == 1)
{
I2C0CONCLR = I2C_ACK; // send NACK after last byte
}
I2C0CONCLR = I2C_INT;
break;
case 0x58: // Last byte received
I2C.Data[I2C.Counter] = I2C0DAT;
I2C.Counter++;
I2C0CONSET = I2C_STOP;
I2C.Done = 0;
I2C0CONCLR = I2C_INT;
break;
default:;
}
VICVectAddr = 0; // Reset VIC logic
}
void pca9555_config(void)
{
I2C.DevAddr = 0x40 | (0x00 << 1); // Доп. адрес
I2C.Addr = I2C_PCA9555_CONF_P0;
I2C.Data[0] = 0x00;
I2C.Data[1] = 0x00;
I2C.Counter = 0;
I2C.Done = 0;
I2C0CONCLR = ( I2C_ACK | I2C_START | I2C_STOP | I2C_INT );
I2C0CONSET = ( I2C_EN | I2C_START );
while(I2C.Done != 1);
}
main.c
#include <LPC214x.H>
#include "main.h"
#include "i2c.h"
#include "input_trigger.h"
void main()
{
i2c_lpc_init(I2C_SPEED_400);
pca9555_config();
while (1);
}
-
- В ARMах я не спец, но похоже на то, что возникает прерывание от I2C когда мы еще не вышли из i2c_ISR (отложенное прерывание). Т.е. при выходе из i2c_ISR потеряли прерывание. Как в таком случае обрабатывать прерывания? - Ruslan(20.06.2009 11:56)
- Разобрался. Ruslan(234 знак., 23.06.2009 07:51)
- В ARMах я не спец, но похоже на то, что возникает прерывание от I2C когда мы еще не вышли из i2c_ISR (отложенное прерывание). Т.е. при выходе из i2c_ISR потеряли прерывание. Как в таком случае обрабатывать прерывания? - Ruslan(20.06.2009 11:56)