0
\$\begingroup\$

I programmed UART3 peripheral on LPC4088 to send a single unsigned character posiljka over Tx line. This is done by continuously copying this character into the Transmitter Holding Register (THR) which is the top of the transmitter FIFO.

So I connected my oscilloscope to the Tx line and tried to sent these characters over while recording their oscilloscope images:

0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x25, 0x26.

Oscilloscope images looked fine at the beginning, but once I reached values 0x20, 0x21, 0x22, 0x23, 0x25, 0x26 I noticed that oscilloscope images for these characters look the same than those for images 0x00, 0x01, 0x02, 0x03, 0x04, 0x05. How is this possible? Here is the compressed folder with all the images (please don't pay attention to measured frequency which is wrong as oscilloscope takes wrong edges to measure it).

My C program was supposed to set UART3 communication to be 9600 8N1 which means 9600 baud rate, 8-bit character length, no parity and 1 stop bit but width of the sent character looks two times shorter to me from the beginning.

Here is the program:

#define IOCON_P0_0      (*((volatile unsigned int *) 0x4002C000))
#define IOCON_P0_1      (*((volatile unsigned int *) 0x4002C004))

#define PCONP           (*((volatile unsigned int *) 0x400FC0C4))

#define THR             (*((volatile unsigned int *) 0x4009C000))
#define DLL             (*((volatile unsigned int *) 0x4009C000))
#define DLM             (*((volatile unsigned int *) 0x4009C004))
#define LCR             (*((volatile unsigned int *) 0x4009C00C))
#define LSR             (*((volatile unsigned int *) 0x4009C014))
#define FDR             (*((volatile unsigned int *) 0x4009C028))



int main(){


    //we use UART3 on pins P0.0 and P0.1 with on-chip and external pullup-resistors
    //we set P0.0 and P0.1 as U3_TXD and U3_RXD, no-pullup, no-hysteresis, no-inversion, standard-mode, open-drain (0b0100000xx00xx...)
    IOCON_P0_0 &= !(0x67F);
    IOCON_P0_0 |= (1<<1);
    IOCON_P0_1 &= !(0x67F);
    IOCON_P0_1 |= (1<<1);

    //we turn on UART3
    PCONP |= (1<<25);

    //we set 8N1 communication in LCR (we only have to set first 2 bits because rest is already set properly by default) 
    //we also set LCR.DLAB = 1 so that we can aces DLL and DLM in next paragraph
    LCR |= (0b11);
    LCR &= !(0b0011111);
    LCR |= (1<<7);

    //we set DLL[0-7] = 96 and DLM[0-7] = 0 which sets baud rate to 9600 - check referenced user manual, page 510.
    //we don't need to manipulate FDR register as DIVADDVAL=0 and MULVAL=1 are already set ok by default - check referenced user manual, page 510.
    DLL |= 0x96;
    DLM |= 0x0;

    //we set LCR.DLAB = 0 back to original value and can now acess THR
    LCR &= !(1<<7);

    //we enable Rx and Tx FIFO
    FCR |= 0b1;


    while(1){

        //here is where we set the character to be sent
        unsigned char posiljka = (0x25);

        //we input character "posiljka" into THR and send it.
        THR = posiljka;

    }
}

Am I missing anything?

\$\endgroup\$
8
  • 1
    \$\begingroup\$ The standard initial test pattern for any UART transmitter is 'U', which is 0x55. On a scope, at 8N1, it looks like a square wave. \$\endgroup\$ Commented Dec 28, 2015 at 19:40
  • \$\begingroup\$ Could you explain a bit. I am completely new to UART. \$\endgroup\$
    – 71GA
    Commented Dec 28, 2015 at 19:43
  • 2
    \$\begingroup\$ Start by replacing the Logical NOT operator "!" by the binary complement operator "~" in your "inverse" operations. !(0) -> true -> often implemented as 1, !(any other number) -> false -> often implemented as 0. \$\endgroup\$
    – Asmyldof
    Commented Dec 28, 2015 at 20:05
  • 1
    \$\begingroup\$ If you were asking why 'U' was the test pattern, 0x55 in binary is 01010101. 0x55 and 0xAA (10101010) are commonly used as test patterns as they maximize transitions on a data line. \$\endgroup\$ Commented Dec 28, 2015 at 20:29
  • 1
    \$\begingroup\$ This may not affect your immediate problem, but you should normally check that THR is empty (ready for new data) before writing new data to it. The processor can write to THR much faster than the UART can read data from it. \$\endgroup\$ Commented Dec 28, 2015 at 20:30

2 Answers 2

4
\$\begingroup\$

The ! operator in C is a logical operator and it produces a result which is either true (1) or false (0).

You seem to be looking for the bitwise NOT operator which is ~, not !

The result of !(0b0011111) is simply 0 (or 0b0000000 or 0x00 or however you want to represent it), while the result of ~(0b00111111) is 0b11000000.

Even if you correct this, you still have code which appears to 'contradict' itself.
You have LCR |= (0b11); which sets the least-significant 2 bits of your LCR register, and then on the next line you have LCR &= !(0b0011111); (and I'm assuming you meant ~ and not !) which immediately clears those 2 bits.

\$\endgroup\$
2
  • \$\begingroup\$ Too lazy to write it as a full answer while eating dinner, you posted this almost concurrently with my comment :-) \$\endgroup\$
    – Asmyldof
    Commented Dec 28, 2015 at 20:08
  • 1
    \$\begingroup\$ I tested it and it works now. \$\endgroup\$
    – 71GA
    Commented Dec 28, 2015 at 20:31
1
\$\begingroup\$

Take another look at these lines.

//we set 8N1 communication in LCR (we only have to set first 2 bits because rest is already set properly by default) 
//we also set LCR.DLAB = 1 so that we can aces DLL and DLM in next paragraph
LCR |= (0b11);
LCR &= !(0b0011111);
LCR |= (1<<7);

It looks to me at first glance as though the second line wipes out the effects of the first one, with the result that you are probably selecting 5 bits per character, not 8. There are times when you are better off calculating the magic value in hex by hand, and just plugging it into the register in one blast.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ In fact, the second line wipes out everything that happened, since ! is the logical operator, not the binary operator and NOT(0b0011111) == NOT(true) in C, which is False, which is most commonly implemented as 0 \$\endgroup\$
    – Asmyldof
    Commented Dec 28, 2015 at 20:04
  • \$\begingroup\$ But if I fixed second line in LCR &= ~(0b0011111); it wouldn't wipe out the effect of the LCR |= (0b11); because it wouldn't affect the states of bits 0 and 1. Right? \$\endgroup\$
    – 71GA
    Commented Dec 28, 2015 at 20:16
  • \$\begingroup\$ I tested it and it works now. \$\endgroup\$
    – 71GA
    Commented Dec 28, 2015 at 20:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.