Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

14/09/2012 #1

Avatar de ilcapo

Tutorial ARM desde 0x00000000
Hola a toda la gente del foro, este tutorial trata del ARM7 TDMI procesador LPC2148 :

porque elegí este? porque no es ni el mas basico ni el mas completo de todos y creo que es el mejor para arrancar ademas despues se puede migrar a cualquier otro ARM sin muchos cambios

Tengo pensado hacer entre 6 y 8 entregas,totalmente en español para que esté al alcance de todos.Por lo tanto voy a pedirles que me ayuden en la traduccion del manual del LPC2148 (Rev. 4 — 23 April 2012). En los archivos adjuntos les dejo la traduccion de los capitulos 6 y 8 que son los que vamos a utilizar para arrancar con todo esto, para la segunda entrega voy a necesitar un valiente traductor para el capitulo 7 (traduccion de cuadros incluido) porque no voy a disponer del tiempo necesario para hacerlo

Cada entrega comienza con una explicacion teorica y despues LOS DESAFIA a realizar algunos ejercicios practicos.Todo lo necesario para hacer las practicas está en los archivos adjuntos, los ejercicios se deben realizar utilizando solo la teoria desarrollada hasta el momento esto es muy importante para que este tutorial sea PASO A PASO,(por ejemplo en esta primera entrega no se explican las Interrupciones por lo tanto no hay que utilizarlas en estos primeros ejercicios)

Lo mas importante de este tutorial es que entre entrega y entrega hay que ir entregando los ejercicios resueltos!! asi los van discutiendo entre todos y van aprendiendo a programar mejor y conociendo mas los pines del LPC2148, esto es fundamental sino el tutorial no tiene sentido, y ademas me da el tiempo para preparar la proxima entrega . Como ayuda para las practicas el Compilador que vamos a utilizar es el KEIL que tiene un simulador, y el que consiga la placa mucho mejor. El programa Flash Magic será el encargado de pasar el programa a la placa.

Conocimiento previo: un poco de C ( si alguna vez programaste pics en C con eso ya es mas que suficiente)

Se agradece la participacion en esta primera entrega de Cosmefulanito04 y todos los nuevos colaboradores para proximas entregas seran bienvenidos

Bueno larguemos ya! les dejo toda la info necesaria en los archivos adjuntos ojala se prendan muchos con los ejercicios !!!!

saludos!
14/09/2012 #2
Moderador general

Avatar de Fogonazo

! Gracias por el aporte ¡
14/09/2012 #3

Avatar de cosmefulanito04

Muy bueno, la verdad vi que le pusiste todas las pilas .

Esta piola que hayas subido el circuito de una placa de desarrollo para que todos se puedan basar en un mismo hard.

Lo que les recomiendo a la gente que no tenga el hard en sus manos, pero quiera aprender sobre estos bichos, bajense el Proteus que permite simular esta familia de uC y en conjunto con el esquemático que subió ilcapo, pueden ir programando y probando como va quedando.

Por último les recomiendo que aprendan a tener siempre cerca las hojas de datos del uC y tal como hizo ilcapo, ver como se comportan los registros de los periféricos que necesitamos utilizar. Si bien uno al principio se asusta con la cantidad de páginas que tienen, tengan en cuenta que esas hojas son como una enciclopedia de como funciona el uC en su totalidad y por lo tanto es muy probable que ustedes en su proyecto solo usen un par de periféricos/registros y el resto les resulte redundante. Además como buena práctica, traten de entender las hojas en inglés, no todos los días van a tener un ilcapo que les traduzca las hojas y si bien algún conocimiento de inglés se necesita, siempre las hojas son iguales, breves y concisas en la información que dan, por lo tanto el inglés necesario es muy básico y técnico (no van a encontrar una poesía en un datasheet... bahh hasta ahora nunca me paso eso )
19/09/2012 #4


Ejercicios con LED y culsador en ARM7 lpc2148
Hola como estan? Soy nueva en el foro, hice los ejercicios de la " Entrega I ". La subo asi lo ven, y si tienen distinto me comparten, y terminamos armando un buen tutorial Saludos
Archivos Adjuntos
Tipo de Archivo: rar TP1 Dig 3.rar (5,3 KB (Kilobytes), 98 visitas)
19/09/2012 #5

Avatar de cosmefulanito04

Por lo que ví están bien, salvo pequeños detalles o algún consejo:

- En los primeros 3 ejercicios no inicializaste los PINSEL, si bien como explicó ilcapo se inicializan en 0 después del reset, es recomendable igual configurarlos.

- En el 1er ejercicio, cuando haces esto:

Código PHP:
if(IOPIN1 & (0x01000000)) //Evaluamos el estado actual de P1.24
  
{
  
IOSET1 = (1<<24); // Si estába apagado, los prendemos
  
}
... 
Podrías reemplazar 0x01000000 en el if por (1<<24):

Código PHP:
if(IOPIN1 & (1<<24)) //Evaluamos el estado actual de P1.24
  
{
  
IOSET1 = (1<<24); // Si estába apagado, los prendemos
  
}
... 
Así resulta mucho más fácil leer el código. Esto lo hiciste en el resto de los ejercicios.

- En los ejercicios 7 y 8, creo que te equivocaste con el valor inicial de la variable "pos", debería ser 8 o para evitar confusión, nuevamente usar desplazamiento (1<<3).

- En los ejercicios 7 y 8, creo que te falto hacer un AND a la hora de modificar el PINSEL

El resto está perfecto según lo que se pidió e hiciste muy bien en usar máscaras a la hora de modificar los registros como PINSEL o IODIR, ya que lo ideal es no modificar el resto de los puertos que no usas.

Por último, tengan en cuenta que los ejercicios que involucran los pulsadores tienen un comportamiento "ideal" y no real, ya que no se tiene en cuenta los rebotes del pulsador.
20/09/2012 #6

Avatar de ilcapo

Con respecto a la configuracion del Pinsel: ( no esta en los primeros ejercicios q envió leluza pero luego esta correcta la configuracion)

/*Configuracion del GPIO P1.24*/
PINSEL2 &= 0xFFFFFFF7; // Pongo el bit3 a 0 entonces me quedan como GPIO los pines 16
// al 25 del puerto 1

Fijense que usó pinsel 2 para configurar el puerto 1!! , un error muy comun hubiese sido colocar pinsel 1 !! , porque para los otros registros que estamos viendo:

IOSET0 : para puerto 0 (cero con cero)
IOSET1: para puerto 1 (uno con uno)
IOCLR0: para puerto 0
IOCLR1: para puerto 1

idem para IODIR,,etc,,,, el unico que no "respeta la logica" es el pinsel
(todo esto esta en las hojas de datos)

************************************************** *******************

El error fino que hay en los ejercicios es que el led se enciende por bajo ( esto es asi para que la energia del led la suministremos con una fuente externa y no usemos como fuente al procesador!! )

por lo tanto en el programa para encender el led usamos: IOCLR1 = pin_24;
y para apagarlo usamos: IOSET1 = pin_24;

************************************************** ********************
No se si lo habia comentado, si no lo repito, en el Keil podemos escribir IOSET1 = IO1SET
ó IOCLR1 = IO1CLR
en otros compiladores solo te deja escribirlo de una ú otra forma,y si no la respetas te tira un error ( de esos que te hacen renegar ) un punto mas a favor para el Keil vs Otros

************************************************** *******************
Esperamos unos ejercicios mas y largamos con el Practico 2:INTERRUPCIONES EXTERNAS
animense todos que son faciles!

Si alguno tiene problemas con la simulacion de los ejercicios en el KEIL que avise porque es muy facil tambien !! y la simulacion nos va a ser muy util para el practico 2

mientras tanto..... habrá algun valiente traductor del capitulo 7 ??

saludos!
21/09/2012 #7


En primer lugar gracias por el tutorial. Para no repetir el mismo codigo, se me ocurrio sugerir algunas alternativas muy simples:

Ejercicio 1 usando el operador ? :
Código PHP:
#include "LPC214x.h"
int main (void){
    
int j;
    
IO1DIR |= (1<<24);      // P1.24 como salida
    
while(1){
        
IO1PIN = (IO1PIN & (1<<24)) ? (0<<24) : (1<<24);   // Cambia el estado del LED
        
for (0100000j++ );                     // Retraso
    
}

Ejercicio 2 usando el operador ^ para cambiar el estado de los LEDs:
Código PHP:
#include "LPC214x.h"
int main (void){
    
int j;
    
IO0DIR |= (1<<17);     // P0.17 como salida
    
IO1DIR |= (1<<24);     // P1.24 como salida    
    
IO0SET  = (1<<17);     // LED en P0.17 apagado
    
IO1CLR = (1<<24);      // LED en P1.24 encendido
    
while(1){
        
IO0PIN ^= (1<<17);                // Cambia el estado del LED
        
IO1PIN ^= (1<<24);                // Cambia el estado del LED            
        
for (0100000j++);     // Retraso
    
}

Ejercicio 7 usando Fast GPIO:
Código PHP:
#include <LPC214x.h>
int main (void){
    
int jn;
    
SCS |= 0x1;              // Activa Fast GPIO
    
FIO0DIR |= 0xAAA8;       // P0 pines 3,5,7,9,11,13 y 15 como salidas
    
FIO0MASK |= 0x5557;      // Configura registro "mask" para pines usados como salidas
    
FIO0SET |= 0xAAA8;       // Inicio con todos los LEDs apagados

    
while(1){
        for (
315){    // Genera secuencia (3->5->7->9->11->13)
            
FIO0PIN 0xFFFF ^ (<< n);    // Enciende LEDn 
            
for (01000j++);     // Retraso
        
}            
        for (
153){    // Genera secuencia (15->13->11->9->7->5)
            
FIO0PIN 0xFFFF ^ (<< n);    // Enciende LEDn
            
for (01000j++);     // Retraso
        
}
    }

Saludos
22/09/2012 #8

Avatar de cosmefulanito04

Interesante código para ver otras alternativa.

Sobre el operador "?", te soy sincero, es la 1era vez que lo veo y ni sabía de su existencia en C .

Sobre el operador "^", para el que no lo conozca es el operador XOR y en este caso es usado como "negador controlado" tal como hizo carferper en su código.

XOR:



Entonces si la máscara contiene 1's en ciertos bits, se puede negar dicho bit, en cambio si la máscara contiene 0's en ciertos bits, dichos bits mantendrán su valor original.

Ejemplo con variables de 8bits:

Código PHP:
var1=0b00101001;
mascara_negadora=0b00001111;

var1=var1^mascara_negadora;  // 0b00101001 XOR 0b00001111 = 0b00100110 
Vean que solo quedó negado el nibble inferior en cambio el nibble superior mantuvo su valor, esto se debe a que la máscara tenía 1's en el nible inferior y 0's en el superior. Esto mismo se aplica para variables de 4, 8, 16, 32, N bits.
18/01/2013 #9


Muy buen aporte el tutorial pero podrian decirme donde se puede adquirir la placa de desarrollo para el ARM que estan tratanndo...bueno seria porder llevar a la practica real el tutorial..
gracias ....
23/01/2013 #10

Avatar de cosmefulanito04

Timer y PLL
Les dejo el código para poder configurar correctamente el PLL de un LPC y luego manejar un timer por interrupciones. El programa simplemente enciende y apaga un LED que se encuentra en el puerto 15 c/1seg. El código se compone de 3 archivos fuentes:

- pllconfig.c:

Código PHP:
#include <LPC213x.h>

void feed(void)
{
  
PLLFEED=0xAA;
  
PLLFEED=0x55;
}

#define PLOCK 0x400

void inicia_pll()
{
    
/*
    Ejemplo de Configuración del PLL:

    Fcontrol-interna-PLL=2*Fcristal*M*P

    Core-Clock=Fcristal*M

    Port-Clock=Core-Clock/D

    M y P se configuran en el registro PLLCFG, bits:
        .0 - 4 : M (Valores posibles: 1 a 32)
        .5 - 6 : P (Valores posibles: 1,2,4,8)

    D se configura con el registro VPBDIV, bits:
        .0 - 1: D (4,1,2,--) 

    A tener en cuenta:
        - Core-Clock máxima según la especificación del modelo
        - 156MHz < Fcontrol-interna-PLL < 320MHZ
        - Cada cambio que se realice se deberá ser completado con el uso del registro PLLFEED según la secuencia que indica la hoja de datos.
    */
          
    /* 
    Configuración del PLL:

    Se desea Core-Clock=60MHz a partir de un cristal de 12MHz:
        Core-Clock=Fcristal*M => M=Core-Clock/Fcristal=60/12=5
        
        Se debe cumplir con 156MHz < Fcontrol-interna-PLL < 320MHZ

        Fcontrol-interna-PLL=2*Fcristal*M*P=2*12MHz*5*P=120MHz*P => Pmin=156/120=1,3 redondeando para arriba P=2
        Verificamos => Fcontrol-interna-PLL=2*12MHz*5*2=240MHz => Cumple con la condición
        
    */
    
PLLCFG=0x24// P=2 y M=5
    
feed();
  
    
// Se activa el PLL    
    
PLLCON=0x1;
    
feed();
  
    
// Espera hasta que el PLL enganche a la frecuencia deseada
    
while(!(PLLSTAT PLOCK)) ;
  
    
// Se habilita al PLL como Core-Clock
    
PLLCON=0x3;
    
feed();
     
  
    
// Se configuran el clock de los periféricos en función del Core-Clock
    
VPBDIV=0;    //Divide por 4 => Valor de "D" para configurar el Port-Clock
    

- Timer.c

Código PHP:
//--------- Rutina de la interrupcion timmer---------------------//
__irq void timer0(void)
 {
     
flag_timmer0=1;
    
    
T0IR=0x01// Limpio registro de interrupcion
    
VICVectAddr=0xFF;
 }
 
//---------------------------------------------------------//

void configura_timmer0()
{
    
    
/* Los timers tienen 2 contadores, 1 es el prescaler y el otro es el contador en si mismo, ambos tienen registros son de 32 bits
       por lo tanto por c/u puedo contar 2^32, osea como máximo podria contar hasta 2^64*Base de tiempo ---> muchoooos días :)
       El timer sería una cosa así:  Port-clk --> Prescaler --> Contador (Nota: Fcristal --> PLL --> Core-clock --> Divisor --> Port-clock)

       - Prescaler -> 2 registros
             . TxPR: Es el valor de la cuenta final del prescaler.
             . TxPC: la cuenta del prescaler, también permite fijar desde donde comienza a contar el prescaler, cuando sea igual a TxPR, desborda y empieza de nuevo, mandandole una cuenta al otro contador

       - Contador -> 4 registros
             . TxTCR: Es un registro de control, si vale:
                -0: el contador no cuenta.
            -1: el contador cuenta.
            -2: reseteo el contador.
          . TxTC: la cuenta del contador, también permite fijar el valor de inicio del contador.
          . TxMRx: Son varios registros (segun el timer pueden ser 4 o 3), acá se pondrá el valor de la cuenta q se desea alcanzar con el contador, cuando TxTC sea igual se produce un evento.
            Son varios porq se lo puede configurar para q envie un evento en cuentas distintas, ej:
            - TxMR0 = 34; Al llegar acá se produce un evento, pero el contador sigue
            - TxMR1 = 45; Al llegar acá se produce otro evento
          . TxMCR: Sirve para configurar q acción tomar cuando se produce un evento, es de 32 bits y c/3bits se configura un MRx distinto:
              Sí se produce un evento en MRx y TxMCR vale:
            - 001: lanza una interrupcion
            - 010: se resetea el contador
            - 100: se para el contador
            Las 3 acciones se pueden combinar, osea interrumpir y resetear al mismo tiempo.
    */

    //------------------ Configuración del Timer -----------------------------------------------//
    
T0TCR=0x0// el contador no cuenta
    
T0TC=0x0;  // el contador comienza de 0
    
T0PR=15000// configuro la cuenta del prescaler tal q le mande una cuenta al contador c/ 1 mSeg
    
T0PC=0x0;  // el prescaler comienza de 0
    
T0MR0=1000// configuro la cuenta del MR0 tal q cuente 1000 mSeg osea 1 seg
    
T0MCR=0x03// configuro q al producirce un evento en MR0, se lance una interrupcion y se resetee el contador
    //------------------------------------------------------------------------------------------//

    /* Registros de interrupciones:
       VICIntEnable: habilita las 16 posibles fuentes de interrupciones
       VICIntSelect: configura a las interrupciones como:
               - FIQ: interrupciones rapidas
            - IRQ: interrupciones comun, q a su vez pueden ser:
                 * vectorizadas 
                * no vectorizadas
       VICVectCntl_0 al 15: en el se indican los índices de interrupciones habilitadas y sí es vectorizada o no.
       VICVectAddr_0 al 15: la dirección donde se encuentra la rutina de atención
    */

    //------------------------ Configuracion de las interrupciones ------------------------------//
    
VICIntSelect=0x0// Lo configuro como IRQ
    
VICIntEnable=0x10// Interrupcion del Timer 0 activado, su indice es 4 al ser el bit 4    (importante para el reg. q viene)
    
VICVectCntl0=0x24// Los 4 1eros bits sirven para indicar el indice, el 6to bit si vale 1 indica q es vectorizado y si vale 0 q no
    
VICVectAddr0= (unsigned longtimer0// Le digo q la direccion de la subrutina timer0 q funciona como interrupción
    //--------------------------------------------------------------------------------------------//

- Main.c

Código PHP:
#include <LPC213x.h>

unsigned char flag_timmer0=0;

#include "pllconfig.c"
#include "timer.c"

#define puerto_15         (1<<15)

int main()
{
    
inicia_pll();
    
    
PINSEL0=0;
    
PINSEL1=0;    

    
configura_timmer0();

    
IODIR0=puerto_15;
    
IOSET0=puerto_15;
    
    
T0TCR=1// el contador empieza a contar
    
    
while(1)
        {
        if(
flag_timmer0)
               {
            
flag_timmer0=0;

            if(
IOPIN0&puerto_15)
                
IOCLR0=puerto_15// Apago led
            
else
                
IOSET0=puerto_15// Prendo led    
            
}

        }

Les subo el proyecto en keil y el esquemático en Proteus para que puedan simularlo.
Archivos Adjuntos
Tipo de Archivo: zip PLL y Timer.zip (109,8 KB (Kilobytes), 43 visitas)
19/02/2013 #11


Hola amigos, estoy trabajando con el lpc 2148 y estoy teniendo problemas con la interrupción UART1, si la hace pero solo una vez, me gustaría saber si alguien tiene algún código para ver las configuraciones que debe de tener y muchas gracias por su atención.
05/03/2014 #12


Hola, bueno les comento que apenas estoy leyendo todo lo relativo a procesadores ARM.
Aclaro que aún no me quedan muchas cosas claras (en lenguaje ensamblador) como el modo ARM ,thumb, thumb-2 , privilegiado y no privilegiado etc.
Temas que ahora mismo estoy aprendiendo, en fin la cuestión es que mientras aprendo he decidido empezar a practicar cosas sencillas a la par para ir adquiriendo experiencia y (maña).
Bueno por ahora he tratado de realizar algo tan sencillo como cargar el valor hexadecimal 0x00000020 a la dirección 0x400FE608 de un microcontrolador tiva C cortex m4 f
Bueno el código lo estoy realizando en el compilador IAR para arm versión 7.10.xxx
Todo va bien excepto por la instrucción mov.w R0,#0x400FE608 que me marca un error el cual dice que el operando esta fuera de rango, el cual se supone puede ser de 32 bits.
¿Alguien me podría dar una idea de lo que estoy haciendo mal?
Se los agradecería mucho.
Código:
   NAME    main
        
        PUBLIC  __iar_program_start
        
        SECTION .intvec : CODE (2)
        CODE32
        
__iar_program_start
        B       main

        
        SECTION .text : CODE (2)
        CODE32

main    
        MOV.W   R0,#0x00000020
        MOV.W   R1,#0x400FE000
        STR.W   R0,[r1,#0x608]

        NOP
        B main

        END
---------- Actualizado después de 1 hora ----------

Bueno, les comento que acabo de revisar y el cortex m4 f al parecer no soporta el modo 32 bits en ensamblador
He ahí el problema, lo que si se puede hacer es separar la palabra en 2 partes de 16 bits o 4 de 8 bits, aunque todavía no me queda claro como acomodar las partes en el registro que sí es de 32 bits, pero lo voy a intentar y ya les comentare el resultado.
Buenas noches a todos.
15/03/2014 #13


thumb sin CMSIS?
buenas tardes compañeros , sigo intentando hacer parpadear un led con el tiva C 123xxx en lenguaje ensamblador, sin mucho exito y como les comente en el mensaje anterior apenas estoy aprendiendo la arquitectura de ARM pero estoy haciendo mi tarea que es estudiarlo; bueno he estado leyendo los manuales de ARM y ti pero me surgen ,muchas dudas. Sé que el cortex M4 ejecuta sus instrucciones en modo thumb, y sé tambien que existe el CMSIS (cortex microcontroller software interface) que por lo que pude entender es una capa de abstarccion (API) para poder acceder a ciertos perifericos y demas prestaciones del micro independientemente del fabricante del micro , ahora mis dudas son;

?el modo thumb lo indica alguna directiva del compilador-preproceasdor o la instruccion misma?

?se pueden usar las instrucciones thumb sin hacer uso de las librerias CMSIS? y de ser posible esto, puedo acceder a registros que no sean de uso general como lo son r0 r1 etc usando su direccion inmediata?

espero me puedan ayudar ya que existe muy poca informacion para ARM en ensamblador (por obvias razones) muchas gracias por su atencion y bonita tarde
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.