UART0 interrupt routine with LPC2106

hello,

I know that you are busy or on holidays, but I need your help for a problem with UART0 interrupt routine on an Olimex LPC2106 board.

Below my code:

#include <LPC210x.h>

#define OSCILLATOR_CLOCK_FREQUENCY 14745600 //in MHz

#define CR 0x0D

#define P0_7 0x00000080

void Init_UART0(unsigned int baud);

unsigned int Get_CCLK(void);

unsigned int Get_PCLK(void);

void UART_putc(char ch);

void UART_puts(char *c);

char UART_getc(void);

void Init_Interrupt(void);

void uart0_irq(void);

unsigned int cclk = 0;

unsigned int pclk = 0;

unsigned int divisor = 0;

unsigned int U0IIR_status = 0;

int main(void)

{

Init_Interrupt();

Init_UART0(9600); //Initialize the UART

/*UART_putc(‘q’); // transmission of characters works properly

UART_putc(‘z’);

UART_putc(‘e’);

UART_putc(‘r’);

UART_putc(‘t’);

UART_putc(‘y’);

*/

while(1){ };

return 0;

}

void UART_putc(char ch)

{

while ((U0LSR & 0x20) == 0);

U0THR = ch;

}

void UART_puts(char *c)

{

while (*c)

{

UART_putc(*c);

c++;

}

}

char UART_getc(void) /* Read character from Serial Port */

{

while (!(U0LSR & 0x01));

return (U0RBR);

}

void uart0_irq(void)

{

//check for a character from the UART0 RX FIFO

if((U0LSR & 0x01) == 0x01) //if there is a character

{

IOSET = P0_7; // turn off the LED

}

//exit ISR

U0IIR_status = U0IIR; // clear interrupt

VICVectAddr = 0x00000000;//write to re-enable interrupt for next time

}

void Init_UART0 (unsigned int baud)

{

U0IER = 0x00; // disable all interrupts

U0FCR = 0x07; // enable and reset buffers

divisor = Get_PCLK() / (16 * baud);

U0LCR = 0x83; /* 8 bit, 1 stop bit, no parity, enable DLAB */

U0DLL = divisor & 0xFF;

U0DLM = (divisor >> 8) & 0xFF;

U0LCR &= ~0x80; /* Disable DLAB */

PINSEL0 = 0x00000005; //Enable TxD0, RxD0

IODIR = P0_7;

IOCLR = P0_7; //turn on the LED

U0IER = 0x01; //enable Rx interrupt

}

void Init_Interrupt(void)

{

VICIntSelect = 0x00000000; // use UART0 as IRQ interrupt

VICIntEnable = 0x00000040; // enable UART0 interrupt

VICVectCntl1 = 0x00000026;

VICVectAddr1 = (unsigned)uart0_irq;

}

unsigned int Get_CCLK(void)

{

//return real processor clock speed

return OSCILLATOR_CLOCK_FREQUENCY * (PLLCON & 1 ? (PLLCFG & 0xF) + 1 : 1);

}

unsigned int Get_PCLK(void)

{

//VPBDIV - determines the relationship between the processor clock (cclk)

//and the clock used by peripheral devices (pclk).

unsigned int divider;

switch (VPBDIV & 3)

{

case 0: divider = 4; break;

case 1: divider = 1; break;

case 2: divider = 2; break;

}

return Get_CCLK() / divider;

}

the serial transmission without interrupt works properly, but I want use interrupt with UART0.

The code above must turn off the LED when it receives a character.

Can you tell me what’s wrong with the code, or tell me where I can find examples of UART0 interrupt routine.

thanks for your helps

I forgot to say that I work under Keil compiler and I use Keil adapter ULINK

thanks

You seem to have configured the VIC but …

You do not seem to have turned on Interrupts on the ARM.

Try reading other posts on this forum to find out how !

I saw there is a regiter that specify where interrupt vector must reside, it’s MEMMAP register.

I tryed to put interrupt vector in Flash and in RAM, but it stille doesn’t work. Below my code:

void Init_UART0 (unsigned int baud)

{

U0IER = 0x00;

U0FCR = 0x07; // enable and reset buffers

divisor = Get_PCLK() / (16 * baud);

U0LCR = 0x83; /* 8 bit, 1 stop bit, no parity, enable DLAB */

U0DLL = divisor & 0xFF;

U0DLM = (divisor >> 8) & 0xFF;

U0LCR &= ~0x80; /* Disable DLAB */

PINSEL0 = 0x00000005; //Enable TxD0, RxD0

MEMMAP = 0x02; //interrupt vector reside in RAM

MEMMAP = 0x01 // interrupt vector reside in Flash

IODIR = P0_7;

IOCLR = P0_7; //turn on the LED

U0IER = 0x01; //enable Rx interrupt

}

thanks

hello,

I find out my errors, I forgot to use " __irq" for the interrupt routine, so we get code below:

void uart0_isr(void) __irq;

void uart0_isr(void) __irq

{

UART_putc(‘Y’);

IOSET = P0_7; // turn off the LED

ch = UART_getc();

//exit ISR

VICVectAddr = 0x00000000;//write to re-enable interrupt for next time

U0IIR_status = U0IIR;

}

thanks

Now the Rx interrupt works, I wand to use the Tx interrupt to transmit character.

Do you think it’s a good idea to use it to free the CPU when you have a lot of data to transmit? Because I must use the CPU to make others tasks when it don’t transmit data.

thanks

IMHO this is a good idea, I’m currently using it for some PIC18 application, the way was setting up the data into a buffer and then trigger the interrupt transmission bit to start the transmission of the data through the serial port. Into the interrupt TX routine simply access into the buffer and send all the char one by one, when the last char was transmitted (by using a counter shared from the main and the interrupt routine) simply set off the TX interrupt bits.

In this way you’re free of any transmission stuff and the micro will be free to work in other task than simply wait for the data tx.

Now I’ve also to do same things on my current project on LPC2106 then when I’ve some news I’ll post it for sure.

Bye

Fabio

Ok I’ve keep the UART1 functioning with interrupt, the main things is in transmission.

For serial port reading there is no more to do than install your interrupt handler and keep the character in a sizable buffer.

For transmission I’ve keep this idea (if someone have some nice one plz let me know), first I’ve sized suitable buffer to store the data that I’ve to send then I’ve set the total char to send in a variable.

At the end of the main loop of the microcontroller I check if the char counter is greather than 0. If yes I send one char from the buffer and then return to the main loop. In this way I can take free the microcontroller and send the char when the transmission queue will be free. Because my setting was 9600 bps and the total microcontroller loop take less than 100 us at the maximum core speed (60 MHz) I can sure to send all the data into the latest time.

Well I microchip microcontroller series I’ve take a slighty different approach because I can set some TX interrupt able to call continuously the interrupt routine but in this micro I can’t see a similar stuff.

Regards

Fabio