Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Интерфейс I2C в LPC2368
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Oleg-K
Здравствуйте.
Требуется организовать обмен данными по интерфейсу I2C между МК LPC2368 и RTC M41T11. Взял пример из книги Тревора Мартина, тк раньше с I2C не работал. Скомпилировал, запустил - не работает((( Посмотрите свежим взглядом, где может быть ошибка?

Код
#include <LPC23xx.H>
#include <stdarg.h>
#include "uart.h"

void I2CISR (void)    __irq;    
void I2CTransferByte(unsigned int I2CAddr,unsigned char MemAddr,unsigned char count,...);            

unsigned char     message[4] ={0x01,0x02,0x03,0x04};                                    
unsigned char    messageIn[4];
unsigned char     *I2CData,
                 I2Counter,
                I2CAddress,
                MemAddress,
                lock;        


int main(void)
{

UART0_Init(115200); // инициализация интерфейса уарт0. работает 100%
UART_PutData(0, "I2C Test...", 11); //посылка в 0-ой уарт строки. работает 100%

lock = 0;        //Initilise the lock flag

  PINSEL1|=0x400000;  //инициализация выводов
  PINSEL1|=0x1000000;
  
PCONP |= 1 << 7; //включение питания модуля
                      
  I20SCLH          = 0x50; //установка частоты шины (нужно 100 кГц)                        
I20SCLL          = 0x50;

VICVectAddr9 = (unsigned)I2CISR; //Настраиваем VIC
VICVectCntl9 = 0x00000008;
VICIntEnable = 1 << 9;     


I2CTransferByte(0xD0,0,4,message);            //write data to the I2C Memory
I2CTransferByte(0xD0,0,0);                //set address to zero
I2CTransferByte(0xD1,0,4,messageIn);        //read back data

UART_PutData         (0, (unsigned char*)&messageIn, 4); //посылаем в уарт0 считанные данные

while(1)
{
;
}
}


void I2CTransferByte(unsigned int I2CAddr,unsigned char MemAddr,unsigned char count,...)
{
va_list ap;
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;
I20CONCLR     = 0x000000FF;                    //Clear all I2C settings
I20CONSET     = 0x00000040;                     //Enable the I2C interface
I20CONSET     = 0x00000020;                     //Start condition
va_end(ap);
}


void I2CISR (void)    __irq                        //I2C interrupt routine
{

switch (I20STAT)                                //Read result code and switch to next action
{
// Start and Send byte conditions

case ( 0x08):                                //Start bit
I20CONCLR     = 0x20;                            //Clear start bit
I20DAT       = I2CAddress;                     //Send address and write bit
break;

case (0x18):                                //Slave address+W, ACK
I20DAT       = MemAddress;                    //Write Mem,ory start address to tx register
break;

case (0x20):                                //Salve address +W, Not ACK
I20DAT       = I2CAddress;                     //Resend address and write bi
break;

case (0x28):
if(I2Counter-->0)                                //Data sent, Ack
{
I20DAT       = *I2CData;                        //Write data to tx register
I2CData++;
}
else
{
I20CONSET     = 0x10;                            //Stop condition
lock = 0;                                   //Signal end of I2C activity
}
break;

case (0x30)    :                                //Data sent, NOT Ack
I20DAT       = *I2CData;                        //Write data to tx register
break;


//Receive byte conditions

case (0x40) :                                //Slave Address +R, ACK
I20CONSET     = 0x04;                            //Enable ACK for data byte
break;

case (0x48) :                                //Slave Address +R, Not Ack
I20CONSET     = 0x20;                            //Resend Start condition
break;

case (0x50) :                                //Data Received, ACK
if(--I2Counter>0)
{
*I2CData     = I20DAT;
I2CData++;
}
else
{
I20CONSET     = 0x10;                            //Stop condition
lock         = 0;                            //Signal end of I2C activity                            
}
break;

case (0x58):                                //Data Received, Not Ack
I20CONSET     = 0x20;                            // Resend Start condition
break;

default :
break;

}

I20CONCLR     = 0x08;                            //Clear I2C interrupt flag
VICVectAddr = 0x00000000;                    //Clear interrupt in
Alex03
Какието странные у Вас выравнивания кода....
А SCL/SDA резюками подтянуты?
как минимум переменная lock должна быть хотя бы volatile.
Oleg-K
Цитата
А SCL/SDA резюками подтянуты?

да, подтянуты внешними резисторами 4.7 кОм

Цитата
как минимум переменная lock должна быть хотя бы volatile.

исправил, но ситуацию это не меняет... Может еще что-то не так?
Alex03
Цитата(Oleg-K @ Aug 5 2008, 10:31) *
да, подтянуты внешними резисторами 4.7 кОм
исправил, но ситуацию это не меняет... Может еще что-то не так?

Зажигание включил? Бензонасос пашет? Искра при прокрутке есть?
Что не работает то?
Qwertty
Странная конструкция. Например это:
Код
case (0x20):                                //Salve address +W, Not ACK
I20DAT       = I2CAddress;                     //Resend address and write bi
break;

Если слейв не опознал свой адрес, или его вообще нет/поломался , то будем вечно долбить шину этим адресом. А в основном потоке также вечно ожидать завершения.
Код
case (0x30)    :                                //Data sent, NOT Ack
I20DAT       = *I2CData;                        //Write data to tx register
break;

Тоже интересный подход - если слейв не может принимать данные, надо его ими закидать по самые помидоры... Причем тоже без конца...
Почитайте про шину I2C, там ничего сложного нет.
Oleg-K
Всем спасибо, проблема решена. Ошибка была в другом модуле)
2 Qwertty: Ваши замечания учту.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.