Skocz do zawartości

Mechaniczny skaner 3D


Pomocna odpowiedź

1 godzinę temu, Szałszanin napisał:

uważam że przetwarzanie równoległe jest w tym przypadku korzystniejsze i w takiej wersji będę kontynuował.

Rób jak chcesz. Na ta chwilę jedyną płytkę jaka mam do dyspozycji to NUCLEO743Z2 (M7 480MHz) i nawet napisałem soft, kompiluje się ale nie sprawdzałem jeszcze ile czasu zajmuje obsługa przerwania (będą to co najwyżej setki ns - pracuję na 96MHz). Kto chce sprawdzić, proszę dwa najważniejsze pliki (cały projekt za duży na to forum):

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "string.h"


/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

int volatile cnt0, cnt1, cnt2, cnt3,cnt4, cnt5, cnt6;
uint16_t volatile TimUart, TimLed;
void irq1ms(void);

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

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

UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_usart3_tx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART3_UART_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

void irq1ms(){
	if( TimUart ) TimUart--;
	if( TimLed ) TimLed--;
}



/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

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

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET );	// Czerwona
	HAL_UART_Transmit( &huart3, (uint8_t*)("\n\rStart\n\r"),9, 10 );

while (1)
  {
		
		if( !TimLed ){
			TimLed = 500;
			HAL_GPIO_TogglePin( LD1_GPIO_Port, LD1_Pin);		// Zielona
		}
		
		
		int32_t static prevCnt0, prevCnt1, prevCnt2, prevCnt3, prevCnt4, prevCnt5, prevCnt6;
		/*
		NVIC_DisableIRQ( EXTI0_IRQn );
		NVIC_DisableIRQ( EXTI1_IRQn );
		NVIC_DisableIRQ( EXTI2_IRQn );
		NVIC_DisableIRQ( EXTI3_IRQn );
		NVIC_DisableIRQ( EXTI4_IRQn );
		NVIC_DisableIRQ( EXTI9_5_IRQn );
		NVIC_DisableIRQ( EXTI15_10_IRQn );
		*/
		if( (prevCnt6 != cnt6) ||
		(prevCnt5 != cnt5) ||
		(prevCnt4 != cnt4) ||
		(prevCnt3 != cnt3) ||
		(prevCnt2 != cnt2) ||
		(prevCnt1 != cnt1) ||
		(prevCnt0 != cnt0) ){
			prevCnt6 = cnt6;
			prevCnt5 = cnt5;
			prevCnt4 = cnt4;
			prevCnt3 = cnt3;
			prevCnt2 = cnt2;
			prevCnt1 = cnt1;
			prevCnt0 = cnt0;
			/*
			NVIC_EnableIRQ( EXTI0_IRQn );
			NVIC_EnableIRQ( EXTI1_IRQn );
			NVIC_EnableIRQ( EXTI2_IRQn );
			NVIC_EnableIRQ( EXTI3_IRQn );
			NVIC_EnableIRQ( EXTI4_IRQn );
			NVIC_EnableIRQ( EXTI9_5_IRQn );
			NVIC_EnableIRQ( EXTI15_10_IRQn );
			*/
			
			char static txt[100];
			sprintf( txt, "%d %d %d %d %d %d %d\n\r", cnt0, cnt1, cnt2, cnt3,cnt4, cnt5, cnt6 );
			//HAL_UART_Transmit_IT( &huart3, (uint8_t*)txt, strlen(txt) );
			HAL_UART_Transmit( &huart3, (uint8_t*)txt, strlen(txt), 10 );
		}
		else{
			/*
			NVIC_EnableIRQ( EXTI0_IRQn );
			NVIC_EnableIRQ( EXTI1_IRQn );
			NVIC_EnableIRQ( EXTI2_IRQn );
			NVIC_EnableIRQ( EXTI3_IRQn );
			NVIC_EnableIRQ( EXTI4_IRQn );
			NVIC_EnableIRQ( EXTI9_5_IRQn );
			NVIC_EnableIRQ( EXTI15_10_IRQn );
			*/
		}
		
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Supply configuration update enable 
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  /** Configure the main internal regulator output voltage 
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3;
  PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{

  /* USER CODE BEGIN USART3_Init 0 */

  /* USER CODE END USART3_Init 0 */

  /* USER CODE BEGIN USART3_Init 1 */

  /* USER CODE END USART3_Init 1 */
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART3_Init 2 */

  /* USER CODE END USART3_Init 2 */

}

/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();
  __HAL_RCC_GPIOE_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(USB_OTG_FS_PWR_EN_GPIO_Port, USB_OTG_FS_PWR_EN_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : B1_USER_KEY_Pin */
  GPIO_InitStruct.Pin = B1_USER_KEY_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(B1_USER_KEY_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : PF0 PF1 PF2 PF3 
                           PF4 PF5 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
                          |GPIO_PIN_4|GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pins : PC1 PC4 PC5 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pins : PA1 PA2 PA7 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : LD1_Pin LD3_Pin */
  GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PB13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_OTG_FS_PWR_EN_Pin */
  GPIO_InitStruct.Pin = USB_OTG_FS_PWR_EN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(USB_OTG_FS_PWR_EN_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PG7 */
  GPIO_InitStruct.Pin = GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

  /*Configure GPIO pins : PA8 PA11 PA12 */
  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_11|GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PD0 PD1 PD2 PD3 
                           PD4 PD5 PD6 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  /*Configure GPIO pins : PG11 PG13 */
  GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

  /*Configure GPIO pin : LD2_Pin */
  GPIO_InitStruct.Pin = LD2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI0_IRQn);

  HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI1_IRQn);

  HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI2_IRQn);

  HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI3_IRQn);

  HAL_NVIC_SetPriority(EXTI4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI4_IRQn);

  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    stm32h7xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32h7xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */


extern int volatile cnt0, cnt1, cnt2, cnt3,cnt4, cnt5, cnt6;


/* USER CODE END TD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
 
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* External variables --------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_usart3_tx;
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN EV */

/* USER CODE END EV */

/******************************************************************************/
/*           Cortex Processor Interruption and Exception Handlers          */ 
/******************************************************************************/
/**
  * @brief This function handles Non maskable interrupt.
  */
void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */

  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */

  /* USER CODE END NonMaskableInt_IRQn 1 */
}

/**
  * @brief This function handles Hard fault interrupt.
  */
void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Memory management fault.
  */
void MemManage_Handler(void)
{
  /* USER CODE BEGIN MemoryManagement_IRQn 0 */

  /* USER CODE END MemoryManagement_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
    /* USER CODE END W1_MemoryManagement_IRQn 0 */
  }
}

/**
  * @brief This function handles Pre-fetch fault, memory access fault.
  */
void BusFault_Handler(void)
{
  /* USER CODE BEGIN BusFault_IRQn 0 */

  /* USER CODE END BusFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
    /* USER CODE END W1_BusFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Undefined instruction or illegal state.
  */
void UsageFault_Handler(void)
{
  /* USER CODE BEGIN UsageFault_IRQn 0 */

  /* USER CODE END UsageFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
    /* USER CODE END W1_UsageFault_IRQn 0 */
  }
}

/**
  * @brief This function handles System service call via SWI instruction.
  */
void SVC_Handler(void)
{
  /* USER CODE BEGIN SVCall_IRQn 0 */

  /* USER CODE END SVCall_IRQn 0 */
  /* USER CODE BEGIN SVCall_IRQn 1 */

  /* USER CODE END SVCall_IRQn 1 */
}

/**
  * @brief This function handles Debug monitor.
  */
void DebugMon_Handler(void)
{
  /* USER CODE BEGIN DebugMonitor_IRQn 0 */

  /* USER CODE END DebugMonitor_IRQn 0 */
  /* USER CODE BEGIN DebugMonitor_IRQn 1 */

  /* USER CODE END DebugMonitor_IRQn 1 */
}

/**
  * @brief This function handles Pendable request for system service.
  */
void PendSV_Handler(void)
{
  /* USER CODE BEGIN PendSV_IRQn 0 */

  /* USER CODE END PendSV_IRQn 0 */
  /* USER CODE BEGIN PendSV_IRQn 1 */

  /* USER CODE END PendSV_IRQn 1 */
}

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

	extern void irq1ms(void);
	irq1ms();
	
  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

/******************************************************************************/
/* STM32H7xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32h7xx.s).                    */
/******************************************************************************/

/**
  * @brief This function handles EXTI line0 interrupt.
  */
void EXTI0_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI0_IRQn 0 */

	
	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_0 ) ) cnt0++; else cnt0--;
	
	
  /* USER CODE END EXTI0_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
  /* USER CODE BEGIN EXTI0_IRQn 1 */

  /* USER CODE END EXTI0_IRQn 1 */
}

/**
  * @brief This function handles EXTI line1 interrupt.
  */
void EXTI1_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI1_IRQn 0 */


	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_1 ) ) cnt1++; else cnt1--;

	
  /* USER CODE END EXTI1_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
  /* USER CODE BEGIN EXTI1_IRQn 1 */

  /* USER CODE END EXTI1_IRQn 1 */
}

/**
  * @brief This function handles EXTI line2 interrupt.
  */
void EXTI2_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI2_IRQn 0 */

	
	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_2 ) ) cnt2++; else cnt2--;

	
  /* USER CODE END EXTI2_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
  /* USER CODE BEGIN EXTI2_IRQn 1 */

  /* USER CODE END EXTI2_IRQn 1 */
}

/**
  * @brief This function handles EXTI line3 interrupt.
  */
void EXTI3_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI3_IRQn 0 */

	
	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_3 ) ) cnt3++; else cnt3--;

	
  /* USER CODE END EXTI3_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
  /* USER CODE BEGIN EXTI3_IRQn 1 */

  /* USER CODE END EXTI3_IRQn 1 */
}

/**
  * @brief This function handles EXTI line4 interrupt.
  */
void EXTI4_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI4_IRQn 0 */

	
	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_4 ) ) cnt4++; else cnt4--;

	
  /* USER CODE END EXTI4_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
  /* USER CODE BEGIN EXTI4_IRQn 1 */

  /* USER CODE END EXTI4_IRQn 1 */
}

/**
  * @brief This function handles DMA1 stream0 global interrupt.
  */
void DMA1_Stream0_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream0_IRQn 0 */

  /* USER CODE END DMA1_Stream0_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart3_tx);
  /* USER CODE BEGIN DMA1_Stream0_IRQn 1 */

  /* USER CODE END DMA1_Stream0_IRQn 1 */
}

/**
  * @brief This function handles EXTI line[9:5] interrupts.
  */
void EXTI9_5_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI9_5_IRQn 0 */


	// INFO: 5..9 aktywne tylko 5 wiec nie trzeba sprawdzac zrodla przerwania
		if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_5 ) ) cnt5++; else cnt5--;

	
  /* USER CODE END EXTI9_5_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
  /* USER CODE BEGIN EXTI9_5_IRQn 1 */

  /* USER CODE END EXTI9_5_IRQn 1 */
}

/**
  * @brief This function handles USART3 global interrupt.
  */
void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */

  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */

  /* USER CODE END USART3_IRQn 1 */
}

/**
  * @brief This function handles EXTI line[15:10] interrupts.
  */
void EXTI15_10_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */

	HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET );	// Czerwona
	HAL_GPIO_TogglePin( LD2_GPIO_Port, LD2_Pin);		// Zolta
	
	
	// INFO: 10..15 aktywne tylko 13 wiec nie trzeba sprawdzac zrodla przerwania
if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_6 ) ) cnt6++; else cnt6--;
	
  /* USER CODE END EXTI15_10_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */

	
	HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET );	// Czerwona
	// INFO: czas obslugi IRQ = 

	
  /* USER CODE END EXTI15_10_IRQn 1 */
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Resztę każdy może sobie wygenerować z CubeMX.  Wybrałem przerwania EXTI0..4 i po jednym z grupy 5..9 i 10..15 więc nie trzeba rozpoznawać źródła przerwania co jest bardzo proste, jeden if.

 

2 godziny temu, FlyingDutch napisał:

Jeśli nie lubisz/ nie masz doświadczenia z układami FPGA to twój problem.

Moja przygoda z układami programowalnymi rozpoczęła się w zeszłym tysiącleciu. Znam GAL, CPLD i FPGA. Kiedyś często ich używałem, teraz mikrokontrolery są tak wyposażone, że najczęściej nie ma potrzeby sięgać po drogie FPGA.

Edytowano przez InspektorGadzet
  • Lubię! 1
Link do komentarza
Share on other sites

Cześć,

jak już wcześniej pisałem w tym wątku. do przeliczenia pozycji liczników enkoderów ramion manipulatora na współrzędne (w kartezjańskim układzie odniesienia) potrzebna jest możliwość liczenia funkcji trygonometrycznych. Wystarczy tablica funkcji sinus w zakresie od 0 do 90 stopni (w mierze łukowej kąta od 0 do PI/2). Za pomocą takiej tablicy można wyliczyć wartości wszystkich funkcji trygonometrycznych w dowolnym zakresie kątów. Taką tablicę o ilości katów odpowiadającej rozdzielczości enkoderów (np. 10 bit to 1024 wartości) można wyliczyć i podać w postaci stało-przecinkowej (fixed-point), jednak takie obliczenia są niewygodne (i mają ograniczony zakres liczbowy). Ponieważ wcześniej wypróbowałem prosty układ FPU (liczący na liczbach float 32-bitowych), który działa poprawnie. Postanowiłem wygenerować tablicę funkcji sinus w formacie zmienno-przecinkowym  "IEEE-754 Single Precision " odpowiednik 32-biowego typu float z języka C. Tutaj pojawił się pewien problem ponieważ "IP Core" Xilinx'a do generacji pamięci ROM w bloku BRAM nie przyjmuje wartości dziesiętnych w plikach *.coe (do wczytania zawartości pamięci ROM dla bloku BRAM). Stąd wynikła potrzeba napisania programu, który wygeneruje plik coe z tablicą funcji sinus w formacie binarnym (IEEE-754 Single Precision). Taki program napisałem w języku C++ korzystając z IDE Borlanda C++ Builder (wersja 6.0). Oto zrzut ekranu z okna tej aplikacji:

GeneratorfunkcjiSinus.thumb.png.e1f58a4e2bb30d2de1cff4251511ab05.png

Mamy możliwość wpisania liczby na ile wartości zostanie podzielony pełen okres funkcji sinus (jest to 360 stopni kątowych lub 2*PI dla miary łukowej kąta. Ponieważ tablica jest generowana dla 1/4 tego okresu (90 stopni lub PI/2), to liczba wartości tablicy funkcji sinus jest równa tej podanej liczbie dzielonej przez 4. Mamy też możliwość podejrzenia reprezentacji binarnej dowolej liczby float podanej dziesuiętnie. UWAGA! liczby do testu konwersji8 zawsze należy podawać z przecinkiem i jedną liczbą po przecinku: np. dla liczby 3 wpisujemy: 3,0 .Możemy też podawać liczby float do zamiany w postaci (naukowej) np. 0,09814e-24.

Po naciśnięciu klawisza <Generuj tablicę funcji sinus> zostanie wygenerowana tablica funkcji sinus najpierw w postaci dziesiętnej, a potem w postaci pliku coe do generacji pamięci ROM w ISE Xilinx'a (UWAGA!: trzeba usunąć przecinek z ostatniej linii postaci binarnej przed wklejeniem do pliku coe.

W załączniku projekt aplikacji dla "C++ Builder 6". Plik wykonywalny to " SinusGenerator01.exe". UWAGA!: nie ma żadnych kontroli dla wprowadzanych danych (jeśli wprowadzimy dane w złym formacie wystąpi wyjątek).

SinusGenerator.zip

Poprawność wygenerowanej postaci binarnej liczby float można sprawdzić korzystając z tego generatora on-line:

https://www.h-schmidt.net/FloatConverter/IEEE754.html

Przy pisaniu aplikacji korzystałem częściowo z kodu na tej stronie:

https://pastebin.com/5CrHq0Gc

Aplikacja była sprawdzona dla 64-bitowej wersji Windows 10.

Pozdrawiam

Edytowano przez FlyingDutch
  • Lubię! 1
Link do komentarza
Share on other sites

1 godzinę temu, InspektorGadzet napisał:

Rób jak chcesz. Na ta chwilę jedyną płytkę jaka mam do dyspozycji to NUCLEO743Z2 (M7 480MHz) i nawet napisałem soft, kompiluje się ale nie sprawdzałem jeszcze ile czasu zajmuje obsługa przerwania (będą to co najwyżej setki ns - pracuję na 96MHz). Kto chce sprawdzić, proszę dwa najważniejsze pliki (cały projekt za duży na to forum):


/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include "string.h"


/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

int volatile cnt0, cnt1, cnt2, cnt3,cnt4, cnt5, cnt6;
uint16_t volatile TimUart, TimLed;
void irq1ms(void);

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

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

UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_usart3_tx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART3_UART_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

void irq1ms(){
	if( TimUart ) TimUart--;
	if( TimLed ) TimLed--;
}



/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

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

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET );	// Czerwona
	HAL_UART_Transmit( &huart3, (uint8_t*)("\n\rStart\n\r"),9, 10 );

while (1)
  {
		
		if( !TimLed ){
			TimLed = 500;
			HAL_GPIO_TogglePin( LD1_GPIO_Port, LD1_Pin);		// Zielona
		}
		
		
		int32_t static prevCnt0, prevCnt1, prevCnt2, prevCnt3, prevCnt4, prevCnt5, prevCnt6;
		/*
		NVIC_DisableIRQ( EXTI0_IRQn );
		NVIC_DisableIRQ( EXTI1_IRQn );
		NVIC_DisableIRQ( EXTI2_IRQn );
		NVIC_DisableIRQ( EXTI3_IRQn );
		NVIC_DisableIRQ( EXTI4_IRQn );
		NVIC_DisableIRQ( EXTI9_5_IRQn );
		NVIC_DisableIRQ( EXTI15_10_IRQn );
		*/
		if( (prevCnt6 != cnt6) ||
		(prevCnt5 != cnt5) ||
		(prevCnt4 != cnt4) ||
		(prevCnt3 != cnt3) ||
		(prevCnt2 != cnt2) ||
		(prevCnt1 != cnt1) ||
		(prevCnt0 != cnt0) ){
			prevCnt6 = cnt6;
			prevCnt5 = cnt5;
			prevCnt4 = cnt4;
			prevCnt3 = cnt3;
			prevCnt2 = cnt2;
			prevCnt1 = cnt1;
			prevCnt0 = cnt0;
			/*
			NVIC_EnableIRQ( EXTI0_IRQn );
			NVIC_EnableIRQ( EXTI1_IRQn );
			NVIC_EnableIRQ( EXTI2_IRQn );
			NVIC_EnableIRQ( EXTI3_IRQn );
			NVIC_EnableIRQ( EXTI4_IRQn );
			NVIC_EnableIRQ( EXTI9_5_IRQn );
			NVIC_EnableIRQ( EXTI15_10_IRQn );
			*/
			
			char static txt[100];
			sprintf( txt, "%d %d %d %d %d %d %d\n\r", cnt0, cnt1, cnt2, cnt3,cnt4, cnt5, cnt6 );
			//HAL_UART_Transmit_IT( &huart3, (uint8_t*)txt, strlen(txt) );
			HAL_UART_Transmit( &huart3, (uint8_t*)txt, strlen(txt), 10 );
		}
		else{
			/*
			NVIC_EnableIRQ( EXTI0_IRQn );
			NVIC_EnableIRQ( EXTI1_IRQn );
			NVIC_EnableIRQ( EXTI2_IRQn );
			NVIC_EnableIRQ( EXTI3_IRQn );
			NVIC_EnableIRQ( EXTI4_IRQn );
			NVIC_EnableIRQ( EXTI9_5_IRQn );
			NVIC_EnableIRQ( EXTI15_10_IRQn );
			*/
		}
		
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Supply configuration update enable 
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  /** Configure the main internal regulator output voltage 
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3;
  PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{

  /* USER CODE BEGIN USART3_Init 0 */

  /* USER CODE END USART3_Init 0 */

  /* USER CODE BEGIN USART3_Init 1 */

  /* USER CODE END USART3_Init 1 */
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart3.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart3, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart3, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART3_Init 2 */

  /* USER CODE END USART3_Init 2 */

}

/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOG_CLK_ENABLE();
  __HAL_RCC_GPIOE_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(USB_OTG_FS_PWR_EN_GPIO_Port, USB_OTG_FS_PWR_EN_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : B1_USER_KEY_Pin */
  GPIO_InitStruct.Pin = B1_USER_KEY_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(B1_USER_KEY_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : PF0 PF1 PF2 PF3 
                           PF4 PF5 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
                          |GPIO_PIN_4|GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

  /*Configure GPIO pins : PC1 PC4 PC5 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /*Configure GPIO pins : PA1 PA2 PA7 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : LD1_Pin LD3_Pin */
  GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : PB13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin : USB_OTG_FS_PWR_EN_Pin */
  GPIO_InitStruct.Pin = USB_OTG_FS_PWR_EN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(USB_OTG_FS_PWR_EN_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PG7 */
  GPIO_InitStruct.Pin = GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

  /*Configure GPIO pins : PA8 PA11 PA12 */
  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_11|GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PD0 PD1 PD2 PD3 
                           PD4 PD5 PD6 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  /*Configure GPIO pins : PG11 PG13 */
  GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

  /*Configure GPIO pin : LD2_Pin */
  GPIO_InitStruct.Pin = LD2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI0_IRQn);

  HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI1_IRQn);

  HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI2_IRQn);

  HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI3_IRQn);

  HAL_NVIC_SetPriority(EXTI4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI4_IRQn);

  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

  HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    stm32h7xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32h7xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */


extern int volatile cnt0, cnt1, cnt2, cnt3,cnt4, cnt5, cnt6;


/* USER CODE END TD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
 
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* External variables --------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_usart3_tx;
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN EV */

/* USER CODE END EV */

/******************************************************************************/
/*           Cortex Processor Interruption and Exception Handlers          */ 
/******************************************************************************/
/**
  * @brief This function handles Non maskable interrupt.
  */
void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */

  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */

  /* USER CODE END NonMaskableInt_IRQn 1 */
}

/**
  * @brief This function handles Hard fault interrupt.
  */
void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Memory management fault.
  */
void MemManage_Handler(void)
{
  /* USER CODE BEGIN MemoryManagement_IRQn 0 */

  /* USER CODE END MemoryManagement_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
    /* USER CODE END W1_MemoryManagement_IRQn 0 */
  }
}

/**
  * @brief This function handles Pre-fetch fault, memory access fault.
  */
void BusFault_Handler(void)
{
  /* USER CODE BEGIN BusFault_IRQn 0 */

  /* USER CODE END BusFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
    /* USER CODE END W1_BusFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Undefined instruction or illegal state.
  */
void UsageFault_Handler(void)
{
  /* USER CODE BEGIN UsageFault_IRQn 0 */

  /* USER CODE END UsageFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
    /* USER CODE END W1_UsageFault_IRQn 0 */
  }
}

/**
  * @brief This function handles System service call via SWI instruction.
  */
void SVC_Handler(void)
{
  /* USER CODE BEGIN SVCall_IRQn 0 */

  /* USER CODE END SVCall_IRQn 0 */
  /* USER CODE BEGIN SVCall_IRQn 1 */

  /* USER CODE END SVCall_IRQn 1 */
}

/**
  * @brief This function handles Debug monitor.
  */
void DebugMon_Handler(void)
{
  /* USER CODE BEGIN DebugMonitor_IRQn 0 */

  /* USER CODE END DebugMonitor_IRQn 0 */
  /* USER CODE BEGIN DebugMonitor_IRQn 1 */

  /* USER CODE END DebugMonitor_IRQn 1 */
}

/**
  * @brief This function handles Pendable request for system service.
  */
void PendSV_Handler(void)
{
  /* USER CODE BEGIN PendSV_IRQn 0 */

  /* USER CODE END PendSV_IRQn 0 */
  /* USER CODE BEGIN PendSV_IRQn 1 */

  /* USER CODE END PendSV_IRQn 1 */
}

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

	extern void irq1ms(void);
	irq1ms();
	
  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

/******************************************************************************/
/* STM32H7xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32h7xx.s).                    */
/******************************************************************************/

/**
  * @brief This function handles EXTI line0 interrupt.
  */
void EXTI0_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI0_IRQn 0 */

	
	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_0 ) ) cnt0++; else cnt0--;
	
	
  /* USER CODE END EXTI0_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
  /* USER CODE BEGIN EXTI0_IRQn 1 */

  /* USER CODE END EXTI0_IRQn 1 */
}

/**
  * @brief This function handles EXTI line1 interrupt.
  */
void EXTI1_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI1_IRQn 0 */


	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_1 ) ) cnt1++; else cnt1--;

	
  /* USER CODE END EXTI1_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
  /* USER CODE BEGIN EXTI1_IRQn 1 */

  /* USER CODE END EXTI1_IRQn 1 */
}

/**
  * @brief This function handles EXTI line2 interrupt.
  */
void EXTI2_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI2_IRQn 0 */

	
	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_2 ) ) cnt2++; else cnt2--;

	
  /* USER CODE END EXTI2_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
  /* USER CODE BEGIN EXTI2_IRQn 1 */

  /* USER CODE END EXTI2_IRQn 1 */
}

/**
  * @brief This function handles EXTI line3 interrupt.
  */
void EXTI3_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI3_IRQn 0 */

	
	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_3 ) ) cnt3++; else cnt3--;

	
  /* USER CODE END EXTI3_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
  /* USER CODE BEGIN EXTI3_IRQn 1 */

  /* USER CODE END EXTI3_IRQn 1 */
}

/**
  * @brief This function handles EXTI line4 interrupt.
  */
void EXTI4_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI4_IRQn 0 */

	
	if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_4 ) ) cnt4++; else cnt4--;

	
  /* USER CODE END EXTI4_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
  /* USER CODE BEGIN EXTI4_IRQn 1 */

  /* USER CODE END EXTI4_IRQn 1 */
}

/**
  * @brief This function handles DMA1 stream0 global interrupt.
  */
void DMA1_Stream0_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream0_IRQn 0 */

  /* USER CODE END DMA1_Stream0_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart3_tx);
  /* USER CODE BEGIN DMA1_Stream0_IRQn 1 */

  /* USER CODE END DMA1_Stream0_IRQn 1 */
}

/**
  * @brief This function handles EXTI line[9:5] interrupts.
  */
void EXTI9_5_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI9_5_IRQn 0 */


	// INFO: 5..9 aktywne tylko 5 wiec nie trzeba sprawdzac zrodla przerwania
		if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_5 ) ) cnt5++; else cnt5--;

	
  /* USER CODE END EXTI9_5_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
  /* USER CODE BEGIN EXTI9_5_IRQn 1 */

  /* USER CODE END EXTI9_5_IRQn 1 */
}

/**
  * @brief This function handles USART3 global interrupt.
  */
void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */

  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */

  /* USER CODE END USART3_IRQn 1 */
}

/**
  * @brief This function handles EXTI line[15:10] interrupts.
  */
void EXTI15_10_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */

	HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET );	// Czerwona
	HAL_GPIO_TogglePin( LD2_GPIO_Port, LD2_Pin);		// Zolta
	
	
	// INFO: 10..15 aktywne tylko 13 wiec nie trzeba sprawdzac zrodla przerwania
if( HAL_GPIO_ReadPin( GPIOD , GPIO_PIN_6 ) ) cnt6++; else cnt6--;
	
  /* USER CODE END EXTI15_10_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */

	
	HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET );	// Czerwona
	// INFO: czas obslugi IRQ = 

	
  /* USER CODE END EXTI15_10_IRQn 1 */
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Resztę każdy może sobie wygenerować z CubeMX.  Wybrałem przerwania EXTI0..4 i po jednym z grupy 5..9 i 10..15 więc nie trzeba rozpoznawać źródła przerwania co jest bardzo proste, jeden if.

Cześć,

kod, który teraz przedstawiałeś jest dużo lepszy niż te pierwsze wstawki, które przedstawiłeś i może stanowić punkt wyjścia do sensownej dyskusji.

Ja jednak pozostanę przy FPGA, ponieważ przy tym projekcie mogę się nauczyć wielu przydatnych mi rzeczy, których na układach FPGA jeszcze nie próbowałem.

Pozdrawiam

 

Link do komentarza
Share on other sites

1 godzinę temu, FlyingDutch napisał:

kod, który teraz przedstawiałeś jest dużo lepszy niż te pierwsze wstawki, które przedstawiłeś

To jest to samo.

 

1 godzinę temu, FlyingDutch napisał:

Ja jednak pozostanę przy FPGA

Twoja sprawa. Chcesz walczyć z FPGA, walcz. STM32 spokojnie wystarczy i nie trzeba sięgać po H7, F4 w zupełności wystarczy. Jeśli jednak to za mało, bierzesz RPi .Nie wiem tylko, czy RPi obsłuży 7 enkoderów.

Swego czasu, jak używałem głównie AVR, zrobiłem dwa projekty, w których AVR był wspomagany układem CPLD. Teraz to samo robię na STM32. Jeden projekt na F429, drugi na F103. Żaden CPLD czy tym bardziej FPGA nie jest potrzebny.

 

Napisz w C obliczenia, które chcesz robić na FPGA, skompiluję na F411 100MHz, F4168MHz, H7 480MHz, F103 72MHz i zmierzę czas ich wykonania. Łatwo będzie ocenić czy FPGA jest niezbędna, czy nie. Widzę, że w FPGA  już kombinujesz z liczbami stałoprzecinkowymi, tablicujesz co się da. Czyżby zasobów zaczęło brakować?

 

Edytowano przez InspektorGadzet
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

2 godziny temu, InspektorGadzet napisał:

Twoja sprawa. Chcesz walczyć z FPGA, walcz. STM32 spokojnie wystarczy i nie trzeba sięgać po H7, F4 w zupełności wystarczy. Jeśli jednak to za mało, bierzesz RPi .Nie wiem tylko, czy RPi obsłuży 7 enkoderów.

Napisz w C obliczenia, które chcesz robić na FPGA, skompiluję na F411 100MHz, F4168MHz, H7 480MHz, F103 72MHz i zmierzę czas ich wykonania. Łatwo będzie ocenić czy FPGA jest niezbędna, czy nie. Widzę, że w FPGA  już kombinujesz z liczbami stałoprzecinkowymi, tablicujesz co się da. Czyżby zasobów zaczęło brakować?

Cześć,

to prawda, ze seria F3 lub F4 (z STM32), to pierwszy sensowny wybór do tego projektu bo posiada własny moduł FPU (prostsze modele go nie posiadają). Ja nigdy nie twierdziłem, że FPGA jest niezbędne do tego projektu, tylko, że pod wieloma względami jest wygodniejsze do tego projektu niż CPU l że chciałbym go spróbować zaimplementować na układzie FPGA.

Co do FPGA (Spartan6) dla tego projektu nie brakuje mi zasobów, tylko po co mam tablicować cały okres funkcji sinus gdy wystarcza jedna czwarta okresu. Obliczenia będą oparte na liczbach zmienno-przecinkowych w tym projekcie.

Pozdrawiam

Link do komentarza
Share on other sites

Jeśli chcesz się czegoś nauczyć to ok bo z ekonomicznego punktu widzenia, FPGA są niestety drogie. Ponadto najczęściej FPGA musi być wspomagana przez CPU. Może owe CPU zaimplementowaćw w FPGA, ale  pochłania zasoby no i jaki CPU umieścisz w FPGA? Niedopracowany darmowy, niewydajny 8051? ARM raczej nie umieścisz 🙂

W praktyce, po FPGA sięgałem aby zrobić układ wizyjny, teraz w takiej sytuacji sięgam po RPi. W czasach świetności portu LPT używałem większych CPLD bo dostępne wtedy mikrokontrolery nie dawały rady z EPP. Teraz, bez problemu EPP można zrealizować na mikrokontrolerze tylko po co? LPT "umarł", nawet w przemyśle już raczej tylko USB.

Edytowano przez InspektorGadzet
Link do komentarza
Share on other sites

1 godzinę temu, InspektorGadzet napisał:

Jeśli chcesz się czegoś nauczyć to ok bo z ekonomicznego punktu widzenia, FPGA są niestety drogie. Ponadto najczęściej FPGA musi być wspomagana przez CPU. Może owe CPU zaimplementowaćw w FPGA, ale  pochłania zasoby no i jaki CPU umieścisz w FPGA? Niedopracowany darmowy, niewydajny 8051? ARM raczej nie umieścisz 🙂

to nie jest do końca prawda - np 32-bitowy Microblaze (Xilinx) jest całkiem wydajnym soft-procesorem (niektóre bloki jak np. FPU możesz sobie dodać warunkowo). Są biblioteki np. Xilinx SDK do pisania softu na ten typ CPU. Podobnie jest z NIOSII Intela i Quartusem. są też tzw. SocC, które stanowią połączenie Hard-CPU (np. ARM lub Power-PC) z układem FPGA.

Cytat

ARM raczej nie umieścisz 🙂

i tu się zdziwisz- zobacz sobie ten post napisany przez Elvis'a na Forbocie:

Możesz też skorzystać z jednej z wielu implementacji darmowego ISA (open-hardware)  RISVC-V (tu masz dostępne implementacje w wielu językach HDL i w wielu wersjach od 32-bity do 128 bitów z akceleratorami sieci neuronowych). Chociaż muszę przyznać, że ta ostatnia architektura dopiero raczkuje  i nie jest łatwo.

Pozdrawiam

 

  • Lubię! 1
Link do komentarza
Share on other sites

1 godzinę temu, FlyingDutch napisał:

i tu się zdziwisz- zobacz sobie ten post napisany przez Elvis'a na Forbocie:

Na ARM trzeba mieć licencję. Dali za free co jest mało wydajne i się słabo sprzedaje, tak jak kiedyś Protel Autotraxa. Poza tym, czytałem, że coś Ci tam nie "rynksztosuje". Szansy na cos szybszego to też chyba nie ma, no i cena owej implementacji. Kupno mikrokontrolera będzie tańsze, chyba, ze będziesz produkował w milionach sztuk.

Kedyś byłe zachwycony FPGA ale mi przeszło.

 

1 godzinę temu, FlyingDutch napisał:

np 32-bitowy Microblaze (Xilinx) jest całkiem wydajnym soft-procesorem

Czy to ARM? Kompilatory są dopracowane jak dla ARM?

Edytowano przez InspektorGadzet
Link do komentarza
Share on other sites

Cześć,

mając wygenerowaną tablicę funkcji sinus (jedna ćwiartka okresu) za pomocą programu (o którym pisałem trochę wcześniej) będę się starał stworzyć dwa moduły: jeden podający wartości funkcji sinus i drugi cosinus (w pełnym zakresie okresu funkcji  - 360 stopni). Moduły będą pozwalały zmieniać kąt dla tych funkcji z rozdzielczością 10 bitów (1024 wartości, przyrost kąta 0,00613592332229018 radiana. Wartości funkcji sinus i cosinus będą liczbą float 32-bitową (standard: IEEE-754 Single Precision).

Wklejam do postu plik tekstowy z wygenerowaną tablicą funkcji sinus (od 0 do 90 stopni) - tego pliku można użyć jako coe, do generacji pamięci ROM (bloki BRAM FPGA) z użyciem IPcore Xilinx'a, co jest punktem wyjścia do generacji wartości tych funkcji.

Pozdrawiam

Sinustable.zip

  • Lubię! 1
Link do komentarza
Share on other sites

Cześć,

dzisiaj napisałem moduł liczący funkcję sinus w pełnym zakresie okresu funkcji, czyli 360 stopni kątowych (lub 2PI w mierze łukowej). Moduł składa się z dwóch komponentów:

1)

   COMPONENT ROM_Sinus90
     PORT (
       clka : IN STD_LOGIC;
       addra : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
       douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
     );
  END COMPONENT;

2)

entity SinProject is
    Port ( clk : in  STD_LOGIC;
	        reset : in  STD_LOGIC;
           Kat : in  STD_LOGIC_VECTOR (9 downto 0);
           DataOut : out  STD_LOGIC_VECTOR (31 downto 0);
           strobe : in  STD_LOGIC);
end SinProject;

ROM_Sinus90 jest to pamięć ROM, przechowująca wartości funkcji sinus (w zakresie pierwszej ćwiartki okresu - 90 stopni)

SinProject (top entity) jest to moduł zwracający wartości funkcji sinus w zakresie 360 stopni.

Kat - jest to kat dla którego liczymy wartość funkcji sinus : wartości od 0 do 1023 (10 bitów).

DataOut - wartość funkcji sinus jako 32-bitowa liczba float (standard: IEEE-754 Single Precision)

strobe - zbocze narastające powoduje zwrócenie wartości funkcji sinus dla podanego kata

clk - zegar

Pamięć ROM została wygenerowana za pomocą darmowego IPCore firmy Xilinx (Memory Generator z ISE 14.7).

Tutaj treść głównego (i jedynego) modułu liczącego funkcję sinus (entity SinProject):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity SinProject is
    Port ( clk : in  STD_LOGIC;
	        reset : in  STD_LOGIC;
           Kat : in  STD_LOGIC_VECTOR (9 downto 0);
           DataOut : out  STD_LOGIC_VECTOR (31 downto 0);
           strobe : in  STD_LOGIC);
end SinProject;

architecture Behavioral of SinProject is
   
   COMPONENT ROM_Sinus90
     PORT (
       clka : IN STD_LOGIC;
       addra : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
       douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
     );
  END COMPONENT;
  
  signal KatUnsigned : unsigned(9 downto 0); -- definicja syg lokalnego	
  signal AddressUnsigned : unsigned(7 downto 0); -- definicja syg lokalnego
  signal AddressInteger : integer range 0 to 256 :=0;
  signal AddressSinus: STD_LOGIC_VECTOR(7 DOWNTO 0);
  signal WartSinus :  STD_LOGIC_VECTOR(31 DOWNTO 0);
  signal ZnakSinus : integer range -1 to 1;  

begin
  
  SEQ: process (reset, clk, strobe)
  begin
    if (reset = '0') then
--	   DataOut <= x"00000000";		
    elsif ((clk' event and clk = '1' ) and (strobe' event and strobe = '1' )) then   
      KatUnsigned <= unsigned(Kat);
		if (KatUnsigned < 256) then
		   AddressUnsigned <= KatUnsigned(7 DOWNTO 0);
			AddressSinus <= std_logic_vector(AddressUnsigned);
			ZnakSinus <= 1;
		elsif ((KatUnsigned >= 256) and (KatUnsigned < 512)) then
		   AddressInteger <= (254 - (to_integer(KatUnsigned)-256));
			AddressSinus <= std_logic_vector(to_unsigned(AddressInteger, AddressSinus'length));
			ZnakSinus <= 1;
		elsif ((KatUnsigned >= 512) and (KatUnsigned <= 767)) then
		   AddressInteger <= (to_integer(KatUnsigned)-512);
			AddressSinus <= std_logic_vector(to_unsigned(AddressInteger, AddressSinus'length));
			ZnakSinus <= -1;	
		elsif ((KatUnsigned > 767) and (KatUnsigned <= 1023)) then
		   AddressInteger <= (254 -(to_integer(KatUnsigned)-768));
			AddressSinus <= std_logic_vector(to_unsigned(AddressInteger, AddressSinus'length));
			ZnakSinus <= -1;		
		else	
			AddressSinus <= b"00000000";
		end if;
	 
    end if;
  end process;
  
  
  TableSinus90 : ROM_Sinus90
  PORT MAP (
    clka => clk,
    addra => AddressSinus,
    douta => WartSinus
  );

 SEQ1: process (clk)
 begin 
   if (clk' event and clk = '1') then    
     if (ZnakSinus > 0) then
       DataOut <= WartSinus;
     else
       DataOut <= (b"1" & WartSinus(30 DOWNTO 0));
     end if; 
   end if;	  
 end process;

end Behavioral;

Nie wiem na razie, czy moduł działa poprawnie, bo nie napisałem testu - mam zamiar to zrobić w najbliższym czasie. Podobnie można zaimplementować moduł służący do liczenia funkcji cosinus. Jeśli ktoś chciałby sprawdzić, czy moduł działa prawidłowo to może to zrobić. W archiwum zip spakowany projekt ISE 14.7 dla tego modułu.

Pozdrawiam

SinusCosinusFunction01.zip

Edytowano przez FlyingDutch
  • Lubię! 1
Link do komentarza
Share on other sites

Cześć

miałem trochę czasu i doprowadziłem projekt w języku VHDL (do obliczania funkcji sinus) do poprawnego działania. Niestety musiałem zamiast projektu w ISE 14.7(FPGA: Spartan6)  przejść na Vivado2018.2(FPGA Artix-7) ponieważ w ISE przestała mi działać symulator (Windows 10), a chwilowo nie mam Linuxa bo padł mi dysk magnetyczny na którym był on zainstalowany. Przejdźmy więc do rzeczy: jak pamiętamy z wcześniejszych wpisów chcemy policzyć wartości funkcji sinus z rozdzielczością 10-bitów (wartości od 0 do 1023. Czyli kąt jest dany wzorem:

kat = i*0,00613592332229018 Radiana

gdzie: 0,00613592332229018 (w radianach to przyrost kata).

a i - to numer próbki (od 0 do 1023) - odpowiada to katowi pełnemu - 2PI (lub 360 stopni kątowych).

Patrz ten rysunek:

SinusF.thumb.png.12ecca001e6cf4a36c837e2999c4a000.png

Jak widać mając tabelę funkcji sinus dla jednej ćwiartki można za jej pomocą wyliczyć wartości funkcji dla całego okresu (czyli 360 stopni). Na rysunku zaznaczyłem jak ma się zmieniać 8-mio bitowy adres (0 do 255) dla pamięci ROM w której jest tablica funkcji sinus dla jednej ćwiartki. Widać też iż dla drugiej połówki sinusoidy (powyżej PI lub 180 stopni) wartości funkcji sinus są identyczne jak dla pierwszej połówki tylko9 z ujemnym znakiem.

Aby zrobić generator funkcji sinus potrzebujemy dwóch komponentów:

1) Pamięć ROM z wartościami funkcji sinus dla jednej ćwiartki (kąty od 0 do 155) - wykorzystamy blok pamięci BRAM z układu FPGA (tablica funkcji sinus wygenerowana programem o którym pisałem wcześniej)

2) Komponentu który zamienia katy z zakresu od 0 do 1023 (10-bit) na odpowiednie wartości adresu z zakresu od 0 do 255

Oto zawartość pliku pamięci coe z tablica funkcji sinus (jako Float 32):

memory_initialization_radix=2;
memory_initialization_vector=
00000000000000000000000000000000,
00111011110010010000111110001000,
00111100010010010000111010010000,
00111100100101101100100110110110,
00111100110010010000101010110000,
00111100111110110100100110111010,
00111101000101101100001100101100,
00111101001011111110000000000111,
00111101010010001111101100110000,
00111101011000100001010001101001,
00111101011110110010101101110100,
00111101100010100010000000001010,
00111101100101101010100100000101,
00111101101000110011000010001100,
00111101101011111011011010000001,
00111101101111000011101011000100,
00111101110010001011110100110110,
00111101110101010011110110111010,
00111101111000011011110000101111,
00111101111011100011100001110111,
00111101111110101011001001110011,
00111110000000111001010100000010,
00111110000010011100111110000111,
00111110000100000000100010110111,
00111110000101100100000010000100,
00111110000111000111011011011110,
00111110001000101010101110110110,
00111110001010001101111011111100,
00111110001011110001000010100010,
00111110001101010100000010011000,
00111110001110110110111011001111,
00111110010000011001101100111000,
00111110010001111100010111000010,
00111110010011011110111001100000,
00111110010101000001010100000010,
00111110010110100011100110011000,
00111110011000000101110000010100,
00111110011001100111110001100110,
00111110011011001001101010000000,
00111110011100101011011001010001,
00111110011110001100111111001100,
00111110011111101110011011100001,
00111110100000100111110111000001,
00111110100001011000011011001111,
00111110100010001000111010010011,
00111110100010111001010100000111,
00111110100011101001101000100010,
00111110100100011001110111011110,
00111110100101001010000000110010,
00111110100101111010000100010111,
00111110100110101010000010000110,
00111110100111011001111001111000,
00111110101000001001101011100101,
00111110101000111001010111000101,
00111110101001101000111100010010,
00111110101010011000011011000100,
00111110101011000111110011010100,
00111110101011110111000100111010,
00111110101100100110001111101111,
00111110101101010101010011101100,
00111110101110000100010000101010,
00111110101110110011000110100001,
00111110101111100001110101001010,
00111110110000010000011100011110,
00111110110000111110111100010110,
00111110110001101101010100101010,
00111110110010011011100101010011,
00111110110011001001101110001011,
00111110110011110111101111001010,
00111110110100100101101000001010,
00111110110101010011011001000010,
00111110110110000001000001101100,
00111110110110101110100010000001,
00111110110111011011111001111001,
00111110111000001001001001001111,
00111110111000110110001111111011,
00111110111001100011001101110101,
00111110111010010000000010111000,
00111110111010111100101110111011,
00111110111011101001010001111001,
00111110111100010101101011101010,
00111110111101000001111100001000,
00111110111101101110000011001011,
00111110111110011010000000101101,
00111110111111000101110100100111,
00111110111111110001011110110011,
00111111000000001110011111100100,
00111111000000100100001010110001,
00111111000000111001110000111101,
00111111000001001111010010000100,
00111111000001100100101110000011,
00111111000001111010000100110110,
00111111000010001111010110011011,
00111111000010100100100010101110,
00111111000010111001101001101011,
00111111000011001110101011010001,
00111111000011100011100111011010,
00111111000011111000011110000101,
00111111000100001101001111001101,
00111111000100100001111010110000,
00111111000100110110100000101011,
00111111000101001011000000111001,
00111111000101011111011011011001,
00111111000101110011110000000111,
00111111000110000111111111000000,
00111111000110011100001000000001,
00111111000110110000001011000110,
00111111000111000100001000001100,
00111111000111010111111111010010,
00111111000111101011110000010010,
00111111000111111111011011001011,
00111111001000010010111111111001,
00111111001000100110011110011001,
00111111001000111001110110101001,
00111111001001001101001000100101,
00111111001001100000010100001010,
00111111001001110011011001010110,
00111111001010000110011000000101,
00111111001010011001010000010101,
00111111001010101100000010000010,
00111111001010111110101101001010,
00111111001011010001010001101010,
00111111001011100011101111011110,
00111111001011110110000110100101,
00111111001100001000010110111011,
00111111001100011010100000011101,
00111111001100101100100011001001,
00111111001100111110011110111100,
00111111001101010000010011110011,
00111111001101100010000001101100,
00111111001101110011101000100011,
00111111001110000101001000010110,
00111111001110010110100001000010,
00111111001110100111110010100101,
00111111001110111000111100111011,
00111111001111001010000000000011,
00111111001111011010111011111001,
00111111001111101011110000011100,
00111111001111111100011101100111,
00111111010000001101000011011010,
00111111010000011101100001110001,
00111111010000101101111000101001,
00111111010000111110001000000001,
00111111010001001110001111110101,
00111111010001011110010000000100,
00111111010001101110001000101010,
00111111010001111101111001100101,
00111111010010001101100010110100,
00111111010010011101000100010011,
00111111010010101100011101111111,
00111111010010111011101111111000,
00111111010011001010111001111010,
00111111010011011001111100000011,
00111111010011101000110110010000,
00111111010011110111101000100000,
00111111010100000110010010110000,
00111111010100010100110100111101,
00111111010100100011001111000111,
00111111010100110001100001001001,
00111111010100111111101011000011,
00111111010101001101101100110010,
00111111010101011011100110010011,
00111111010101101001010111100101,
00111111010101110111000000100110,
00111111010110000100100001010011,
00111111010110010001111001101010,
00111111010110011111001001101010,
00111111010110101100010001010000,
00111111010110111001010000011010,
00111111010111000110000111000111,
00111111010111010010110101010011,
00111111010111011111011010111110,
00111111010111101011111000000110,
00111111010111111000001100100111,
00111111011000000100011000100001,
00111111011000010000011011110010,
00111111011000011100010110011000,
00111111011000101000001000010000,
00111111011000110011110001011010,
00111111011000111111010001110011,
00111111011001001010101001011001,
00111111011001010101111000001100,
00111111011001100000111110001000,
00111111011001101011111011001101,
00111111011001110110101111011000,
00111111011010000001011010101000,
00111111011010001011111100111100,
00111111011010010110010110010001,
00111111011010100000100110100111,
00111111011010101010101101111011,
00111111011010110100101100001100,
00111111011010111110100001011000,
00111111011011001000001101011111,
00111111011011010001110000011110,
00111111011011011011001010010011,
00111111011011100100011010111111,
00111111011011101101100010011110,
00111111011011110110100000110000,
00111111011011111111010101110011,
00111111011100001000000001100111,
00111111011100010000100100001000,
00111111011100011000111101010111,
00111111011100100001001101010011,
00111111011100101001010011111000,
00111111011100110001010001001000,
00111111011100111001000100111111,
00111111011101000000101111011110,
00111111011101001000010000100010,
00111111011101001111101000001011,
00111111011101010110110110010111,
00111111011101011101111011000110,
00111111011101100100110110010111,
00111111011101101011101000000111,
00111111011101110010010000010111,
00111111011101111000101111000101,
00111111011101111111000100010001,
00111111011110000101001111111000,
00111111011110001011010001111011,
00111111011110010001001010011000,
00111111011110010110111001001110,
00111111011110011100011110011110,
00111111011110100001111010000100,
00111111011110100111001100000010,
00111111011110101100010100010110,
00111111011110110001010010111111,
00111111011110110110000111111100,
00111111011110111010110011001101,
00111111011110111111010100110001,
00111111011111000011101100101000,
00111111011111000111111010110000,
00111111011111001011111111001001,
00111111011111001111111001110011,
00111111011111010011101010101100,
00111111011111010111010001110101,
00111111011111011010101111001100,
00111111011111011110000010110001,
00111111011111100001001100100100,
00111111011111100100001100100011,
00111111011111100111000010110000,
00111111011111101001101111001001,
00111111011111101100010001101101,
00111111011111101110101010011101,
00111111011111110000111001011000,
00111111011111110010111110011110,
00111111011111110100111001101101,
00111111011111110110101011000111,
00111111011111111000010010101011,
00111111011111111001110000011001,
00111111011111111011000100001111,
00111111011111111100001110001111,
00111111011111111101001110011000,
00111111011111111110000100101001,
00111111011111111110110001000011,
00111111011111111111010011100110,
00111111011111111111101100010001,
00111111011111111111111011000100

Tutaj zamieszczam pliki źródłowe projektu w języku VHDL (dla FPGA Artix-7).

Główną instancją projektu (top module) jest teraz SineFunction:

entity SineFunction is
    Port ( clk : in STD_LOGIC;
           reset : in STD_LOGIC;
           strobe : in STD_LOGIC;
           angle : in STD_LOGIC_VECTOR (9 downto 0);
           SineValue : out STD_LOGIC_VECTOR (31 downto 0); --Sine function value in IEEE-754 Single Precision (Float32)
           Sign : out STD_LOGIC); -- Sign: 0 positive, 1 negative
end SineFunction;

Jak widać mamy tu zegar, pin reset, strobe (stan wysoki na strobe zwraca wartość funkcji dla podanego kąta 0 do 1023).

angle - kat: 0 do 1023

SineValue - wartość funkcji sinus 32-bit float

Sign - znak funkcji sinus: 0 dodatni, 1 ujemny

A tutaj cały kod pliku SineFunction.vhd:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity SineFunction is
    Port ( clk : in STD_LOGIC;
           reset : in STD_LOGIC;
           strobe : in STD_LOGIC;
           angle : in STD_LOGIC_VECTOR (9 downto 0);
           SineValue : out STD_LOGIC_VECTOR (31 downto 0); --Sine function value in IEEE-754 Single Precision (Float32)
           Sign : out STD_LOGIC); -- Sign: 0 positive, 1 negative
end SineFunction;

architecture Behavioral of SineFunction is
   
   component SinProject is
       Port ( clk : in  STD_LOGIC;
              reset : in  STD_LOGIC;
              strobe : in  STD_LOGIC;
              Kat : in  STD_LOGIC_VECTOR (9 downto 0);
              AddressSinus : out  STD_LOGIC_VECTOR(7 DOWNTO 0);
              ZnakSinus : out integer range -1 to 1 
            );
   end component;
   
   component SineTable_ROM is
     Port ( 
       clka : in STD_LOGIC;
       ena : in STD_LOGIC;
       addra : in STD_LOGIC_VECTOR ( 7 downto 0 );
       douta : out STD_LOGIC_VECTOR ( 31 downto 0 )
     );
   end component;
   
   signal  OutAddressSinus : STD_LOGIC_VECTOR(7 DOWNTO 0);
   signal  OutZnakSinus :  integer range -1 to 1;
   signal  SinOut32Float : STD_LOGIC_VECTOR ( 31 downto 0 );

begin

  C1: SinProject port map (clk, reset, strobe, angle, OutAddressSinus, OutZnakSinus);
  C2: SineTable_ROM port map (clk, strobe, OutAddressSinus, SinOut32Float);
  
  SEQ1: process (clk, OutZnakSinus, SinOut32Float)
   begin 
     if (rising_edge(clk)) then    
       if (OutZnakSinus > 0) then
         SineValue <= SinOut32Float;
         Sign <= '0';
       else
         SineValue <= (b"1" & SinOut32Float(30 DOWNTO 0));
         Sign <= '1';
       end if; 
     end if;      
   end process;


end Behavioral;

Komponent SinProject zamienia 10-cio bitowy adres dla kata pełnego (360 stopni) na adres 8-mio bitowy (0 do 255) do odczytu wartości funkcji sinus z pamięci ROM. Oto kod pliku SinProject.vhd:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity SinProject is
    Port ( clk : in  STD_LOGIC;
	       reset : in  STD_LOGIC;
	       strobe : in  STD_LOGIC;
           Kat : in  STD_LOGIC_VECTOR (9 downto 0);
           AddressSinus : out  STD_LOGIC_VECTOR(7 DOWNTO 0);
           ZnakSinus : out integer range -1 to 1 
         );
end SinProject;

architecture Behavioral of SinProject is
    
  signal KatUnsigned : unsigned(9 downto 0); -- definicja syg lokalnego
  signal AddressUnBig : unsigned(9 downto 0); -- definicja syg lokalnego	
  signal AddressUnsigned : unsigned(7 downto 0); -- definicja syg lokalnego

begin
  
  SEQ: process (reset, clk, strobe, Kat)
  begin
    if rising_edge(clk) then
       if (reset = '0') then
	     AddressSinus <= b"00000000";	
       elsif (strobe = '1') then   
         KatUnsigned <= unsigned(Kat);
		 if (KatUnsigned < 256) then
		    AddressUnsigned <= KatUnsigned(7 DOWNTO 0);
			AddressSinus <= std_logic_vector(AddressUnsigned);
			ZnakSinus <= 1;
		 elsif ((KatUnsigned >= 256) and (KatUnsigned < 511)) then
		    AddressUnBig <= (254-(KatUnsigned-256));
		    AddressUnsigned <= AddressUnBig(7 DOWNTO 0);
			AddressSinus <= std_logic_vector(AddressUnsigned);
			ZnakSinus <= 1;
		 elsif ((KatUnsigned >= 511) and (KatUnsigned <= 766)) then
		    AddressUnBig <= (KatUnsigned-511);
		    AddressUnsigned <= AddressUnBig(7 DOWNTO 0);
			AddressSinus <= std_logic_vector(AddressUnsigned);
			ZnakSinus <= -1;	
		 elsif ((KatUnsigned >= 767) and (KatUnsigned < 1023)) then
		    AddressUnBig <= (255-(KatUnsigned-767));
		    AddressUnsigned <= AddressUnBig(7 DOWNTO 0);
			AddressSinus <= std_logic_vector(AddressUnsigned);
			ZnakSinus <= -1;		
		else	
			AddressSinus <= b"00000000";
		end if;	 
    end if;
   end if;  -- if rising_edge(clk) then
  end process;  

end Behavioral;

Ostatnim komponentem jest SineTable_ROM:

  component SineTable_ROM is
     Port ( 
       clka : in STD_LOGIC;
       ena : in STD_LOGIC;
       addra : in STD_LOGIC_VECTOR ( 7 downto 0 );
       douta : out STD_LOGIC_VECTOR ( 31 downto 0 )
  );

Został on wygenerowany za pomocą darmowego IPCore Xilinx'a jako pamięć ROM (w bloku BRAM FPGA).

W pliku SinProjecttestBench.vhd jest symulacja działania modułu liczącego funkcję sinus. Poniżej zamieszczam plik graficzny z wynikiem symulacji:

SineFuncSimulation.thumb.png.2883f533c6ba316fa8bb7b6943c9121d.png

Dla ułatwienia ustawiłem, aby SineValue było od razu wyświetlane jako liczba dziesiętna w formacie Float32. Jak widać zwrócone wartości są poprawne dla podanych kątów. Powyższego modułu mnożna użyć do  liczenia zadania kinematyki prostej dla manipulatora z tego wątku. Na bazie tego modułu można też łatwo stworzyć moduł liczący wartości funkcji cosinus.

W pliku zip spakowany projekt dla Xilinx Vivado2018.2:

SinusCosTestProj01.zip

Jeśli ktoś z Was ma pomysł na ulepszenie tego projektu to z chęcią o tym podyskutuje 😉

Pozdrawiam

Edytowano przez FlyingDutch
  • Lubię! 1
Link do komentarza
Share on other sites

Cześć @Szałszanin,

mam już też skończony  moduł do liczenia funkcji  Cosinus (floating-point). W razie, gdyby obliczenia zmnienno-przecinkowe były zbyt wolne (lub zajmowały za dużo zasobów układu FPGA) mam już też gotowe moduły liczące Sinus i Cosinus w postaci stało-przecinkowej (fixed-point). Zmiana jest banalna bo w całości polega na zmianie zawartości pamięci ROM wygenerowanej programem (plik coe). W najbliższym czasie opublikuje kod tych wszystkich 4 modułów.

Czy mógłbyś już podać końcowe wzory dla trzech współrzędnych kartezjańskich x, y, z w zależności od kątów z siedmiu enkoderów (w przegubach ramienia)? Najlepiej w postaci:

x = tu zależność na wsp. x w zależności od katów enkoderów

y = ....

z = ...

Wtedy mógłbym zaplanować jak zorganizować końcowe obliczenia w układzie FPGA. Oczywiście jak znajdziesz chwilę wolnego czasu 🙂

Pozdrawiam

  • Lubię! 1
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.