I'm having a problem with getting UART1 to work on my Embedded Artists prototype board. I have a serial display that has only 1 serial line. In other words, you can only transmit to the display. I can't get P0.8 (UART1 TX) to send any data. Here is my setup at 9600. And, another question is 'Do I really need an interrupt just to transmit? It seems like throwing a char out to U1THR should suffice. It's probably something simple I'm missing. Thanks. Sutton - dodge55 VICIntSelect = 0; VICVectAddr2 = (unsigned int) uart1_out; VICVectCntl2 = 0x20 | 7; // enables the UART1 interrupt, slot 7 U1FDR = 0x00000010; // MULVAL = 1, DIVVAL = 0 U1DLM = 0; U1DLL = 0x48; // 9600 baud U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0 U1FCR = 1; VICIntEnable |= 0x00000080; void display_write(char text[]) { unsigned char i; sprintf(display_output, "%s", text); for (i = 0; i < strlen(display_output); i++) { my_putchar(display_output[i]); } } void my_putchar(char c) { U1THR = c; } void uart1_out(void) __irq { VICVectAddr = 0; }
UART1 for LPC2148
Started by ●February 24, 2006
Reply by ●February 24, 20062006-02-24
dodge1955 wrote: > I'm having a problem with getting UART1 to work on my Embedded Artists > prototype board. I have a serial display that has only 1 serial line. > In other words, you can only transmit to the display. I can't get > P0.8 (UART1 TX) to send any data. Here is my setup at 9600. And, You need to set bit 7 (DLAB) of the LCR before setting the divider. > another question is 'Do I really need an interrupt just to transmit? > It seems like throwing a char out to U1THR should suffice. It's > probably something simple I'm missing. Thanks. No, I think you don't need an interrupt. Another thing, although the bit for UART1 in the PCONP register is supposed to default to 1, I would verify that it is _really_ set. > > Sutton - dodge55 > > > VICIntSelect = 0; > VICVectAddr2 = (unsigned int) uart1_out; > VICVectCntl2 = 0x20 | 7; // enables the UART1 interrupt, slot 7 > U1FDR = 0x00000010; // MULVAL = 1, DIVVAL = 0 > U1DLM = 0; > U1DLL = 0x48; // 9600 baud > U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0 > U1FCR = 1; > VICIntEnable |= 0x00000080; > > void display_write(char text[]) > { > unsigned char i; > > sprintf(display_output, "%s", text); > for (i = 0; i < strlen(display_output); i++) > { > my_putchar(display_output[i]); > } > } > > void my_putchar(char c) > { > U1THR = c; > } I think it would be wise to check if the UART is able to accept the character. You can do this by checking that bit 5 or 6 of the LSR. > > void uart1_out(void) __irq > { > VICVectAddr = 0; > } Regards, Bertrik
Reply by ●February 24, 20062006-02-24
Sutton: try making sure you have room in the transmit buffer before sending a character: void my_putchar(char c) { while(!(U0LSR & 0x20)); U0THR = c; } This is my setup code: PCONP |= PCONP_PCUART0; PINSEL0 = (PINSEL0 & 0xfffffffc) | 0x00000001; // TX only U0LCR = 0x83; // 8 bits, no Parity, 1 Stop bit, DLAB = 1 U0DLL = UART0_DIV_LOW; U0DLM = UART0_DIV_HIGH; U0LCR = 0x03; // DLAB = 0 U0IER = 0x00; // No interrupts U0FCR = 0x01; // Use FIFO U0TER = 0x80; // Transmitter enabled Hope this helps. Guille --- In lpc2000@lpc2..., Bertrik Sikken <bertrik@...> wrote: > > dodge1955 wrote: > > I'm having a problem with getting UART1 to work on my Embedded Artists > > prototype board. I have a serial display that has only 1 serial line. > > In other words, you can only transmit to the display. I can't get > > P0.8 (UART1 TX) to send any data. Here is my setup at 9600. And, > > You need to set bit 7 (DLAB) of the LCR before setting the > divider. > > > another question is 'Do I really need an interrupt just to transmit? > > It seems like throwing a char out to U1THR should suffice. It's > > probably something simple I'm missing. Thanks. > > No, I think you don't need an interrupt. > > Another thing, although the bit for UART1 in the PCONP register > is supposed to default to 1, I would verify that it is > _really_ set. > > > > > Sutton - dodge55 > > > > > > VICIntSelect = 0; > > VICVectAddr2 = (unsigned int) uart1_out; > > VICVectCntl2 = 0x20 | 7; // enables the UART1 interrupt, slot 7 > > U1FDR = 0x00000010; // MULVAL = 1, DIVVAL = 0 > > U1DLM = 0; > > U1DLL = 0x48; // 9600 baud > > U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0 > > U1FCR = 1; > > VICIntEnable |= 0x00000080; > > > > void display_write(char text[]) > > { > > unsigned char i; > > > > sprintf(display_output, "%s", text); > > for (i = 0; i < strlen(display_output); i++) > > { > > my_putchar(display_output[i]); > > } > > } > > > > void my_putchar(char c) > > { > > U1THR = c; > > } > > I think it would be wise to check if the UART is able to accept the > character. You can do this by checking that bit 5 or 6 of the LSR. > > > > > void uart1_out(void) __irq > > { > > VICVectAddr = 0; > > } > > Regards, > Bertrik >
Reply by ●February 24, 20062006-02-24
Bertrik and Guille,
Here is my new code. Still doesn't work right. I've even tweaked the
MULVAL and DIVVAL numbers to better match the 12Mhz at 9600 baud. It
doesn't come out perfect with a 12Mhz clock. P0.8 blinks like mad,
but still no data out on 9600 PROCOMM. PROCOMM works great directly
to my 9600 baud display. But can't get it to work thru the 2148
chip's UART1. Am I still missing something?
Sutton - dodge55
PINSEL0 |= 0x00010000;
PCONP |= 0x00000010;
U1FDR = 0x0000009A; // MULVAL = 9, DIVVAL = 10
U1LCR = 0x83; // enable Divisor Latches
U1DLM = 0;
U1DLL = 0x25; // 9601.71 baud
U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0
U1FCR = 1;
U1TER = 0x80;
U1IER = 0;
void my_putchar(char c)
{
if ((U1LSR & 0x20) != 0) // TX buffer empty
{
U1THR = c;
}
}
void display_write(char text[])
{
unsigned char i;
sprintf(display_output, "%s", text);
for (i = 0; i < strlen(display_output); i++)
{
my_putchar(display_output[i]);
}
}
--- In lpc2000@lpc2..., "dodge1955" <sutton@...> wrote:
>
> I'm having a problem with getting UART1 to work on my Embedded Artists
> prototype board. I have a serial display that has only 1 serial line.
> In other words, you can only transmit to the display. I can't get
> P0.8 (UART1 TX) to send any data. Here is my setup at 9600. And,
> another question is 'Do I really need an interrupt just to transmit?
> It seems like throwing a char out to U1THR should suffice. It's
> probably something simple I'm missing. Thanks.
>
> Sutton - dodge55
>
>
> VICIntSelect = 0;
> VICVectAddr2 = (unsigned int) uart1_out;
> VICVectCntl2 = 0x20 | 7; // enables the UART1 interrupt, slot 7
> U1FDR = 0x00000010; // MULVAL = 1, DIVVAL = 0
> U1DLM = 0;
> U1DLL = 0x48; // 9600 baud
> U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0
> U1FCR = 1;
> VICIntEnable |= 0x00000080;
>
> void display_write(char text[])
> {
> unsigned char i;
>
> sprintf(display_output, "%s", text);
> for (i = 0; i < strlen(display_output); i++)
> {
> my_putchar(display_output[i]);
> }
> }
>
> void my_putchar(char c)
> {
> U1THR = c;
> }
>
> void uart1_out(void) __irq
> {
> VICVectAddr = 0;
> }
>
Reply by ●February 24, 20062006-02-24
I think the baudrate is incorrect.
The divisor that you're using now does not make sense to me
(looks like a bug in the baudrate calculation program).
Try 78 for U1DLL (calculated from PCLK/(16*baudrate))
and set U1FDR to 0.
Bertrik
dodge1955 wrote:
> Bertrik and Guille,
>
> Here is my new code. Still doesn't work right. I've even
tweaked the
> MULVAL and DIVVAL numbers to better match the 12Mhz at 9600 baud. It
> doesn't come out perfect with a 12Mhz clock. P0.8 blinks like mad,
> but still no data out on 9600 PROCOMM. PROCOMM works great directly
> to my 9600 baud display. But can't get it to work thru the 2148
> chip's UART1. Am I still missing something?
>
> Sutton - dodge55
>
> PINSEL0 |= 0x00010000;
> PCONP |= 0x00000010;
> U1FDR = 0x0000009A; // MULVAL = 9, DIVVAL = 10
> U1LCR = 0x83; // enable Divisor Latches
> U1DLM = 0;
> U1DLL = 0x25; // 9601.71 baud
> U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0
> U1FCR = 1;
> U1TER = 0x80;
> U1IER = 0;
>
>
>
> void my_putchar(char c)
> {
> if ((U1LSR & 0x20) != 0) // TX buffer empty
> {
> U1THR = c;
> }
> }
>
> void display_write(char text[])
> {
> unsigned char i;
>
> sprintf(display_output, "%s", text);
> for (i = 0; i < strlen(display_output); i++)
> {
> my_putchar(display_output[i]);
> }
> }
>
>
>
>
>
>
> --- In lpc2000@lpc2..., "dodge1955" <sutton@...> wrote:
>>
>> I'm having a problem with getting UART1 to work on my Embedded
Artists
>> prototype board. I have a serial display that has only 1 serial line.
>> In other words, you can only transmit to the display. I can't
get
>> P0.8 (UART1 TX) to send any data. Here is my setup at 9600. And,
>> another question is 'Do I really need an interrupt just to
transmit?
>> It seems like throwing a char out to U1THR should suffice. It's
>> probably something simple I'm missing. Thanks.
>>
>> Sutton - dodge55
>>
>>
>> VICIntSelect = 0;
>> VICVectAddr2 = (unsigned int) uart1_out;
>> VICVectCntl2 = 0x20 | 7; // enables the UART1 interrupt, slot 7
>> U1FDR = 0x00000010; // MULVAL = 1, DIVVAL = 0
>> U1DLM = 0;
>> U1DLL = 0x48; // 9600 baud
>> U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0
>> U1FCR = 1;
>> VICIntEnable |= 0x00000080;
>>
>> void display_write(char text[])
>> {
>> unsigned char i;
>>
>> sprintf(display_output, "%s", text);
>> for (i = 0; i < strlen(display_output); i++)
>> {
>> my_putchar(display_output[i]);
>> }
>> }
>>
>> void my_putchar(char c)
>> {
>> U1THR = c;
>> }
>>
>> void uart1_out(void) __irq
>> {
>> VICVectAddr = 0;
>> }
Reply by ●February 24, 20062006-02-24
This code just discards bytes when the FIFO's full! if ((U1LSR & 0x20) != 0) // TX buffer empty { U1THR = c; } You should do this instead: while(!(U1LSR & 0x20)); U1THR = c; Mind the semi-colon after the while. You can reword it like this: while( (U0LSR & 0x20) == 0x00 ) { // Do nothing but wait } U0THR = c; Guille --- In lpc2000@lpc2..., "dodge1955" <sutton@...> wrote: > > Bertrik and Guille, > > Here is my new code. Still doesn't work right. I've even tweaked the > MULVAL and DIVVAL numbers to better match the 12Mhz at 9600 baud. It > doesn't come out perfect with a 12Mhz clock. P0.8 blinks like mad, > but still no data out on 9600 PROCOMM. PROCOMM works great directly > to my 9600 baud display. But can't get it to work thru the 2148 > chip's UART1. Am I still missing something? > > Sutton - dodge55 > > PINSEL0 |= 0x00010000; > PCONP |= 0x00000010; > U1FDR = 0x0000009A; // MULVAL = 9, DIVVAL = 10 > U1LCR = 0x83; // enable Divisor Latches > U1DLM = 0; > U1DLL = 0x25; // 9601.71 baud > U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0 > U1FCR = 1; > U1TER = 0x80; > U1IER = 0; > > > > void my_putchar(char c) > { > if ((U1LSR & 0x20) != 0) // TX buffer empty > { > U1THR = c; > } > } > > void display_write(char text[]) > { > unsigned char i; > > sprintf(display_output, "%s", text); > for (i = 0; i < strlen(display_output); i++) > { > my_putchar(display_output[i]); > } > } > > > > > > > --- In lpc2000@lpc2..., "dodge1955" <sutton@> wrote: > > > > I'm having a problem with getting UART1 to work on my Embedded Artists > > prototype board. I have a serial display that has only 1 serial line. > > In other words, you can only transmit to the display. I can't get > > P0.8 (UART1 TX) to send any data. Here is my setup at 9600. And, > > another question is 'Do I really need an interrupt just to transmit? > > It seems like throwing a char out to U1THR should suffice. It's > > probably something simple I'm missing. Thanks. > > > > Sutton - dodge55 > > > > > > VICIntSelect = 0; > > VICVectAddr2 = (unsigned int) uart1_out; > > VICVectCntl2 = 0x20 | 7; // enables the UART1 interrupt, slot 7 > > U1FDR = 0x00000010; // MULVAL = 1, DIVVAL = 0 > > U1DLM = 0; > > U1DLL = 0x48; // 9600 baud > > U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0 > > U1FCR = 1; > > VICIntEnable |= 0x00000080; > > > > void display_write(char text[]) > > { > > unsigned char i; > > > > sprintf(display_output, "%s", text); > > for (i = 0; i < strlen(display_output); i++) > > { > > my_putchar(display_output[i]); > > } > > } > > > > void my_putchar(char c) > > { > > U1THR = c; > > } > > > > void uart1_out(void) __irq > > { > > VICVectAddr = 0; > > } > > >
Reply by ●February 24, 20062006-02-24
Oops, after a closer look, your U1FDR and U1DLM/DLL settings
appear to be correct. Sorry about the confusion.
Bertrik
Bertrik Sikken wrote:
> I think the baudrate is incorrect.
> The divisor that you're using now does not make sense to me
> (looks like a bug in the baudrate calculation program).
> Try 78 for U1DLL (calculated from PCLK/(16*baudrate))
> and set U1FDR to 0.
>
> Bertrik
>
> dodge1955 wrote:
>> Bertrik and Guille,
>>
>> Here is my new code. Still doesn't work right. I've even
tweaked the
>> MULVAL and DIVVAL numbers to better match the 12Mhz at 9600 baud. It
>> doesn't come out perfect with a 12Mhz clock. P0.8 blinks like
mad,
>> but still no data out on 9600 PROCOMM. PROCOMM works great directly
>> to my 9600 baud display. But can't get it to work thru the 2148
>> chip's UART1. Am I still missing something?
>>
>> Sutton - dodge55
>>
>> PINSEL0 |= 0x00010000;
>> PCONP |= 0x00000010;
>> U1FDR = 0x0000009A; // MULVAL = 9, DIVVAL = 10
>> U1LCR = 0x83; // enable Divisor Latches
>> U1DLM = 0;
>> U1DLL = 0x25; // 9601.71 baud
>> U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0
>> U1FCR = 1;
>> U1TER = 0x80;
>> U1IER = 0;
>>
>>
>>
>> void my_putchar(char c)
>> {
>> if ((U1LSR & 0x20) != 0) // TX buffer empty
>> {
>> U1THR = c;
>> }
>> }
>>
>> void display_write(char text[])
>> {
>> unsigned char i;
>>
>> sprintf(display_output, "%s", text);
>> for (i = 0; i < strlen(display_output); i++)
>> {
>> my_putchar(display_output[i]);
>> }
>> }
>>
>>
>>
>>
>>
>>
>> --- In lpc2000@lpc2..., "dodge1955" <sutton@...> wrote:
>>>
>>> I'm having a problem with getting UART1 to work on my Embedded
Artists
>>> prototype board. I have a serial display that has only 1 serial
line.
>>> In other words, you can only transmit to the display. I
can't get
>>> P0.8 (UART1 TX) to send any data. Here is my setup at 9600. And,
>>> another question is 'Do I really need an interrupt just to
transmit?
>>> It seems like throwing a char out to U1THR should suffice.
It's
>>> probably something simple I'm missing. Thanks.
>>>
>>> Sutton - dodge55
>>>
>>>
>>> VICIntSelect = 0;
>>> VICVectAddr2 = (unsigned int) uart1_out;
>>> VICVectCntl2 = 0x20 | 7; // enables the UART1 interrupt, slot 7
>>> U1FDR = 0x00000010; // MULVAL = 1, DIVVAL = 0
>>> U1DLM = 0;
>>> U1DLL = 0x48; // 9600 baud
>>> U1LCR = 0x03; // 8 bits, 1 stop, no parity, DLAB = 0
>>> U1FCR = 1;
>>> VICIntEnable |= 0x00000080;
>>>
>>> void display_write(char text[])
>>> {
>>> unsigned char i;
>>>
>>> sprintf(display_output, "%s", text);
>>> for (i = 0; i < strlen(display_output); i++)
>>> {
>>> my_putchar(display_output[i]);
>>> }
>>> }
>>>
>>> void my_putchar(char c)
>>> {
>>> U1THR = c;
>>> }
>>>
>>> void uart1_out(void) __irq
>>> {
>>> VICVectAddr = 0;
>>> }
Reply by ●February 24, 20062006-02-24
Hi Sutton,
> I'm having a problem with getting UART1 to
work on my Embedded Artists
> prototype board. I have a serial display that has only 1 serial line.
> In other words, you can only transmit to the display. I can't get
> P0.8 (UART1 TX) to send any data. Here is my setup at 9600. And,
> another question is 'Do I really need an interrupt just to transmit?
> It seems like throwing a char out to U1THR should suffice. It's
> probably something simple I'm missing. Thanks.
Below is code to implement 115200 baud at any peripheral clock frequency
based on 12MHz with lowest % error. All items have been tested, and numbers
were derived from my utility. This concept can be applied for any
peripheral clock or baud rate. When I have some time I will create defines
for all standard baud rates for lowest % error.
To transmit character out of UART no interrupts are required. Just write
the character to the UART_THR after initializing UART.
Unrelated but important when using LPC214x and USB peripheral, it states in
manual core clock must run at a minimum of 18MHz.
Joel
/*
****************************************************************
* UART w/fraction divider register values for lowest % error
****************************************************************
*/
#define BAUDRATE 115200L
#if (PCLK_UART=`MHZ)
#define UART_DLM 0
#define UART_DLL 24
#define UART_MULVAL 14
#define UART_DIVADDVAL 5
#elif (PCLK_UART=HMHZ)
#define UART_DLM 0
#define UART_DLL 23
#define UART_MULVAL 15
#define UART_DIVADDVAL 2
#elif (PCLK_UART=6MHZ)
#define UART_DLM 0
#define UART_DLL 8
#define UART_MULVAL 9
#define UART_DIVADDVAL 13
#elif (PCLK_UART=0MHZ)
#define UART_DLM 0
#define UART_DLL 12
#define UART_MULVAL 14
#define UART_DIVADDVAL 5
#elif (PCLK_UART=$MHZ)
#define UART_DLM 0
#define UART_DLL 13
#define UART_MULVAL 14
#define UART_DIVADDVAL 0
#elif (PCLK_UART=MHZ)
#define UART_DLM 0
#define UART_DLL 8
#define UART_MULVAL 9
#define UART_DIVADDVAL 2
#elif (PCLK_UART=MHZ)
#define UART_DLM 0
#define UART_DLL 3
#define UART_MULVAL 7
#define UART_DIVADDVAL 12
#elif (PCLK_UART=MHZ)
#define UART_DLM 0
#define UART_DLL 3
#define UART_MULVAL 12
#define UART_DIVADDVAL 14
#elif (PCLK_UART== 9MHZ)
#define UART_DLM 0
#define UART_DLL 2
#define UART_MULVAL 9
#define UART_DIVADDVAL 13
#elif (PCLK_UART== 6MHZ)
#define UART_DLM 0
#define UART_DLL 3
#define UART_MULVAL 12
#define UART_DIVADDVAL 1
#if 0 /* bauds > 38400 are not working with fdr for pclk == 3MHz */
#elif (PCLK_UART== 3MHZ)
#define UART_DLM 0
#define UART_DLL 1
#define UART_MULVAL 8
#define UART_DIVADDVAL 5
#endif
#endif
/*
****************************************************************
* UART Init
****************************************************************
*/
#define _BAUDDIVIDE ((PCLK_UART+BAUDRATE*8L)/(BAUDRATE*16L))
// Setup Port-Mode to alternate function
_PINSEL0 |= _PINSEL_UART_MODE; // Set UART-port to alt func
_PCONP |= (1 << _UART_PCONP_BIT); // Enable UART unit
_UART_IER = 0x00; // Initially disable all interrupts
_UART_LCR = 0x80; // Set DLAB to init Baudrate gen
#ifdef UART_MULVAL // This mcu has fraction divider
_UART_DLM = UART_DLM; // MSB of baud divider
_UART_DLL = UART_DLL; // LSB of baud divider
_UART_FDR = (UART_MULVAL<<4) | UART_DIVADDVAL;
#else
_UART_DLL = (_BAUDDIVIDE & 0xFF);
_UART_DLM = ((_BAUDDIVIDE >> 8) & 0xFF);
#endif
_UART_LCR &= ~0x80; // reset DLAB to lock baudrate gen access
_UART_LCR = 0x03 // 8 data bits
|(0 << 2) // 1 stop bit
|(0 << 3) // NO parity
|(0 << 4) // Parity setting (bit 5:4) does not care
|(0 << 6) // Disable Break transmission
|(0 << 7); // Clear DLAB
// _UART_FCR = 0; // Disable FIFO
_UART_FCR = 3; // Enable FIFO