UART is acting weird

clpcnxposcilloscopeuart

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?

Best Answer

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.

Related Topic