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

martes, 25 de mayo de 2021

Manejo de un motor CC con una tarjeta EV-VNH7100AS

 ➤ Programa

/* Mayo de 2021
Tarjeta: NUCLEO
Microcontrolador: STM32F446RET6U
(Frecuencia de reloj empleada: 16 MHz)
IDE: mikroC PRO for ARM v.6.2.0
Programa que genera una secuencia cíclica de avance y frenado de un motor CC, utilizando
 una tarjeta EV-VNH7100AS. Se emplean los pines PC5 (INA), PC6 (INB), PC8 (SEL0) 
y PB7 (PWM) de la tarjeta NUCLEO:
- Avance dextrógiro:  INA=1, INB=0, SEL0=1
- Avance levógiro:    INA=0, INB=1, SEL0=0
- Frenado del motor:  INA=1, INB=1, SEL0=0
La señal SEL0 no influye en el avance, sirve para poder medir la corriente que circula por 
el puente. La señal PWM se genera en el pin PB7 de la tarjeta NUCLEO.
*/

//--------------------------- Constantes y variables globales
#define av_dextrogiro 0x00000120;
#define av_levogiro 0x00000040;
#define frenado 0x00000060;
int x = 1;                                                             // Permite modificar el ciclo de trabajo del PWM


//--------------------------- Función para PWM
void pwm_PB7(int i){
  unsigned int periodo_pwm;
  periodo_pwm = PWM_TIM4_Init(5000);       // Frecuencia: 5 KHz
  PWM_TIM4_Start(_PWM_CHANNEL2, &_GPIO_MODULE_TIM4_PB7);
  Delay_ms(1);
  PWM_TIM4_Set_Duty(periodo_pwm/i,  _PWM_NON_INVERTED, _PWM_CHANNEL2);
}

//--------------------------- Función principal
void main (void) {
  RCC_AHB1ENR |= 0x00000004;                  // Habilita el reloj para el puerto C
  GPIOC_MODER |= 0x00011400;                  // Configura PC5, PC6 y PC8 como salidas
  
  pwm_PB7(x);                                                  // Genera una señal PWM en PB7

  while (1) {
    GPIOC_ODR = av_dextrogiro;                    // Escribe en el puerto C
    delay_ms(5000);
    GPIOC_ODR = frenado;
    delay_ms(2000);
    GPIOC_ODR = av_levogiro;
    delay_ms(5000);
    GPIOC_ODR = frenado;
    delay_ms(2000);
  }
}


 ➤ Circuito

Se utiliza:
- Una tarjeta EV-VNH7100AS
- Una tarjeta NUCLEO-F446RE
- Un motor de corriente continua
- Una batería de 12 V o una fuente de alimentación




➤ Observaciones

- La siguiente tabla detalla el patillaje del circuito integrado VNH7100AS, que es el que emplea la tarjeta EV-VNH7100AS.



- La tabla anterior también se obtiene de la hoja de datos del VNH7100AS e indica sus modos de funcionamiento:
  • Rojo: frenado del motor
  • Azul: avance dextrógiro
  • Verde: avance levógiro 
- El programa realizado está basado en la tabla anterior. La secuencia de avance y de frenado del motor se efectúa utilizando comandos que escriben directamente en el puerto C del microcontrolador los valores de INA, INB y SEL0. La señal PWM, en cambio, se genera empleando órdenes propias de mikroC for ARM.

- La siguiente imagen corresponde al esquema electrónico de la tarjeta EV-VNH7100AS. 



- El pin CS del circuito integrado VNH7100AS entrega una corriente proporcional a la del motor. Mediante el circuito de la imagen anterior se consigue una tensión a partir de esta corriente. La tensión obtenida podría medirse mediante una de las entradas analógicas de la tarjeta NUCLEO, pero el programa descrito arriba no efectúa esta lectura.

- El pin SEL0, en combinación con INA e INB, selecciona la información obtenida de CS, de acuerdo con la tabla de verdad anterior. 

viernes, 7 de abril de 2017

Generación de un retardo -ARM Cortex-M4-

Programa

/* Marzo de 2016
Tarjeta: STM32 Discovery
Microcontrolador: STM32F411VET6U
IDE: IAR Embedded Workbench
Programa que produce el parpadeo cíclico de LED verde (PD12) de la tarjeta
STM32 Discovery cada segundo. El retardo se genera manejando Systick.
*/

#include "stm32f4xx.h"

//--- Función que inicializa el puerto D y configura PD12 ---
void ini_LED_verde(void){
  RCC->AHB1ENR   |= 0x00000008;       // Habilita el reloj para el puerto D
  GPIOD->MODER   |= 0x01000000;       // Configura el pin 12 como salida
  GPIOD->OSPEEDR |= 0x03000000;      // PD12 podrá funcionar a alta velocidad 
}

//--- Función que configura Systick ---
void config_systick_retardo(void) {
  SysTick->CTRL &= ~(SysTick_CTRL_CLKSOURCE_Msk); // La señal de reloj para
                                                                                                       // Systick es AHB / 8
                                                                                                       // ( = 12 MHz, en este caso)
  SysTick->LOAD  = 12000 - 1;        // Systick contará 12000 ciclos de una
señal de reloj de 12 MHz
 }

//--- Función que genera un retardo en milisegundos igual a num_ms ---
void retardo_ms(uint32_t num_ms) {
  SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;           // Habilita Systick
  while (num_ms != 0) {
    // Espera hasta que el valor del bit COUNTFLAG del registro de control de
Systick sea igual a '1'
    while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) {}
    --num_ms;
  }
  SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);    // Deshabilita Systick
}

//--- Función principal del programa ---
void main (void)  {        
  ini_LED_verde();                 
  config_systick_retardo();           
    
  while (1) {
    GPIOD->BSRRL = 0x1000;         // Enciende el LED
    retardo_ms(1000);                         // Retardo de 1 segundo 
    GPIOD->BSRRH = 0x1000;         // Apaga el LED    
    retardo_ms(1000);                         // Retardo de 1 segundo 
   }
}




➤ Observaciones

- No es necesario ningún componente electrónico externo a la tarjeta Discovery, dado que se utiliza el LED verde de la misma.

- El programa accede a los siguientes registros: RCC_AHB1ENR, GPIOD_MODER, GPIOD_OSPEEDR,  STK_CTRLSTK_LOAD. 

- En este programa se genera un retardo mediante el temporizador del sistema, SysTick.

- SysTick es un temporizador pensado para sistemas operativos en tiempo real, pero también puede ser usado como contador descendente estándar. Dispone de: un contador descendente de 24 bits, capacidad de auto-recarga, un sistema de generación de interrupciones cuando el contador llega a 0 y una fuente de señal de reloj programable.


- SysTick cuenta de manera descendente desde el valor de carga hasta 0, recarga ese valor en el registro STK_LOAD en el siguiente flanco de reloj y entonces cuenta descendentemente en los siguientes ciclos de reloj. Es decir, cuenta cíclicamente desde el valor cargado en STK_LOAD hasta 0.

- config_sysTick_retardo(): efectúa una llamada a la función encargada de configurar SysTick.

- retardo_ms(1000): llama a la función que crea el retardo valiéndose de SysTick. En este caso, la función llamada crea un retardo de 1000 milisegundos. 


- SysTick->CTRL &= ~(SysTick_CTRL_CLKSOURCE_Msk): selecciona la fuente de la señal de reloj para SysTick. En este caso, poniendo a ‘0’ el bit CLKSOURCE del registro STK_CTRL (bit 2), se decide que la señal de reloj de SysTick sea AHB / 8, que es la frecuencia a la salida del prescaler AHB dividida entre 8. En la entrada anterior del blog se había elegido una frecuencia para AHB de 96 MHz. La constante SysTick_CTRL_CLKSOURCE_Msk está definida en el archivo core_m4.h, al igual que el resto de constantes relacionadas con SysTick y empleadas en este programa.


- SysTick->LOAD = 12000 – 1: carga el valor ‘11999’ en el registro STK_VAL (bits 23:0, RELOAD). Este valor se carga en el registro STK_VAL cuando el contador está habilitado y alcanza 0. El valor de RELOAD puede ser cualquiera en el rango comprendido entre ‘0x00000001’ y ‘0x00FFFFFF’.


- El valor de RELOAD se calcula según su uso: para generar un temporizador multidisparo con un periodo de N ciclos de reloj del procesador, hay que usar un valor de RELOAD de N-1. Por ejemplo, si se requiere una interrupción de SysTick cada 100 pulsos de reloj, RELOAD tiene que valer 99. 


- Según el apartado 10.1.2 del documento
RM0383 Reference Manual, el valor de calibración está fijado en 10500, lo que da una referencia de la base de tiempos de 1 ms para una frecuencia de reloj de SysTick de 10,5 MHz (HCLK/8, con HCLK ajustado a 84 MHz). En este programa, el valor de RELOAD hace que SysTick cuente 12000 ciclos de una señal de reloj de 12 MHz; para efectuar esta operación es necesario 1 milisegundo de tiempo.

- SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk: habilita el contador, escribiendo un ‘1’ en el bit ENABLE del registro SysTick->CTRL. Cuando este bit está a ‘1’ el contador carga el valor de RELOAD desde el registro STK_LOAD y empieza a contar de manera descendente. Al llegar a 0, pone el bit COUNTFLAG (bit 16) a ‘1’ y opcionalmente activa la petición de excepción, dependiendo del valor de TICKINT, que es el bit 1 del registro STK_CTRL (en este ejemplo no se habilita la petición de excepción). Después de esto, carga el valor de RELOAD otra vez y sigue contando.


- while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) {}: esta instrucción sirve para esperar hasta que el valor del bit COUNTFLAG del registro STK_CTRL sea igual a ‘1’. El bit COUNTFLAG devuelve un ’1’, si la cuenta del temporizador ha llegado a ‘0’; cuando sucede esto, que es cada milisegundo, se decrementa en una unidad el valor numérico contenido en la variable num_ms.


- SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk): deshabilita el contador, poniendo a ‘0’ el bit ENABLE del registro SysTick_CTRL. Esto es necesario porque mientras este bit esté habilitado el contador seguirá contando de manera cíclica. 



➤ Registros empleados

Las siguientes imágenes representan una parte de los registros utilizados en el programa y en ellas están señalados los bits que éste modifica o consulta. Únicamente aparecen los registros relacionados con la generación del retardo, los demás pueden encontrarse en las primeras entradas del blog.

Para más información, ver los documentos RM0383 Reference Manual y PM0214 Programming manual.










jueves, 6 de abril de 2017

Señal de reloj -ARM Cortex-M4-


La señal SYSCLK, que es el reloj del sistema, puede ser generada de tres maneras diferentes (ver siguiente figura):
- Desde un oscilador interno de 16 MHz (HSI).

- Desde un oscilador externo (HSE).
- Mediante un PLL (PLLCLK), el cual puede modificar la señal creada por HSI o por HSE.

Los periféricos del microcontrolador (salidas digitales, temporizadores, USART, etc.) utilizan frecuencias de reloj iguales o más bajas que SYSCLK, dependiendo de los valores configurados para los prescalers (AHB, APBx) y dependiendo también de qué prescaler esté asociado el periférico.


La fuente de señal de reloj que se emplea en los ejemplos de este blog es PLLCLK. En concreto, lo que se hace es modificar la señal de reloj procedente del cristal X2 de la tarjeta Discovery (HSE), que es de 8 MHz y es externo al microcontrolador.


Las frecuencias de reloj configuradas para los programas de este blog están detalladas en la siguiente figura. La configuración se realiza teniendo en cuenta que la frecuencia máxima para esta familia de microcontroladores es de 100 MHz (ver la señal SYSCLK en la figura anterior). También se consideran las frecuencias máximas a la salida de los prescalers (divisores de frecuencia), según lo indicado en el apartado 6.2 del documento RM0383 Reference Manual: AHB: 100 MHz, APB2: 100 MHz y APB1: 50 MHz.



La configuración de la señal de reloj se lleva a cabo gracias a los siguientes archivos (ver este enlace) y considerando el circuito de la figura anterior:
- startup_stm32f4xx.s
- system_stm32f4xx.c
- stm32f4xx.h

Hay que tener en cuenta lo siguiente:
- Existen versiones más recientes de los anteriores archivos que las empleadas aquí.
- Los valores de frecuencia y los factores de división y de multiplicación, indicados en la figura anterior, pueden ser otros, dependiendo de la frecuencia de reloj deseada y de cómo se obtenga ésta matemáticamente. Aunque siempre se han de tener en cuenta las frecuencias máximas de funcionamiento.

Mediante el código de startup_stm32f4xx.s se llama a la función SystemInit (ver siguiente figura), que está definida en system_stm32f4xx.c.



Para obtener las frecuencias indicadas en el esquema de más arriba es necesario realizar las siguientes modificaciones en el código del archivo system_stm32f4xx.c:
  • uint32_t SystemCoreClock = 100000000: 100 MHz es la frecuencia máxima del sistema.
  • PLL_M = 8: divide entre 8 la frecuencia del cristal externo de 8 MHz, con lo que se obtiene 1 MHz a la entrada del VCO.
  • PLL_N = 192: multiplica la frecuencia de 1 MHz por 192, de manera que la frecuencia de salida del VCO será de 192 MHz.
  • PLL_P = 2: divide entre 2 los 192 MHz del VCO, obteniendo una señal PLLCLK de 96 MHz, por tanto, una señal SYSCLK también de 96 MHz.
  • PLL_Q = 4: divide entre 4 los 192 MHz para obtener 48 MHz. Para configurar PLL_M, PLL_N, PLL_P y PLL_Q el código del archivo system_stm32f4xx.c ha de efectuar modificaciones en el registro RCC_PLLCFGR.
  • RCC->CFGR |= RCC_CFGR_HPRE_DIV1: accede al registro RCC_CFGR para que el prescaler AHB divida la frecuencia de SYSCLK por 1. La constante utilizada en esta instrucción y las usadas en las dos siguientes están definidas en el archivo stm32fxx.h.
  • RCC->CFGR |= RCC_CFGR_PPRE2_DIV1: accede al registro RCC_CFGR para que el prescaler APB2 divida la frecuencia de salida de AHB por 1.
  • RCC->CFGR |= RCC_CFGR_PPRE1_DIV2: accede al registro RCC_CFGR para que el prescaler APB1 divida la frecuencia de salida de AHB por 2.
También hay que indicar, en el código del archivo stm32f4xx.h, la frecuencia del cristal externo, que en este caso es de 8 Mz. Por tanto, se ha de cambiar ‘25000000’ por ‘8000000’.

 
El siguiente texto es un resumen del cometido del código contenido en el archivo system_stm32f4xx.c.