por j.silvestre » 07 Mar 2008 08:32
olá..
estou postando o código da serial + I2C for lpc2148. só falta por um buffer para receber os dados na rotina de interrupção. A rotina da serial funciona redonda, mas por algum motivo não simula no keil.
I2C preparada para ler e escrever eeprom 24LC512.
sds
j.silvestre
-----------------------------------------------------------------------------------------
/********************************************************************************************/
/* INCLUDES */
/********************************************************************************************/
#include <LPC214x.H>
/*********************************************************************************************/
/* PROTOTYPE FUNCTIONS */
/*********************************************************************************************/
void I2CISR (void) __irq ; //I2C interrupt routine
void UART_1_INTVectoredIRQ (void)__irq;
int sendchar (char *dat);
void init_PLL_VPB(void);
void config_Uart1_9k(void);
void initI2C0(void);
void write_eeprom(unsigned char write,unsigned short MemAddr, unsigned char Counter);
void read_eeprom(unsigned char read,unsigned short MemAddr, unsigned char Counter);
/*********************************************************************************************/
/* GLOBAL VARIAVEIS */
/*********************************************************************************************/
unsigned char dado[13] ;// dados s serem gravados na eeprom //
char dado_in[10] ={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x42}; // buffer que vai guardar
// valores lidos //
unsigned char mybtnum,
I2Counter, //quantidade de bytes a ser gravado/lido //
I2CAddress,// endereço da eeprom 0xA0 -> write 0xa1 -> read
MemAddress_high,// endereço da memoria parte alta
MemAddress_low, //endereço da memoria parte baixa
// endereço para 24LC512 tem um range de 0x00 -> 0xFFFF//
lock; // flga que trava até o final da interrupção I2c
struct eeprom // endereço da eprom 00000 -> 65536
{
unsigned char low_byte :8;
unsigned char high_byte :8;
};
union
{
struct eeprom addr; //address.addr_full = 0xaabb
unsigned short addr_full; //address.addr.low_byte = 0xbb
}address; //address.addr.high_byte = 0xaa
/*********************************************************************************************/
/* MAIN */
/********************************************************************************************/
int main(void)
{
//unsigned char n;
mybtnum =0;
lock = 0;
init_PLL_VPB();
config_Uart1_9k();
initI2C0();
// I2CAddress/address eeprom / numero de bytes //
write_eeprom(0xa0,0xAA00,12); //sempre 2 bytes a mais que o read eeprom que é addrhigh e addrlow.
sendchar(" wait...wait...wait..."); // delay para chamar read eeprom .. its necessáry//
read_eeprom(0xa1,0xAA00,10);
sendchar(dado_in); // buffer que armazena os dados lidos da eeprom //
while(1){} // loop infinito //
}
/********************************************************************************************/
/* write_eeprom */
/* "write" comando para escrever na eeprom */
/* "MemAddr" endereço da memória 24LC512 composto de 16 bits */
/* "Counter" quantidade de caracteres que ira ser escrito na eeprom. (Counter -2) igual */
/* quantidade de caracteres a ser escriro, pois a posição dado[0] e dado[1] contem os */
/* os endereços msb e lsb da eeprom 24LC512. */
/********************************************************************************************/
void write_eeprom(unsigned char write,unsigned short MemAddr, unsigned char Counter)
{
lock = 0; // flag de controle do fim da interrupção//
mybtnum = 0x00; // index do buffer de escrita e leitura //
I2CAddress = write; // endereço da eeprom + R/W
address.addr_full = MemAddr;// endereço da memoria de 16 bits //
I2Counter = Counter; // controla a quantidade de bytes a ser escritos ou lidos
dado [0] = address.addr.high_byte; // enderço high da eeprom
dado [1] = address.addr.low_byte; // endereço low da eeprom
dado [2] = 'A';
dado [3] = 'B'; // buffer dos dados a serem escritos //
dado [4] = 'C';
dado [5] = 'D';
dado [6] = 'E';
dado [7] = '$';
dado [8] = 'G';
dado [9] = 'H';
dado [10] = '*';
dado [11] = 'J';
//dado [12] = '*';
I2C0CONSET = 0x20; // //Start bit
while(!lock); // aguarda fim da interrupção SI //
}
/*********************************************************************************************/
/* */
/*********************************************************************************************/
void read_eeprom(unsigned char read,unsigned short MemAddr, unsigned char Counter)
{
lock = 0;
I2CAddress = 0xa0; // escrever na eeprom
address.addr_full = MemAddr;
I2Counter =2 ;
dado [0] = address.addr.high_byte; // escreve os endereços high e low na eeprom
dado [1] = address.addr.low_byte;
mybtnum = 0x00; // controla a quantidade de bytes escritos ou lidos //
I2C0CONSET = 0x20; // //Start bit
while(!lock); // aguarda o fim da interrupção SI //
I2CAddress = 0xa1; // ler a eeprom
I2Counter =Counter ; //quantidade de bytes a ser escritos ou lidos //
mybtnum = 0;
lock = 0; // flag que controla o fim da interrupção.
I2C0CONSET = 0x20; // //Start bit
while(!lock); // aguarda fim da interrupção//
}
/*******************************************************************************************/
/* */
/* */
/*******************************************************************************************/
void I2CISR (void) __irq //I2C interrupt routine
{
switch (I2C0STAT) //Read result code and switch to next action
{
// Start and Send byte conditions
case ( 0x08): // Start bit ok //
sendchar ("CASE 08 "); //*for debug*//
I2C0CONCLR = 0x20; //Clear start bit
I2C0DAT = I2CAddress; //Send address and write bit
break;
case (0x18): //Slave address + W Ok.
sendchar ("CASE 18 "); //*for debug*//
I2C0DAT = dado[mybtnum]; // primeiro byte do buffer a ser escrito na eeprom
mybtnum ++; // posição do byte no buffer // neste caso endereço a eprom parte high
I2Counter--; // quantidade de bytes a ser enviadas
break;
case (0x20): //Slave address +W, Not ACK
sendchar ("CASE 20 "); //*for debug*//
I2C0CONSET = 0x14; // send stop (error)
break;
case (0x28):
sendchar ("CASE 28 "); //*for debug*//
if(I2Counter > 0) //Data sent, Ack
{
lock = 0;
I2C0DAT = dado[mybtnum]; //Write data to tx register
mybtnum ++;
I2Counter--;
}
else
{
lock = 1;
I2C0CONSET = 0x14; //*** //Stop condition
sendchar ("stop condition "); //*for debug*//
}
break;
case (0x30) :
sendchar ("CASE 30 "); //Data sent, NOT Ack
I2C0CONSET = 0x10; //Stop condition
break;
//Receive byte conditions
case (0x40) : //Slave Address +R, ACK
sendchar ("CASE 40 "); //*for debug*//
I2C0CONSET = 0x04; //Enable ACK for data byte
break;
case (0x48) : //Slave Address +R, Not Ack
sendchar ("CASE 48 "); //*for debug*//
I2C0CONSET = 0x14; //send stop
break;
case (0x50) : //Data Received, ACK
sendchar ("CASE 50 "); //*for debug*//
if(I2Counter > 0)
{
dado_in[mybtnum] = I2C0DAT;
mybtnum ++;
I2Counter--;
}
else
{
I2C0CONSET = 0x10;
lock = 1; //Stop condition
sendchar ("stop ok "); //*for debug*//
}
break;
case (0x58):
sendchar ("CASE 58 "); //Data Received, Not Ack
I2C0CONSET = 0x10; // Send Stop
sendchar ("stop error "); //*for debug*//
break;
default :
break;
}
I2C0CONCLR = 0x08; //Clear I2C interrupt flag
VICVectAddr = 0x00000000; //Clear interrupt in
}
/********************************************************************************************/
/* config_Uart1(void) 9k */
/********************************************************************************************/
void config_Uart1_9k(void)
{
PINSEL0 = 0x00050000; /* Enable RxD1 and TxD1 */
U1LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
U1DLL = 0xC3; /* 9600 Baud Rate @ 30MHz VPB Clock */
//U1DLL = 0X61; /*19200 Baud Rate @ 30MHz VPB Clock */
//U1DLL = 0X20; /*57600 Baud Rate @ 30MHz VPB Clock */
U1LCR = 0x03; /* DLAB = 0 */
U1IER = 0x02; // habilita uart receiver/;/
VICVectAddr2 = (unsigned) UART_1_INTVectoredIRQ; //pass the address of the IRQ into the VIC slot
VICVectCntl2 = 0X00000027;
VICIntEnable = 0X00000080; // habilita interrupção UART1 //
}
/********************************************************************************************/
/* UART_1_INTVectoredIRQ (void)__irq */
/* Recebe um Byte e armazena em um buffer */
/* Funciona da seguinte maneira: enche o primeiro buffer, transfere para serial, e começa a */
/* encher o segundo, qdo cheio envia para a serial, depois o terceiro buffer e envia para a */
/* serial , então volta ao primeiro buffer. */
/********************************************************************************************/
void UART_1_INTVectoredIRQ (void)__irq // for debug I2c
{
while (!(U1LSR & 0x01));
VICVectAddr = 0;//0x0000; // limpa interrupção //
}
/*********************************************************************************************/
/* sendchar Write character to Serial Port */
/*********************************************************************************************/
int sendchar (char *dat) // for debug I2C
{ /* Write character to Serial Port */
int j=0;
// if( dat ==0x00) return;
while(dat[j]) // send string
{
// start sending one byte
while (!(U1LSR & 0x20));
U1THR=dat[j];
j++;
if( j == 10) // tamanho do buffer a ser lido //
return (U1THR );
}
return (U1THR );
}
/*********************************************************************************************/
/* void init_PLL_VPB(void) */
/* */
/********************************************************************************************/
void init_PLL_VPB(void)
{
PLL0CFG = 0x00000024; // configura o multiplicador e o divisor para 60MHZ ->cristal de 12MHZ
PLL0CON = 0x00000001; // habilita o PLL //
PLL0FEED = 0x000000AA; // atualiza os registradores
PLL0FEED = 0x00000055; // atualiza os registradores
while(!(PLL0STAT & 0x00000400)); // testa PCLOCK
PLL0CON = 0x00000003; // conecta ao PLL //
PLL0FEED = 0x000000AA; // atualiza os registradores
PLL0FEED = 0x00000055; // atualiza os registradores
VPBDIV = 0x00000002; // configura o divisor VPB para 30MHZ.
// CCLK /2
}
void initI2C0(void)
{
VICVectCntl1 = 0x00000029; //select a priority slot for a given interrupt
VICVectAddr1 = (unsigned)I2CISR; //pass the address of the IRQ into the VIC slot
VICIntEnable = 0x00000200; //enable interrupt
PINSEL0 |= 0x50; //Switch GPIO to I2C pins
I2C0SCLH = 0x96; // for 100khz
I2C0SCLL = 0x96;
I2C0CONSET = 0x40;
}
--------------------------------------------------------------------------------------
sds
j.silvestre