¿Es correcto el reloj de salida?

1

He escrito y utilizando un STM32F030F4 para alternar un pin . Configuré todas las cosas y mi programa es este (uso GPIOA->ODR ^= GPIO_PIN_2 para alternar GPIOA2 en el bucle infinito):

#include "stm32f0xx_hal.h"

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* System interrupt init*/
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

  /* Initialize all configured peripherals */
  MX_GPIO_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* USER CODE BEGIN 3 */
  /* Infinite loop */
  while (1)
  {
        GPIOA->ODR ^= GPIO_PIN_2; //toggle GPIOA2
  }
  /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);

  __SYSCFG_CLK_ENABLE();

}

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __GPIOF_CLK_ENABLE();
  __GPIOA_CLK_ENABLE();

  /*Configure GPIO pin : PA2 */
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

Como ha dicho manual de referencia :

Porlotanto,si2*2=4significaquecadaciclode4haceuncambioenGPIOA2.entonceslafrecuenciadeberíaser48/4=12MHz(48esrelojMCUporque,comopuedever,enloscódigosheusadoPLLyhemultiplicado8MHza6).escorrecto?

DejequeseejecuteelcódigoenMCU.miraelresultadodemisaleae:

¿Eh? ¿Es correcta la frecuencia de salida? ¿Hay algún punto?

Editar:

El conjunto para el conmutador es este:

    
pregunta Roh

1 respuesta

2

Esta es una respuesta genérica en lugar de algo específico de ese chip en particular para ayudarlo a comprender algunos de los problemas. Cuando tenga un código como este:

while (1)
{
    GPIOA->ODR ^= GPIO_PIN_2; //toggle GPIOA2
}

No será una sola instrucción / ciclo en el ensamblador, se usará una rama para repetir la misma secuencia de instrucciones y también será una instrucción para realizar la operación OR exclusiva. Como Matt Young sugirió en un comentario, la única manera de saber con certeza la salida del ensamblador es mirar la salida del compilador para ver cuántas instrucciones de la máquina se están utilizando realmente.

Otro problema probable es el FLASH_LATENCY_1 que inserta un retraso al leer el FLASH que probablemente no sea necesario a esa velocidad bastante baja. Creo que si reemplaza eso con FLASH_LATENCY_0 , debería ver una mejora en la velocidad (dependiendo de cualquier almacenamiento en caché), pero vale la pena revisar la hoja de datos para ver a qué velocidad se requiere. Muchos núcleos ARM pueden funcionar a velocidades superiores a la que se puede obtener del código de FLASH, que es la razón de esa función.

Nunca he usado el compilador Keil, así que no estoy seguro de cómo obtener la salida del ensamblador, pero a menudo se describe como un archivo de listado. La búsqueda de Listing (MDK-ARM) parece que lo cubre.

Ahora que ha encontrado cómo ver la salida del ensamblador, puede ver que hay un total de cuatro instrucciones involucradas, las instrucciones entre las direcciones 0x80009C8 y 0x80009CE son esa parte del código y la última instrucción es la rama que vuelve al inicio.

    
respondido por el PeterJ

Lea otras preguntas en las etiquetas