Mostrando entradas con la etiqueta ARM. Mostrar todas las entradas
Mostrando entradas con la etiqueta ARM. Mostrar todas las entradas

lunes, 16 de junio de 2014

Primer programa con la Connected Launchpad.

En la entrada anterior os presente la nueva placa de la serie Launchpad de Texas Instruments. Esta placa monta un microcontrolador Tiva TM4C129, lo que se traduce en un ARM Cortex M4 a 120Mhz. Como ya comenté, Texas Instruments, ha facilitado mucho la programación de estas placas, lo que en principio parece una ventaja, pero no lo es tanto, ya que utilizando ese método nos abstraemos mucho del hardware con el que trabajamos, pero sin duda, la utilización de APIs hace mucho más sencilla la programación, y como dije, estas APIs son muy eficientes en cuanto a código.
Lo primero que debemos hacer para aprender a programar estas placas y familiarizarnos con las APIs, lo mejor es empezar a ver algunos ejemplos que encontramos en la colección TivaWare que podéis descargar aquí. Una vez instalado, en la carpeta de instalación tenemos muchos ejemplos para los diferentes periféricos que dispone, pero los ejemplos no son infinitos.
Por algunas razones, uno de los ejemplos que he echado en falta es el de la lectura de varios canales analógicos a una frecuencia determinada. Esto que puede parecer trivial para algunos es muy útil cuando queremos, por ejemplo realizar un control, o cuando queremos hacer un procesado de la señal.
En este ejemplo, como en todos, lo primero que debemos hacer es habilitar los periféricos que vamos a utilizar, que en nuestro caso serán los puertos digitales N y E, el Timer0, y el propio conversor analógico - digital. Esto es lo primero que debíamos hacer también cuando programábamos los STM32 de ST, y es que recordad que internamente, muy internamente, son lo mismo. Lo siguiente es empezar a configurar los perifericos, empezando por los GPIO, configurándolos como salida los que vayamos a utilizar. En segundo lugar debemos configurar el Timer0. Texas Instruments, en la serie Tiva, divide los timers en 2, TIMER_A y TIMER_B, cada uno de ellos de 16 bits. En el ejemplo solo utilizo el TIMER_A. Por último configuramos el conversor AD. Añadimos los canales 0 y 1 al secuenciador, a la cola de conversión , y le decimos que al llegar al canal 1 ha acabado y genere una interrupción.
El conversor ADC de los microcontroladores Tiva permite bastantes opciones de disparo, incluso podemos decirle que una vez ha finalizado, el mismo se genere el disparo para que lea los canales continuamente.
El código del ejemplo que he desarrollado lo teneis a continuación.


He estado buscando ejemplos un poco menos genericos y no he encontrado muchos, solo en los propios foros de TI, así que espero que este ejemplo os ayude y anime a probar con estas placas low cost.

miércoles, 4 de junio de 2014

Connected Launchpad

Hola a todos, en esta entrada os voy a presentar la ultima de las herramientas de desarrollo que ha sacado Texas Instruments para su serie Launchpad, la Connected Launchpad.
A pesar de este nuevo nombre, que abarca 2 placas de desarrollo, una de estas no es mas que la Tiva Launchpad, antes Stellaris Launchpad, a la que ahora le ha salido una hermana mayor.


Esta nueva placa monta un microcontrolador de la serie Tiva, el TM4C1294, el cual lleva un núcleo ARM Cortex M4, con todo lo que eso conlleva, es decir, 120MHz, 1MB de memoria de programa, 256KB de SRAM, 6KB de memoria E2PROM, FPU.... Además de los periféricos propios del núcleo ARM, este microcontrolador cuenta también con 2 ADC independientes de 1MSPS cada uno, a los cuales podemos asignar cualquiera de los 20 canales analógicos de los que dispone, 3 comparadores analógicos, módulo EMAC con PHY incorporado, lo cual reduce el número de componentes externos para poder utilizar la comunicación Ethernet, y un sin fin de periféricos más que harán que podamos controlar casi cualquier cosa.
La placa de desarrollo tiene el mismo color rojo de toda la serie, y lleva incorporado el programador y el depurador. A diferencia de otros Launchpad, y gracias a su tamaño, en esta herramienta es posible "pinchar" hasta 2 BoosterPack, y por si con esos 80 pines no podemos acceder a todas las entradas y salidas del microcontrolador, además disponemos de un conector en el lateral en el cual si que encontramos todos los pines.
Una de las cosas que me ha hecho decantarme por empezar con esta herramienta, y no seguir con las placas discovery de ST es que lleva un puerto RJ45, con lo que sin añadir nada más podemos crear un servidor web o cualquier otro dispositivo que se conecte a la red. Aunque no todo van a ser ventajas...


Una de las cosas que mas me gustaba de la serie discovery, y de los microcontroladores STM32 en general, es que se pueden programar como si de un PIC se tratara, es decir, miro en el datasheet el registro que quiero modificar,  gracias a las librerías que proporciona ST, puedo asignar de una forma fácil un valor concreto a un registro, incluso el compilador, gracias a la declaración de estructuras dadas por el fabricante, me sugiere los registros disponibles para modificar. Esto parece que no es del agrado de texas instruments, ya que esas estructuras y esos registros no están declaradas en ninguna librería de las que he probado, con lo que tienes que "conformarte", con utilizar las funciones o APIs que ellos te dan. Si bien, la utilización de esas APIs te hace la vida más sencilla, pero te obliga a conocerlas, mientras que los registros se encuentran en el datasheet. Ojo! que nadie se piense que esas funciones son como las de Arduino, esas APIS pueden incluso ser más optimas que la configuración directa del registro, pero si tengo que sacar un defecto a esta placa, o a TI, es ese. Por lo demás es una placa de desarrollo muy buena, bonita y barata (14 euros), ¿que mas se puede pedir?

lunes, 21 de abril de 2014

Primeros pasos con la STM32 Nucleo

En la entrada anterior os presenté mi nuevo juguete, la placa STM32 Nucleo-F401RE. En esta entrada voy a contaros los primeros pasos que tenéis que dar si queréis hacer funcionar vuestro primer programa en esta placa.
Lo primero que tenéis que saber es que esta familia de placas son MBED Enable, y esto quiere decir que vienen pre-programadas con un firmware, mediante el cual podemos cargar programas sin necesidad de un programador, aunque si que lo llevan, incluso sin necesidad de instalar un compilador, ya que los programas los podemos escribir y compilar directamente desde la página web de la plataforma.

Una vez ya hemos sacado de su paquete la placa, lo primero que hacemos es buscar un cable USB, ya que este no viene incluido. Cuando lo tengamos, conectamos la placa al PC y dejamos que instale los drivers, que en mi caso los instaló sin necesidad de yo decirle donde encontrarlos. 
Una vez instalados los drivers, si vamos a Equipo, veremos que tenemos una nueva unidad de disco llamada NUCLEO. Dentro de esa unidad tenemos tan solo un archivo con extensión .html.


Si abrimos el archivo .html, nos llevará directamente a la página https://mbed.org/platforms/ST-Nucleo-F401RE/. Una vez aquí nos debemos registrar. Cuando nos registremos, la plataforma MBED ya sabrá que nuestro usuario posee una placa Nucleo-F401RE, por lo que los programas que creemos los compilará compatibles con esta plataforma. Una vez formalizado el registro, ya podremos empezar a utilizar el compilador pulsando sobre el botón COMPILER. Cuando pulsemos, el navegador nos redirige hacia otra página en la que, una vez cargado, tenemos un compilador para código C online.


El compilador, a pesar de estar funcionando sobre el navegador, va bastante fluido, y como MBED es una plataforma abierta, disponemos de muchos ejemplos que podemos probar de forma gratuita.
Para crear nuestro primer programa debemos pulsar sobre New y se nos abrirá una ventana por delante del compilador. En esta ventana lo primero que tenemos es la placa sobre la que queremos trabajar, que en mi caso como solo tengo una solo me deja elegir esa. El segundo campo que tenemos es la plantilla que queremos utilizar. Estas plantillas se parecen bastante a los ejemplos de Arduino, por lo que nos serán de mucha ayuda. Por ultimo debemos darle un nombre a nuestro programa.

Una vez hecho esto, pulsamos sobre OK y en nuestro espacio de trabajo nos aparecerá un proyecto nuevo con un archivo .cpp y un desplegable llamado mbed que contiene todas las librerías. El archivo .cpp es, obviamente, el programa, el cual podemos modificar a nuestro gusto. Como veis, el lenguaje de programación es bastante sencillo y está basado completamente en objetos.
Una vez tenemos nuestro programa pulsamos sobre Compile y el compilador verificará el programa y nos descargará un archivo .bin. Una vez tenemos el archivo compilado, directamente lo copiamos en la unidad llamada NUCLEO, y después de un segundo desaparecerá, y nuestra placa empezará a compilar el código.
Como veréis si lo probáis es muy sencillo tener programas básicos funcionando en tan solo un par de minutos, sin instalaciones de drivers ni entornos de desarrollo.
Espero que os animéis con estas placas ya que además de baratas ya cuentan con una comunidad importante que aporta muchos ejemplos de código.

miércoles, 16 de abril de 2014

Placas NUCLEO de ST.

Hola a todos! a principios de esta semana me llego un nuevo juguete desde STMicroelectronics, y es una de las nuevas placas NUCLEO que son compatibles con el entorno MBED, en concreto tengo en mi poder la mas potente de las 4, la NUCLEO-F401. Despues de todos los enlaces que acabo de poner... vamos a ir paso por paso.
De las grandes empresas de electrónica que hacen microcontroladores que existen hoy (Texas Instruments, Microchip, ATMEL, ST, Freescale, NXP y pocas más), ST fue, si no me equivoco, la primera en ofrecer placas de desarrollo a unos precios muy, muy competitivos. Lo hizo con las primeras versiones de las placas de la serie Discovery, las cuales se podían, y pueden, encontrar por precios que van desde los 7 euros, las que montar microcontroladores ARM CORTEX M0, hasta los 20 euros las que montan pequeñas bestias como son los CORTEX M4 con pantalla LCD incorporada. Algunos ya estaréis echando espuma por la boca pensando que he olvidado las archiconocidas placas Arduino, pero estas tienen una carencia muy importante para un desarrollador, ya sea novato o experto, y es la ausencia de un depurador hardware, cosa que si encontramos en todas las demás herramientas de desarrollo de otros fabricantes, es por eso que las placas Arduino, y derivados, no van a entrar en este juego como herramienta de desarrollo, sin embargo si que ha sido muy importante la salida al mercado de Arduino como ecosistema, pues son estas placas las que han encendido la mecha para que los demás fabricantes se pongan las pilas, aunque en mi opinión, si Massimo Banzi, David Cuartielles y compañía no se ponen las pilas, estas quedarán relegadas muy pronto, y más con la salida al mercado de otras herramientas más potentes, y al 50% del precio. Siguiendo con el tema, a partir de la salida al mercado de las placas Discovery, los demás fabricantes no quisieron quedarse atrás y empezaron a ofrecer herramientas de desarrollo, aunque a un precio mayor, por ejemplo, las placas ChipKit de Microchip, tienen un precio incluso un poco mayor que las Arduino, está claro que son más potentes, pero las han hecho tan parecidas a estas que incluso cuentan con el mismo fallo, y es que no cuentan con un depurador hardware incorporado... ¿que les costaba meter un PIC18 al igual que hacen con los Starter Kit?, siendo suyo también el entorno de desarrollo no les hubiera supuesto ningún inconveniente..., y en ese momento llegaron Freescale, con la serie Freedom, y ST, con la serie Discovery, y, para mi, se hizo la luz. Estas dos series montan procesadores ARM Cortex M4 que corren hasta 168Mhz, e incluyen coprocesadores en punto flotante, y lo más importante para un desarrollador, cuentan cada una con su propio depurador hardware, con lo que podemos depurar casi en tiempo real nuestro programa, y ver en que punto deja de funcionar bien, o por el contrario, verificar el correcto funcionamiento.


Estas dos series de placas, aunque parecidas, tienen unas diferencias que las hacen estar lejos una de la otra, en primer lugar, Freescale optó por un pinout compatible con Arduino, es decir, todas las shields de Arduino se pueden utilizar en esta placa, cosa que en las discovery no encontramos, ya que su pinout se basa en dos tiras de pines, simples o dobles, en donde encontramos todos los pines del microcontrolador, cosa que en la Freedom no ocurre, ya que el pinout Arduino cuenta con pocos pines. Por último las placas Freedom cuentan con el entorno de desarrollo MBED, un compilador online con un lenguaje muy sencillo. Por tanto, si además de a los desarrolladores, queremos llegar al publico inexperto que está empezando con la electrónica, eso justo es lo que necesitamos, y eso es lo que ha hecho ST con las nuevas placas NUCLEO. 


Estas placas montan microcontroladores ARM, desde los M0, hasta el M4, y han adoptado el formato de las placas Arduino, por lo que son compatibles con todas las shields, ademas de ser programables mediante el entorno MBED, por lo que tenemos unas placas muy potentes, y fácilmente programables, pero... eso es Arduino no? exacto, pero además las placas NUCLEO cuentan con un depurador hardware ST-LINK, y esto significa muchas cosas, y se pueden resumir en que podemos crecer junto a esta plataforma, y ¿que significa crecer en este caso?, pues que si somos unos novatos,  y compramos una de estas placas, podemos utilizar el entorno online y diseñar un montón de programas de forma muy sencilla, y con muchos ejemplos, una vez nos hayamos soltado, y queremos empezar con la programación de verdad, bien por que se nos queda corto, o bien porque queremos explorar la placa a fondo, simplemente nos descargamos un entorno del estilo de Keil, y podemos programar la placa directamente, sin utilizar el firmware de MBED, cierto es que si queremos volver a MBED deberemos volver a instalar el firmware de origen. 


Como he dicho, la placa que he comprado es la que monta un Cortex M4 que funciona a 84Mhz, y lo mejor de estas placas es el precio, ya que las podemos encontrar desde unos 10-11 euros, por lo que en nuestro ranking virtual, estas placas estarían por delante de las Freedom.


En próximas entradas os explicare la forma tan sencilla de programar estas placas, y os aseguro que si os gusta programar microcontroladores, querréis comprar una. 

jueves, 31 de octubre de 2013

Unidad en punto flotante (FPU) Cortex M4

Cuando programamos cualquier algoritmo para un PC, ya sea en C, C++, VB.NET, Pascal... o cualquier otro lenguaje, no nos preocupamos de la cantidad o el tipo de datos que utilizamos, normalmente reina en nuestro subconsciente el, Más vale que sobre que no que falte. Esta metodología de programación es completamente válida, a no ser que estemos desarrollando programas en los que la velocidad de ejecución es crítica, y además estemos utilizando sistemas en tiempo real. Los potentes procesadores de PC procesan casi a la misma velocidad un dato del tipo entero, que uno en coma fija, o uno en coma flotante, o en caso de no hacerlo, como he dicho, no es demasiado relevante.
En cambio, si el procesador es mucho más limitado, tanto en velocidad, como en memoria, la cosa cambia drásticamente. Este tipo de limitaciones, las sufrimos, y mucho cuando programamos un microcontrolador, ya sea un PIC, o un potente ARM.
En general, los microcontroladores se desenvuelven muy bien si en nuestros programas introducimos operaciones con números enteros, y mejor si estos números tienen un tamaño igual o menor a la cantidad de bits que dispone en la unidad aritmético-lógica. En cambio, si necesitamos hacer operaciones con números no enteros, la cosa cambia, haciendo que para cualquier operación, el microcontrolador tenga que ejecutar varias decenas de instrucciones. Para este problema, existen 2 soluciones. La primera de ellas es trabajar en un formato de coma fija, o formato IQ, el cual se basa en codificar los números decimales, de forma que para el procesador son números enteros, y de esta forma operar con ellos más rápido. Trabajar con el formato IQ conlleva que para realizar una multiplicación, no podemos utilizar directamente el simbolo *, sino que tenemos que llamar a una función que, después de realizar la multiplicación, vuelva a codificar el número  adecuadamente. La otra opción es olvidarnos de cualquier tipo de codificación y  trabajar  directamente con variables del tipo float, lo cual hace nuestro programa mucho más lento... a no ser que el procesador cuente con una ALU especial  para este tipo de operaciones conocida  como FPU, o Floating Point Unit.
Esta unidad se encarga exclusivamente de operaciones en coma flotante, pudiendo realizar operaciones entre números float realmente rápido. Lo malo, es que esta unidad no se encuentra en la mayoría de los microcontroladores, de hecho, no conozco ningún PIC que la incorpore, y si  nos vamos a DSP de texas, tenemos que coger al menos un TMS320F28335, un DSP de gama alta, para encontrarlo. En cuanto a los ARM, la mayoría de los Cortex M4 si que disponen de una FPU, tanto la Tiva Launchpad de TI, como la STM32F4Discovery.
En esta entrada os voy a explicar como habilitar la FPU en la STM32F4Discovery, y en el vídeo podréis ver una comparativa entre la velocidad de una multiplicación en coma flotante con, y sin FPU. Para poder utilizar la FPU en el STM32F4 se debe introducir un fragmento de código en el archivo system_stm32f4xx.c, dentro de la función SystemInit(). El código es el siguiente:
// Código añadido para habilitar la FPU en el procesador

#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)

    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */

  #endif

Con este código le decimos al compilador que dispone de FPU, y luego en la configuración del proyecto, debemos decirle que la utilice.


A continuación os pongo un vídeo con la comparativa.



Espero os resulte interesante!!

viernes, 27 de septiembre de 2013

Conversor analógico digital en la STM32F0Discovery

Siguiendo con la programación del ARM Cortex M0, una vez visto el manejo de los puertos, y como utilizar los temporizadores, lo siguiente es como adquirir señales analógicas del exterior, en este caso, nuestra señal externa será la tensión del cursor de un potenciometro. Para hacer un código un poco, solo un poco, más complejo, vamos a mezclar el ultimo código que os puse, en el cual controlábamos el ciclo de trabajo de una señal PWM, pero ahora el ciclo de trabajo lo controlaremos directamente desde una entrada analógica.

El conversor que lleva el Cortex M0 está muy completo, además de llevar lo que llevan casi todos los micros (diferentes canales, diferentes formas de disparo, diferentes formas de leer los canales...), dispone de otras características un poco más especiales, como por ejemplo, poder elegir la resolución que queremos, pudiendo aumentar la velocidad de adquisición para resoluciones bajas. Ademas de los canales externos, 16 para el STM32F0, dispone de 3 canales internos los cuales monitorizan un sensor de temperatura, la tensión de referencia del conversor, y la tensión de la batería, en caso de que alimentemos el sistema desde una pila por ejemplo.
A continuación os dejo un vídeo explicativo


Y a continuación os dejo el código completo.
//=============================================================================
// Autor: P.Trujillo
// mipsandchips.blogspot.com.es
// Lectura de un canal analógico sin interrupción
//=============================================================================
 
#include "stm32f0xx.h"
 
//=============================================================================
// aux functions
//=============================================================================


//=============================================================================
// global vars
//=============================================================================
int dc = 50;

//=============================================================================
// main function
//=============================================================================
int main(void)
{ 
   
  RCC->AHBENR |= RCC_AHBENR_GPIOCEN ;  //Habilitamos el reloj para el puerto C
 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;  //Habilitamos el reloj para el timer 3
  RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //Habilitamos el reloj para el ADC
 
  GPIOC->MODER = GPIO_MODER_MODER8_1; //Puerto C8 como salida PWM
  GPIOA->MODER = GPIO_MODER_MODER0; // Puerto A0 como analógico
 
 TIM3->PSC = 12;
 TIM3->ARR = 4096; // Configuramos el valor de recarga con el valor máximo de la conversión
 TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE;
 TIM3->CCER = TIM_CCER_CC3E;
 TIM3->CR1 |= TIM_CR1_CEN;
 TIM3->CCR3 = 0;
 
 // Calibrar ADC
 ADC1->CR &= ADC_CR_ADCAL ;
 while(ADC1->CR &= ADC_CR_ADCAL);
 
 ADC1->CR = ADC_CR_ADEN;
 ADC1->CHSELR = ADC_CHSELR_CHSEL0; // Seleccionaoms el canal 0
 ADC1->CFGR1 = ADC_CFGR1_CONT;
 ADC1->CR = ADC_CR_ADSTART;
  
 
  while (1) {
    dc = ADC1->DR;
  TIM3->CCR3 = dc;
      
  }
}

domingo, 8 de septiembre de 2013

PWM en la STM32F0Discovery

Siguiendo el orden natural, una vez hemos visto como utilizar los temporizadores de los Cortex M0 que montan las placas discovery, lo siguiente que podemos aprender es a generar una señal de modulación de ancho de pulso (PWM). 
Como ocurre en todos los microcontroladores, las señales PWM van muy ligadas a los temporizadores, ya que son estos los que generan la base de tiempos, que luego se convertirá en nuestra frecuencia de conmutación. Sobre la rampa imaginaria que generan los temporizadores al ir incrementando la cuenta, se deslizan hasta 4 comparadores en los Cortex M0, dependiendo del temporizador que escojamos. El número de comparadores del que dispone cada timer lo podeis ver en la tabla de la entrada anterior.
El procedimiento para empezar a generar señales PWM es muy sencillo, lo primero que debemos hacer es configurar el temporizador, de forma que el periodo de este se corresponda con nuestra frecuencia deseada de conmutación del PWM, además de decirle que el temporizador funcionará en modo PWM. Una vez configurado, debemos habilitar en primer lugar el uso de comparadores y luego habilitar el comparador que vayamos a utilizar, de forma que quede así:
TIM3->PSC = 47;
TIM3->ARR = 100;
TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE;
TIM3->CCER = TIM_CCER_CC3E;
TIM3->CR1 |= TIM_CR1_CEN;
Una vez configurado mediante el registro CCR3 establecemos el punto de comparación. En el siguiente vídeo podeis ver el proceso completo, además de como utilizar el depurador de Keil uVision.

Y a continuación teneis el código completo que he desarrollado en el vídeo.
/=============================================================================
// Autor: P.Trujillo
// mipsandchips.blogspot.com.es
// Generación de señal PWM en la placa STM32F0Discovery
//=============================================================================
 
#include "stm32f0xx.h"
 
//=============================================================================
// aux functions
//=============================================================================


//=============================================================================
// global vars
//=============================================================================
int dc = 50;

//=============================================================================
// main function
//=============================================================================
int main(void)
{ 
   
  RCC->AHBENR |= RCC_AHBENR_GPIOCEN ; //Habilitamos el reloj para el puerto C
 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; //Habilitamos el reloj para el timer 3
  
  GPIOC->MODER = GPIO_MODER_MODER8_1; //Puerto C8 como salida PWM
  
 TIM3->PSC = 47;
 TIM3->ARR = 100;
 TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE;
 TIM3->CCER = TIM_CCER_CC3E;
 TIM3->CR1 |= TIM_CR1_CEN;
 
 TIM3->CCR3 = 50;
 
  while (1) {
    
  TIM3->CCR3 = dc;
      
  }
}

viernes, 23 de agosto de 2013

Interrupciones en la STM32F0Discovery

En esta ocasión os voy a contar como utilizar las interrupciones en los microcontroladores STM32F0. En el blog ya he hablado de las interrupciones en los microcontroladores PIC de Microchip y de como se activan y configuran, pues ahora vamos a hacer lo mismo pero esta vez con el ARM Cortex M0 que monta la placa STM32F0Discovery.
En el ejemplo que he desarrollado en el vídeo vais a ver que es bastante fácil, tan solo tenemos que activar la interrupción mediante el bit correspondiente del registro DIER.
TIM3->DIER |= TIM_DIER_UIE;

Una vez activado, lo siguiente es habilitar el vector de interrupción, es decir, decirle al procesador que en el caso de que se produzca la interrupción, a que posición de memoria debe ir, para eso ejecutamos la siguiente instrucción:
NVIC_EnableIRQ(TIM3_IRQn);

Una vez hecho esto, la interrupción ya está lista, tan solo tenemos que escribir el código que debe ejecutarse en caso de que se produzca la interrupción:
void TIM3_IRQHandler(void){

     // Código de la interrupción 

}

A contiuación teneis un vídeo explicativo.

Por último aquí teneis el código completo del vídeo.
//=============================================================================
// Autor: P.Trujillo
// mipsandchips.blogspot.com.es
// Parpadeo de los leds de la placa discovery alternativamente con interrupciones
//=============================================================================
 
#include "stm32f0xx.h"
 
//=============================================================================
// aux functions
//=============================================================================


//=============================================================================
// global vars
//=============================================================================
char led_stat = 0;

//=============================================================================
// main function
//=============================================================================
int main(void)
{ 
   
  RCC->AHBENR |= RCC_AHBENR_GPIOCEN ; //Habilitamos el reloj para el puerto C
 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; //Habilitamos el reloj para el timer 3
  
  GPIOC->MODER = GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0; //Puerto C8 y C9 como salida
  GPIOC->ODR = !GPIO_ODR_8|GPIO_ODR_9;
 
 TIM3->PSC = 47999;
 TIM3->ARR = 1000;
 TIM3->DIER |= TIM_DIER_UIE;
 TIM3->CR1 |= TIM_CR1_CEN;
 
 NVIC_EnableIRQ(TIM3_IRQn); 
 
  while (1) {
    
      
  }
}

void TIM3_IRQHandler(void){
 
 TIM3->SR &= ~TIM_SR_UIF; //Borrar el flag de interrupción
 
 if(led_stat){
  GPIOC->ODR = GPIO_ODR_8|!GPIO_ODR_9;
  led_stat = 0;
 }
 else{
  GPIOC->ODR = !GPIO_ODR_8|GPIO_ODR_9;
  led_stat = 1;
 } 
}

//=============================================================================
// End of file
//=============================================================================

sábado, 17 de agosto de 2013

Temporizaciones en STM32F0

Siguiendo con los primeros pasos con la placa STM32F0Discovery, una vez tenemos controlados los GPIO, lo siguiente que más vamos a utilizar en cualquier diseño son las temporizaciones, y para ello, el Cortex M0 tiene bastantes posibilidades, en concreto dispone de 8 timers de proposito general, cada uno con características diferentes, además del timer de sistema llamado SysTick. Los timers de proposito general son el 1, 2, 3, 6, 14, 15, 16 y 17, siendo el 6 el más básico, y el 1 el más completo, con el que podemos generar señales PWM, captura de señales, salidas de comparación con hasta 4 comparadores... en la siguiente tabla podéis ver una comparativa de los timers.

Como veis cada uno lo podríamos utilizar para una aplicación diferente, por ejemplo los que disponen de salidas complementarias, los podríamos utilizar para el control de fuentes conmutadas o control de motores. Los que disponen de 4 comparadores se pueden utilizar para el control de inversores por ejemplo.
Para configurar los timers tan solo tenemos que modificar 2 registros, el registro de preescaler PSC, y el registro de autorecarga ARR, que se corresponde con el número de cuentas que debe hacer el temporizador, de forma que el número total de cuentas es (PSC+1) * ARR Además de estos dos, debemos habilitar el timer, desde el registro de control 1 CR1, además de llevar la señal de reloj a este.
En el siguiente vídeo tenéis explicado un ejemplo de Hola Mundo utilizando el timer 3.



El código que se ha desarrollado en el vídeo es el siguiente:

//=============================================================================
// Autor: P.Trujillo
// mipsandchips.blogspot.com.es
// Parpadeo de los leds de la placa discovery alternativamente
//=============================================================================
 
#include "stm32f0xx.h"
 
//=============================================================================
// main function
//=============================================================================
int main(void)
{ 
   
  RCC->AHBENR |= RCC_AHBENR_GPIOCEN ; //Habilitamos el reloj para el puerto C
 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; //Habilitamos el reloj para el timer 3
  
  GPIOC->MODER = GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0; //Puerto C8 y C9 como salida
  GPIOC->ODR = GPIO_ODR_8|GPIO_ODR_9;
 
 TIM3->PSC = 47999;
 TIM3->ARR = 1000;
 TIM3->CR1 |= TIM_CR1_CEN;
 
 
  while (1) {
    
  while(!(TIM3->SR & TIM_SR_UIF));
  TIM3->SR &= ~TIM_SR_UIF;
  GPIOC->ODR = GPIO_ODR_8|!GPIO_ODR_9;
  while(!(TIM3->SR & TIM_SR_UIF));
  TIM3->SR &= ~TIM_SR_UIF;
  GPIOC->ODR = !GPIO_ODR_8|GPIO_ODR_9;

    
  }
}

Como ya os dije, la programación de estos micros no es mas complicada que a de los DSP de texas o los PIC de microchip, tan solo hay que cambiar un poco la forma de llamar a los registros, y por supuesto, su nombre. Espero que os sea útil!

jueves, 8 de agosto de 2013

Crear un proyecto en Keil uVision

En el siguiente video-tutorial podeis ver como crear un proyecto desde cero para la placa STM32F0Discovery con la herramienta Keil uVision.

jueves, 1 de agosto de 2013

Primeros pasos con el STM32F0.

Durante estas ultimas semanas he estado probando un poco más a fondo la placa STM32F0DISCOVERY, y la verdad que aunque al principio la programación se me hacia complicada, al final se basa en lo mismo que todos los microcontroladores, buscar el registro del periferico que queremos configurar en el datasheet, y asignar valores a los diferentes bits. En un principio habia pensado en hacer los programas utilizando ciertas librerias que nos da ST, pero eso haria necesario saber como funciona la libreria, sin embargo de la otra forma, tan solo he de ir al datasheet y buscar el registro que quiero. Es cierto que de esta forma, el código no queda tan simple a primera vista, pero es lo mejor si luego queremos migrar a otro microcontrolador.
El primer ejemplo que he realizado es muy básico, y se trata de un hola mundo en el que parpadea un led, en principio con una frecuencia sin determinar. Lo primero que hay que hacer es habilitar la señal de reloj para el puerto que queramos utilizar. Esto, para el puerto C lo hacemos desde el registro AHBENR poniendo el bit del GPIOC a 1. Lo siguiente es configurar el puerto, para ello, aunque existen bastantes registros, en principio solo nos vamos a fijar en 2:
  • GPIOx_MODER, con el que le diremos si el pin es de entrada, salida, función alternativa (SPI, UART...), o si se va a utilizar como entrada analógica.
  • GPIOx_OTYPER, mediante el cual, si el pin está configurado como salida, le decimos que tipo de salida queremos, push-pull o drenador abierto.
Una vez hemos configurado el puerto, podemos proceder a escribir en el, y esto se puede hacer 2 formas diferentes, utilizando instrucciones atomicas (se ejecutan en un ciclo de reloj), o no utilizándolas, así pues, si las queremos utilizar existe 1 registro que debemos modificar:
  • GPIOx_BSRR, el cual es un registro de 32 bits que dividido en 2 partes, los 16 bits de la parte alta llamados BRx (x = nº de pin), ponen a cero el pin que seleccionemos, es decir si queremos poner el GPIOC2 a cero, pues asignaremos a este registro 0x0200, y la parte baja, llamados BSx, ponen a uno el bit seleccionado. Como he dicho, esto se realiza en una sola instrucción.
En cambio, si nos da lo mismo utilizar instrucciones atomicas que no, existen otro registro que hace la misma función que este:
  • GPIOx_ODR, (Output Data Register), desde el cual podemos escribir directamente el valor que queramos en el bit correspondiente, ya sea un 1 o un 0. 
En el caso de que queramos leer el valor de un pin utilizaremos el registro:
  • GPIOx_IDR, (Input Data Register), el cual simplemente leemos el bit que queremos del puerto y ya está.
En el programa que os pongo a continuación, en lugar de poner directamente e valor del registro, utilizo unos defines que están en la librería stm32f0xx.h, los cuales mediante or, vamos aponiendo los diferentes bits a una o cero.
//=============================================================================
// Autor: P.Trujillo
// mipsandchips.blogspot.com.es
// Parpadeo de los leds de la placa discovery alternativamente
//=============================================================================

#include "stm32f0xx.h"

//=============================================================================
// main function
//=============================================================================
int main(void)
{ 
  int led_stat = 0;
 
  RCC->AHBENR |= RCC_AHBENR_GPIOCEN ; //Habilitamos el reloj para el puerto C
 
  GPIOC->MODER = GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0; //Puerto C8 y C9 como salida
  GPIOC->ODR = GPIO_ODR_8|GPIO_ODR_9;

  while (1) {
   
   GPIOC->ODR = GPIO_ODR_8|!GPIO_ODR_9;
   delay();
   GPIOC->ODR = !GPIO_ODR_8|GPIO_ODR_9;
   delay();
   
  }
}
//=============================================================================
// End of file
//=============================================================================
La función delay() en principio puede ser un simple for que genere un retardo en el procesador. Como veis no es diferente de la programación de PIC, ni de os TMS320 de TI. Seguiré poniendo más ejemplos para estos ARM pronto!

sábado, 20 de julio de 2013

STM32F0 y STM32F4 Discovery

En al entrada en la que hablaba de NETMF, os comenté que existía una placa muy barata con la que se pueden hacer pruebas con este Framework. Hace una semana me llegó a casa (previo pago de 30 euros), un pedido que hice a RS, en el cual iba la susodicha placa STM32F4Discovery, además de su hermana pequeña, la STM32F0Discovery. Las dos placas montan microcontroladores ARM Cortex M, la primera de ellas como ya dije lleva un ARM CORTEX M4 (168MHz, 1MB), los cuales son el tope de gama de la serie CORTEX. La otra de las placas lleva un ARM CORTEX M0 (48MHz, 64kB), el cual se corresponde con la gama más baja de la serie. Como he dicho, el precio de las dos placas, más el iva, más los gastos de envío ha sido de 30 euros, el cual es un precio bajo comparado con casi cualquier placa de desarrollo, incluso sale más barato casi que comprar un Arduino.


Todas las placas discovery, lleva incorporado el programador/depurador STLink, lo que está realmente bien ya que tan solo debemos comprar una placa y podremos empezar a trabajar. Como es habitual, estas placas de desarrollo suelen llevar un hardware muy básico para probar los periféricos. En el caso de la STM32F0 disponemos de 2 leds de usuario, y un pulsador para utilizarlo en nuestros primeros diseños. En el caso de la STM32F4 el hardware del que dispone la placa es bastante completo. Como en el caso anterior disponemos de un pulsador de usuario, 4 leds de usuario además de 2 leds que nos indican el estado de la comunicación USB a través de un puerto USB OTG. Además de esto, dispone también de un acelerómetro (LIS302DL), un micrófono omnidireccional (MP45DT02), y un conversor analógico - digital (CS43L22), el cual va conectado a una salida de audio, con lo que solo con la placa ya podemos desarrollar varios proyectos.


En cuanto a la programación de estas placas, hasta ahora no es que haya encontrado muchos ejemplos por internet, pero hay suficientes para ir tirando. Lo primero que se debe hacer es elegir el IDE que vamos a utilizar para programarlas. En mi caso estoy utilizando Keil uVision, un IDE basado en (oh que sorpresa!) Eclipse, por lo que ya me es algo familiar, aunque poco. El mismo IDE ya nos proporciona ejemlos básicos para casi todos los ARM disponibles del mercado, y son muchisimos porque hay que tener en cuenta la gran cantidad de empresas que los implementan en sus microcontroladores. Después dentro de cada empresa, divide los ejemlos en sus diferentes placas de desarrollo. En el caso de ST podemos encontrar ejemplos para todas las placas discovery, además de otras.


Como he dicho los ejemplos que hay son muy básicos, y se limitan al típico blinky. Aquí os pongo el ejemplo básico que nos da Keil para la STM0Discovery.
void LED_Init (void) {

  /* Enable clock for GPIOC                                                   */
  RCC->AHBENR |= (1UL << 19);

  /* Configure LED (PC.8..9) pins as push-pull outputs */
  GPIOC->MODER  &= ~((3UL << 2 * 8) | (3UL << 2 * 9));
  GPIOC->MODER  |=  ((1UL << 2 * 8) | (1UL << 2 * 9));
  GPIOC->OTYPER &= ~((1UL <<     8) | (1UL <<     9));

}
void LED_On (uint32_t num) {

  if (num < LED_NUM) {
    GPIOC->BSRR |= (led_mask[num]);
  }
}
void LED_Off (uint32_t num) {

  if (num < LED_NUM) {
    GPIOC->BSRR |= (led_mask[num] << 16);
  }
}
int main (void) {
  int32_t num = -1; 
  int32_t dir =  1;
 uint32_t btns = 0;

  SystemCoreClockSetHSI();

  SystemCoreClockUpdate();                      /* Get Core Clock Frequency   */
  if (SysTick_Config(SystemCoreClock / 1000)) { /* SysTick 1 msec interrupts  */
    while (1);                                  /* Capture error              */
  }

  LED_Init();
  BTN_Init();                             
 
  while(1) {                                    /* Loop forever               */
    btns = BTN_Get();                           /* Read button states         */

    if (btns != (1UL << 0)) {
      /* Calculate 'num': 0,1,...,LED_NUM-1,LED_NUM-1,...,1,0,0,...  */
      num += dir;
      if (num == LED_NUM) { dir = -1; num =  LED_NUM-1; } 
      else if   (num < 0) { dir =  1; num =  0;         }

      LED_On (num);
      Delay( 50);                               /* Delay 50ms                 */
      LED_Off(num);
      Delay(450);                               /* Delay 450ms                */
    }
    else {
      LED_Out (0x0F);
      Delay(10);                                /* Delay 10ms                 */
    }

  }
  
}
Parece chino de momento. Además de los ejemplos que nos da Keil, podemos descargarnos desde la página de ST los ejemplos de periféricos para cada placa y para 4 IDEs diferentes, en el caso de la STM32F0 podeis descargar los ejemlos aquí,  y para la STM32F4 aquí. En este pack si que hay ejemlos para muchos de los perifericos que dispone el CORTEX M4, GPIO, ADC, DAC, DMA Timers... Estos ejemlos hacen uso de librerias de ST, por lo que como vais a ver son bastante más sencillos. Aunque en esta ocasión el ejemplo lo he programado yo, y lo he cambiado ligeramente del que nos da ST llamado IO_Toogle.

/*
 Proyecto:   HolaMundo:
 Archivo:   main1.c
 Autor:    P.Trujillo
 Descripción: Manejo de las salidas digitales de la placa STM32F0Discovery
*/

// Incluimos las librerias básicas
#include "stm32f0xx.h"
#include "stm32f0_discovery.h"

// Incluimos las librerias nuestras
#include "main.h"

// Programa principal
int main(){
 
 init_discovery();
 
  // Poner el led a 1
 GPIOC->BSRR = GPIO_Pin_9;      // Forma 1
 //GPIO_SetBits(GPIOC, GPIO_Pin_9); // Forma 2
 
 // Poner el led a 0
 GPIOC->BRR = GPIO_Pin_9;
 //GPIO_ResetBits(GPIOC, GPIO_Pin_9);
  
 // Bucle
 while(1){
  
  if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
  {
   GPIO_SetBits(GPIOC, GPIO_Pin_8);
   GPIO_ResetBits(GPIOC, GPIO_Pin_9);
  }
  else
  {
   GPIO_ResetBits(GPIOC, GPIO_Pin_8);
   GPIO_SetBits(GPIOC, GPIO_Pin_9);
  }
 }
}

void init_discovery(){
 
 // Creamos una estructura del tipo GPIO_InitTypeDef para definir el puerto
 GPIO_InitTypeDef GPIO_InitStructure;
 
 // Habilitamos el reloj en el puerto GPIOC
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
 
  // Configuramos los pines de los leds
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
 
 // Configuramos el pin del pulsador
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); 
 GPIO_StructInit(&GPIO_InitStructure);   // establecer valores por defecto    
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;        // PA0 es el pulsador
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;     // pin como entrada
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // desactivar los pull
 GPIO_Init(GPIOA, &GPIO_InitStructure);  
}
En proximas entradas haré más ejemlos para poder empezar a desarrollar pequeños proyectos con los microcontroladres ARM.

viernes, 28 de junio de 2013

NET MicroFramework

Por motivos de trabajo he empezado a programar una placa de desarrollo llamada NETDUINO, que, como todas las xDUINO, tiene el mismo formato de las placas que todos sabéis, pero estas se diferencias de las Arduino y derivados en una cosa, se pueden programar tanto en Visual Basic, como en C#, y para ello se basan en .NET MicroFramework.


Este mini FrameWork, tiene muchas de las clases y tipos que su hermano mayor, pero no todas, además que dispone de .dll específicas para manejar hardware, por ejemplo puertos GPIO, lecturas analógicas, PWM, incluso podemos crear timers. Como he dicho, la utilización de esta herramienta nos permite programar un microcontrolador ya sea en Visual Basic, o en C#, y desde el mismo entorno Visual Studio. Una de las cosas buenas que tiene utilizar este "método de programación" es la compatibilidad entre placas, es decir, yo diseño un programa para un ARM Cortex M3, y si lo quiero correr en un M4, no hay problema. El problema viene cuando queremos correrlo en otro micro que no tenga una arquitectura ARM. Aunque los requisitos para mover el NETMF no son exagerados, unos 80MHz y 512 de FLASH, no he visto ninguna página que lo hayan hecho correr, por ejemplo, en un PIC32MX7, el cual cumple los requisitos. De hecho si nos vamos a la página oficial nos dice que solo es soportado por 3 arquitecturas, ARM, ADI Blackfin y Renesas SH2, lo que deja fuera la arquitectura MIPS32, La placa que yo utilizo en el trabajo, como ya he dicho es una NETDUINO 2 PLUS, que monta un ARM STM32F4, e incorpora ETHERNET mediante el controlador ENC28J60, su precio es de 65 euros, algo muy exagerado en mi opinión cuando existen en el mercado opciones como la STM32F4DISCOVERY, que monta el mismo procesador pero de 100 patillas, con algunos periféricos como leds, decodificador de audio y acelerómetro y lo tenemos en MOUSER por 12 euros, si queremos añadirle Ethernet, existe la opción de adquirir la DISCOVERY EXTENSION BOARD por 33 euros, que saca los pines de la placa hacia arriba, ademas de otorgar a la placa de un conector RS232 y uno Ethernet.

Si queremos la pantalla y la cámara el precio se encarece más pero por 55 euros podemos tener un equipo mucho mejor que la NETDUINO y más barato.  A continuación os dejo un código para la NETDUINO escrito en C#, el típico blinkin led.

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

/* NOTE: make sure you change the deployment target from the Emulator to your Netduino before running this
 * Netduino sample app.  To do this, select "Project menu > Blinky Properties > .NET Micro Framework" and 
 * then change the Transport type to USB.  Finally, close the Blinky properties tab to save these settings. */

namespace Blinky
{
    public class Program
    {
        public static void Main()
        {
            // write your code here
            OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);

            while (true)
            {
                led.Write(true);
                Thread.Sleep(250);
                led.Write(false);
                Thread.Sleep(250);
            }

        }

    }
}

A ver si me puedo hacer con una STM32F4DISCOVERY y puedo poneros más ejemplos.

domingo, 16 de junio de 2013

Energía. Programar Stellaris o MSP430 como Arduino.

Desde que Arduino de popularizó, poco a poco todas las grandes empresas de electrónica van abriendo camino en esa dirección. Primero fué Microchip, con su plataforma CHIPKIT, la cual incorpora un IDE similar al de Arduino. Otra de estas empresas fué Cypress, la cual también ha sacado una placa con un PSOC4 compatible con Arduino, y ahora es Texas Instruments la que, después de sacar su gama Launchpad, se atreve con un IDE similar al de Arduino, el cual podemos encontrar por ahí como ENERGIA.


El IDE es prácticamente el mismo, cambiando el color, incluso podemos encontrar muchos de los ejemplos que existen para Arduino, aunque no tantos como se encuentras para las ChipKit, aunque si tenemos en cuenta el tiempo que tiene esta plataforma, y que se alimenta de los ejemplos que  suben los usuarios es normal que todavía haya pocos, pero conforme pase el tiempo, y la comunidad vaya creciendo, el número de ejemplos aumentará también.
Aunque el IDE sea idéntico al de Arduino, las placas Launchpad tienen poco que ver con estas, al contrario que pasa por ejemplo con las ChipKit, que el formato de forma es idéntico. Por tanto el número de los pines y sus funciones difieren, y los nuevos mapeados los podemos encontrar aquí para el MSP430, y aquí para el Stellaris. Aunque el IDE no está disponible todavía para el Launchpad C2000, en la página informan de que estará pronto.
A continuación os pongo un ejemplo del código "fadding" de Arduino, modificado para funcionar en el MSP430 Launchpad.

int ledPin = 4;    
//int ledPin = 14;    

void setup()  { 
  // nothing happens in setup 
} 

void loop()  { 
  // fade in from min to max in increments of 5 points:
  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);         
    // wait for 30 milliseconds to see the dimming effect    
    delay(30);                            
  } 

  // fade out from max to min in increments of 5 points:
  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { 
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);         
    // wait for 30 milliseconds to see the dimming effect    
    delay(30);                            
  } 
}
Como veis el código es  idéntico al de arduino, solo que en el caso del MSP430 tan solo disponemos de 2 pines con salida PWM, el 4 y el 14. Este mismo código puede funcionar en la Stellaris, en la cual tenemos bastantes más pines de PWM disponibles. 
Como ya sabéis, no soy fan ni de Arduino, ni de su lenguaje, ya que me parece que está bastante limitado tanto en eficiencia como en optimización de código, pero no deja de ser interesante que podamos escribir un codigo para un AVR, pasarlo a un PIC32 sin cambiar casi nada, y si no nos convence, utilizar un ARM M4F como es la Stellaris, incluso si nuestro proyecto está limitado en cuanto a consumo, podemos utilizar un procesador de ultra bajo consumo como es un MSP430.