5 votos

UART, minicom y ASCII

Estoy intentando enviar mi nombre ( Ziga ) a través de la periferia UART de mi microcontrolador a mi PC. Las líneas GND, Tx, Rx del micro-controlador están directamente conectadas al convertidor UART-USB CP2102 que está conectado a mi PC.

Mi PC funciona con el sistema operativo Linux y estoy utilizando la aplicación minicom para comprobar la información transferida. Durante la transmisión, mi terminal minicom imprime unos símbolos extraños (haz clic para ampliar):

enter image description here

y si activo " Visualización HEX " obtengo estos valores (haga clic para ampliar):

enter image description here

Los valores son 0x5C = 92 que es \ en ASCII entonces 0xFC = 252 que no tiene ningún signo en ASCII antiguo por lo que se convierte en ? entonces hay 0x40 = 64 igual a @ en ASCII y, por último 0x81 = 129 que tampoco está definido en el antiguo ASCII, por lo que se convierte en ? .

mientras que estoy recibiendo imagen correcta en mi osciloscopio (haga clic para ampliar):

enter image description here

¿Por qué no consigo ZigaZigaZigaZiga ... en la consola minicom? Los valores de las letras individuales son correctos según ASCII mesa.


ADD 1 :

Tomé una imagen de osciloscopio de la letra a de Ziga . Espero que esto pueda ayudar a determinar si la tasa de baudios del microcontrolador es correcta.

enter image description here


ADD 2 :

He probado a utilizar 2 bits de parada tanto en el minicom como en el microcontrolador y obtengo un resultado diferente que es incluso peor - sólo transfiere 3 caracteres en lugar de cuatro ( Ziga tiene cuatro). Echa un vistazo:

enter image description here


ADD 3 :

He encontrado esta información sobre osciladores externos. ¿Significa esto que el reloj PCLK mencionado en el micro-controlador manual del usuario es 12Mhz ?

enter image description here


ADD 4 :

Así que nos dimos cuenta de que debe ser un problema de velocidad de transmisión, así que empecé a leer manual del usuario y descubrí en la página 21 que mi PCLK = 3MHz por defecto. Luego elegí un algoritmo en la página 509 para calcular los valores:

DLL = 0
DLM = 13

DIVADDVAL = 1
MULVAL = 2

Estos valores deberían darme 9600 baudios según la ecuación (4) de la página 508. Bueno, da 9615.384615 que debería ser 0.16% exacto. Entonces empecé a programar y puse los valores de arriba así:

DLL &= ~(0xFF);                //setting first byte to 0  (divisor latch least signifficant byte)
DLL |= 13;                     //setting first byte to 13 (divisor latch least signifficant byte)
DLM &= ~(0xFF);                //setting first byte to 0 (divisor latch most signifficant byte) -- not really needed
DLM |= 0;                      //setting first byte to 0 (divisor latch least signifficant byte) -- not really needed
FDR |= (1<<5); FDR &= ~(1<<4); //setting value MULVAL
FDR |= 0x1;                    //setting value DIVADDVAL

Pero aún no consigo la velocidad de transmisión correcta...

1 votos

¿Tasa de baudios incorrecta?

0 votos

Lo tengo configurado 9600 8N1 en ambos lados. Esto significa 9600 baudios, 8 bits de datos, sin paridad y 1 bit de parada.

0 votos

¿Has programado tu uC para que haga eco de lo que escribas? Si no lo has hecho, no deberías ver nada. ¿Qué se supone que debe devolver tu uC?

3voto

chews Puntos 1507

Creo que tienes un desajuste en la tasa de baudios.

A 9600 baudios, cada bit debe ser ~104us de ancho . He aquí un ASCII real 5 en el visor con un solo bit cronometrado a 105us...

enter image description here

(tenga en cuenta que ASCII 5 es un carácter útil para las pruebas porque alterna unos y ceros en binario)

A 9600 baudios, un solo byte debe ser ~833us de ancho (8 bits de datos, sin contar inicio y parada)....

enter image description here

Su traza muestra los mismos 8 bits tomando ~300us, por lo que su reloj serie es de aproximadamente 2.7x demasiado rápido.

Prueba a configurar tu velocidad de transmisión en Minicom a 26656 baudios y comprueba lo que obtienes. Si ve Ziga entonces puedes empezar a buscar por qué el reloj serie está demasiado rápido.

0 votos

Para ver bits ascii U es incluso mejor que 5 es arriba-abajo todo el camino desde el bit de inicio hasta el bit de parada.

2voto

RelaXNow Puntos 1164

Lo que muestras parece la típica bazofia en baudios.

Uno de tus diagramas muestra que estás enviando 8 bits en 300 µs, lo que significa 26,7 kBaud. Eso es un valor impar. Prueba con una velocidad en baudios estándar, como 9600, y asegúrate de que tu PC está configurado en esa velocidad. 9600 baudios significa un tiempo de 104,2 µs por bit, por lo que 8 bits deberían tardar 833 µs y un carácter completo de 10 bits (1 bit de inicio, 8 bits de datos, 1 bit de parada) 1,04 ms.

0 votos

Por favor, eche un vistazo al ADD 4 de mi pregunta. He añadido algunas explicaciones sobre el cálculo de la velocidad de transmisión como se describe en la documentación. También he añadido algunas líneas de programación en C donde establezco esos valores.

1 votos

@71GA: No conozco su procesador. La mayoría de las UART quieren un reloj que sea 16 veces la velocidad en baudios. Si quieres 9600 baudios, entonces necesitas alimentarlo a 153.6 kHz. A partir de 3 MHz, que requeriría dividir por 19,5, que no va a funcionar. 4800 baudios requeriría dividir por 39.06, así que 39 debería funcionar. Eso puede requerir cargar 38 en un registro dependiendo de cómo funcione tu hardware.

0 votos

Lo más bajo que puedo observar en mi PC es 9600.

1voto

Derek Allums Puntos 1275

Este hilo aún no está resuelto pero hemos descubierto que tenía un desajuste de baudrate UART y puedo confirmarlo. ¿Pero dónde está el problema? Si leo LPC4088 manual del usuario Puedo leer que utiliza un oscilador interno de 12MHz (p.7). Gracias a ti también encontré capítulo generación de reloj (p.21) con este esquema:

enter image description here

Ahora para entender completamente esto necesitamos buscar en la documentación los valores por defecto de los multiplexores CLKSRCSEL[0]=0 (p.34), CCLKSEL[8]=0 (p.33) y divisor PCLKSEL[4:0]=0x4 (p.34). Así que debería recibir PCLK = 12Mhz/4 = 3MHz pero creo que esto no es cierto o debe haber un error con el algoritmo para calcular la velocidad de transmisión o la ecuación (p.508, p.509):

enter image description here enter image description here

En mi caso he intentado calcular con PCLK=3MHz y quería baudrate 9600 . Así que primero calculé DL_EST = PCLK/(16*9600) = 19.53 (EST significa estimación) y esto no es un número entero por lo que FR_EST = 1.5 y DL_EST = PCLK/(16*9600*1.5) = 13.02 = 13 . A continuación calculamos FR_EST = PCLK/(16*9600*13) = 1.5024 . Sostiene que mi 1.5 < FR_EST < 1.9 para poder leer valores para un latch divisor DL de la tabla (p.510):

enter image description here

De las tablas y cálculos anteriores se deduce que en mi caso:

DIVADDVAL = 1
MULVAL = 2
DL = 13

Porque DL = 13 = 00000000 00001101 consiste en el byte menos significativo del latch divisor DLL y divisor latch byte más significativo DLM esos dos son iguales a:

DLL = 13
DLM = 0

Usé esos valores para programar la tasa de baudios de la UART del LPC4088, pero no obtuve 9600 como debería. Incluso comprobé dos veces la ecuación suministrada que devuelve 9615.384615 y esto es 0.16% preciso que parece bien.

Bueno me rendí con el algoritmo/ecuación de NXP e intenté trabajar por ensayo y error y descubrí que:

DIVADDVAL = 1
MULVAL = 2
DL = 255         //this means DLL = 255 and DLM = 0

Devolvió 9600 baudrate y pude comunicarme con mi PC sin problemas. Pero todavía no sé cuál es el error. ¿Estoy haciendo algo mal en el código o es NXP que proporcionó algoritmos erróneos?

Aquí está mi programa en C completamente funcional. ¿Notas algún error?

#include "LPC4088-ioconfig.h"
#include "LPC4088-system.h"
#include "LPC4088-gpio.h"
#include "LPC4088-uart.h"

int main(){

    //PIN settings    
    IOCON_P0_0 &= ~(0x67F);
    IOCON_P0_0 |= (1<<1);
    IOCON_P0_1 &= ~(0x67F);
    IOCON_P0_1 |= (1<<1);

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

    //we set 8-bit characters, no parity, one stop-bit in LCR register
    //LCR.DLAB = 1
    LCR |= (0x3);
    LCR &= ~(0x7C);
    LCR |= (1<<7);

    //set DLL[0-7] = 255, DLM[0-7] = 0, FDR[0-3] = 1, FDR[4-7] = 2
    //values obtained by trial & error - NXP's algorithms don't work
    DLL &= ~(0xFF);
    DLL |= 255;
    DLM &= ~(0xFF);
    DLM |= 0;

    FDR &= ~(0xFF); 
    FDR |= 1;           //DIVADDVAL 
    FDR |= (2<<4);      //MULVAL

    //LCR.DLAB = 0 
    LCR &= ~(1<<7);

    //enable Rx and Tx FIFO
    FCR |= 0x1;

    unsigned char posiljka[] = "Ziga";

    while(1){

        for ( int i = 0 ; i < ( sizeof(posiljka)/sizeof(posiljka[0]) -1 ) ; ++i ){

            //we read LSR and wait for THR to empty
            while ( (LSR & (1<<5)) != (1<<5) );

            //send one character at a time
            THR = posiljka[i];
        }
    }
}

1voto

Raj Puntos 11

Acabo de encontrarme con este mismo problema. La configuración de 9600 baudios de la OP funcionó para mí, donde los valores calculados a partir del manual no lo hicieron.

El problema para mí era que el código de arranque por defecto utilizado en mi proyecto (Keil utilizando el paquete LPC4000_DFP-1.1.0) llama a una función "SystemInit" que configura los registros de reloj a valores no reseteados.

La función problemática reside en "system_LPC407x_8x_177x_8x.c". La función se llama desde el código de arranque en "startup_LPC407x_8x_177x_8x.s".

Una solución es copiar ambos ficheros en tu proyecto en lugar de utilizar los estándar y modificar el fichero C para configurar los relojes como tú quieras. Alternativamente, puede modificar el archivo ensamblador para evitar la llamada a "SystemInit"; tenga en cuenta, sin embargo, que en este caso tendrá que configurar el coprocesador usted mismo (como en "fpu_init", que se llama desde "SystemInit"), ya que esto parece ser necesario para el funcionamiento normal (todavía no tengo claro por qué).

0 votos

Y por eso odio el CÓDIGO DE INICIO que no se suministra como código fuente sino como archivo objeto... ¿Tienes quizás un código fuente para el archivo de inicio? Necesito el del compilador GNU...

0 votos

Lo siento, no. El código de inicio que utilicé era para MDK-ARM (armcc). No lo tengo instalado en este momento, pero es de descarga gratuita y probablemente podrías adaptarlo a gcc con bastante facilidad.

0 votos

Parece que tendré que escribirlo yo mismo... ¿Por qué ocultan esto? ¿Alguien lo sabe? =/

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X