stm32 7483(가산기) 74138(디코더)

전자인간·2022년 5월 21일
/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2022 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "rtc.h"
#include "gpio.h"
#include <string.h>
#include <stdio.h>
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

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

/* USER CODE END PTD */

/* 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 -----------------------------------------------*/
void SystemClock_Config(void);



/* USER CODE BEGIN PFP */
//new function
void GPIO_Moder();

int JKFF_Module(JKFF *_JKFF, int i);
int pulse_module(pulse_struct *ps, int select);

pulse_struct pulse[4];
JKFF jkff[4];



void counter_Synchronous_up(JKFF *_jkff,  int pulse_status);
void counter_Synchronous_down(JKFF *_jkff,  int pulse_status);


void counter_Asynchronous_up(JKFF *_jkff,  int pulse_status);
void counter_Asynchronous_down(JKFF *_jkff,  int pulse_status);
/* USER CODE END PFP */

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

uint16_t inputC = 0;
uint16_t inputG = 0;





/* 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 */

	pulse[0].trigger_state = 0;
	pulse[0].trigger = 1;
	pulse[0].pulse_output = 0;
	pulse[0].delay = 500;

	for(int i = 0; i < 4; i++){
		memset(&jkff[i], 0, sizeof(struct _JKFF));
	}
	/* 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_RTC_Init();
	//new function
	GPIO_Moder();
	/* USER CODE BEGIN 2 */
	int pulse_select = 0;
	int pulse_select_save = 0;
	int pulse_status = 0;			//High,Low
	int mode = 0;	// 0 -> Syn_up / 1 -> Syn_down / 2 -> Asyn_up / 3 -> Asyn_down
	/* USER CODE END 2 */

	/* Infinite loop */
	/* USER CODE BEGIN WHILE */
	while (1) {

		inputC = GPIOC->IDR;
		inputG = GPIOG->IDR;

		pulse_select_save = pulse_select;		// Use when pulse_select change.
		pulse_select = 0;						//pulse mode select

		if(pulse_select_save != pulse_select){	// if select changed, initializing value to 0
			memset(&pulse[pulse_select_save],0,sizeof(struct _pulse_struct));
		}
		pulse_status = pulse_module(pulse, pulse_select);	//pulse_status. It depends on pulse_module status

		for(int i = 0; i < 4; i++) {
			if(~inputG & 0x01 << i) {
				mode = i;
			}
		}
		if(mode == 0) {
			counter_Asynchronous_up(jkff,  pulse_status);
		}
		else if(mode == 1) {
			counter_Synchronous_down(jkff,  pulse_status);
		}
//		else if(~inputG == 0x04) {
//			counter_Asynchronous_up(jkff, pulse_status);
//		}
//		else if(~inputG == 0x08) {
//			counter_Asynchronous_up(jkff, pulse_status);
//		}



		//counter_Synchronous_up(jkff,  pulse_status);

		//counter_Synchronous_down(jkff,  pulse_status);

		/* 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 };

	/** Configure the main internal regulator output voltage
	 */
	__HAL_RCC_PWR_CLK_ENABLE();
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	/** Initializes the RCC Oscillators according to the specified parameters
	 * in the RCC_OscInitTypeDef structure.
	 */
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI
			| RCC_OSCILLATORTYPE_LSE;
	RCC_OscInitStruct.LSEState = RCC_LSE_ON;
	RCC_OscInitStruct.HSIState = RCC_HSI_ON;
	RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
	RCC_OscInitStruct.PLL.PLLM = 8;
	RCC_OscInitStruct.PLL.PLLN = 180;
	RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
	RCC_OscInitStruct.PLL.PLLQ = 4;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
		Error_Handler();
	}

	/** Activate the Over-Drive mode
	 */
	if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
		Error_Handler();
	}

	/** Initializes the CPU, AHB and APB buses clocks
	 */
	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
			| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
		Error_Handler();
	}
}

/* USER CODE BEGIN 4 */
void GPIO_Moder() {
	GPIOD->MODER = 0x00000055;			// GPIOD output mode PIND 0~7
}


int pulse_module(pulse_struct *ps, int select) {
	if(ps[select].trigger == 0 && ps[select].trigger_state == 0) {	// init upper_edge
		ps[select].pulse_output = 0;
	}
	else if(ps[select].trigger == 1 && ps[select].trigger_state == 0) {	// init down_edge
		ps[select].pulse_output = 1;
	}
	else {
		ps[select].pulse_output ^= 1;		// next pulse will change after delay.
	}

	if(ps[select].trigger_state == 0) ps[select].trigger_state  = 1;	// after select edge, cannot change edge.

	HAL_Delay(ps[select].delay);

	return ps[select].pulse_output;

}

int JKFF_Module(JKFF *_JKFF, int i) {				// for each JKFF struct
	if (_JKFF[i].ck_save == 1 && _JKFF[i].ck == 0) {		// when down_edge
		if (_JKFF[i].j == 0) {
			if (_JKFF[i].k == 0) {	//j = 0, k = 0  -> stay
				_JKFF[i].q = _JKFF[i].q;
			} else {		//j = 0, k = 1  -> 0
				_JKFF[i].q = 0;
			}
		}

		else {
			if (_JKFF[i].k == 0) {	//j = 1, k = 0  -> 1
				_JKFF[i].q = 1;
			} else {		//j = 1, k = 1  -> toggle
				_JKFF[i].q ^= 1;
			}

		}
	} else {	//not down _edge
		_JKFF[i].q = _JKFF[i].q;
	}

	_JKFF[i].ck_save = _JKFF[i].ck;

	return _JKFF[i].q;


}


void counter_Synchronous_up(JKFF *_JKFF,  int pulse_status) {
	int sum = 0;
	int Q[4] ={0,};

	_JKFF[0].ck = pulse_status;

	 for(int i = 0; i < 4; i++) {
		 _JKFF[i].j = 1;
		 _JKFF[i].k = 1;
		 Q[i] = JKFF_Module(_JKFF, i);
		 _JKFF[i+1].ck = Q[i];
		 sum += Q[i]<<i;
	 }

	 GPIOD -> ODR = sum;
}
void counter_Synchronous_down(JKFF *_jkff,  int pulse_status) {
	int sum = 0;
	int Q[4] ={0,};

	 _jkff[0].ck = pulse_status;

	 for(int i = 0; i < 4; i++) {
		 _jkff[i].j = 1;
		 _jkff[i].k = 1;
		 Q[i] = JKFF_Module(_jkff, i);
		 _jkff[i+1].ck = !Q[i];
		 sum += Q[i]<<i;
	 }

	 GPIOD -> ODR = sum;
}

//void counter_Synchronous_up() {
//	int j = 1, k = 1;
//}
//처음 시작 pulse_Now 0일 때 pulse_Next = 1이됨 + 0.25초.-> pulse_Now가 1이 되고 pulse_Next = 0이 됨 +0.25초.
//pulse_Now 가 1이고 pulse_Next가 0이 되어 마지막에 하강엣지가 된다. 1Hz 0.5초 지난 꼴.
void counter_Asynchronous_up(JKFF *_jkff,  int pulse_status) {
	int sum = 0;
	int Q[4] ={0,};
	_jkff[0].j = 1;
	_jkff[0].k = 1;

	for (int i = 0; i < 4; i++) {
		_jkff[i].ck = pulse_status;
		Q[i] = JKFF_Module(_jkff, i);
		if (i == 1) {
			if(Q[1] == 1 && Q[0] == 1){
				_jkff[2].j = 1;
				_jkff[2].k = 1;
			}
		} else if (i == 2) {
			if(Q[2] == 1 && _jkff[2].j == 1 && _jkff[2].k == 1) {
				_jkff[3].j = 1;
				_jkff[3].k = 1;
			}
		}  else if( i == 3){
			Q[3] = Q[3];
		} else {
			_jkff[i+1].j = Q[i];
			_jkff[i+1].k = Q[i];
		}
		sum += Q[i]<<i;
	}
	 GPIOD -> ODR = sum;
}



/* 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 */
	__disable_irq();
	while (1) {
	}
	/* 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,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

0개의 댓글