UART está actuando raro

0

Programé el periférico UART3 en LPC4088 para enviar un solo carácter sin signo posiljka sobre la línea Tx. Esto se hace copiando continuamente este carácter en el Registro de retención del transmisor (THR), que es la parte superior del FIFO del transmisor.

Así que conecté mi osciloscopio a la línea Tx e intenté enviar a estos personajes mientras grababa sus imágenes de osciloscopio:

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 .

Las imágenes del osciloscopio se veían bien al principio, pero una vez que alcancé los valores 0x20 , 0x21 , 0x22 , 0x23 , 0x25 , 0x26 noté que las imágenes del osciloscopio para estos caracteres parecen iguales que los de las imágenes 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 . ¿Cómo es esto posible? Aquí está la carpeta comprimida con todas las imágenes (por favor, no preste atención a las mediciones frecuencia que es incorrecta ya que el osciloscopio toma bordes erróneos para medirlo) .

Se suponía que mi programa C configuraba la comunicación UART3 en 9600 8N1, que significa 9600 baudios, longitud de caracteres de 8 bits, sin paridad y 1 bit de parada, pero el ancho del carácter enviado me parece dos veces más corto desde el principio.

Aquí está el programa:

#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;

    }
}

¿Me estoy perdiendo algo?

    
pregunta 71GA

2 respuestas

4

El! operador en C es un operador lógico y produce un resultado que es verdadero (1) o falso (0).

Parece que estás buscando el operador NO a nivel de bits que es ~, ¡no!

El resultado de! (0b0011111) es simplemente 0 (o 0b0000000 o 0x00 o como quieras representarlo), mientras que el resultado de ~ (0b00111111) es 0b11000000.

Incluso si corriges esto, todavía tienes un código que parece "contradecirse" a sí mismo.
Tiene LCR |= (0b11); que establece los 2 bits menos significativos de su registro LCR, y luego en la siguiente línea tiene LCR &= !(0b0011111); (y supongo que quiso decir ~ y no!) Que borra inmediatamente esos 2 bits.

    
respondido por el brhans
1

Echa un vistazo a estas líneas.

//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);

A primera vista, me parece que la segunda línea elimina los efectos de la primera, con el resultado de que probablemente esté seleccionando 5 bits por carácter, no 8. Hay ocasiones en las que es mejor calcular la valor mágico en hexadecimal a mano, y simplemente enchufarlo en el registro de una sola vez.

    
respondido por el John R. Strohm

Lea otras preguntas en las etiquetas