# Infrared remote control debugging based on STM32F0 series single chip microcomputer

Principle analysis of infrared remote control

Remote control: the wavelength crystal oscillator with NEC code of 960nm is 455KHZ, and the corresponding transmission frequency (carrier frequency) is 38KHZ,
The remote ID is 0 (i.e. system identification code), and the inverse code is 255. Different remote IDs may be different.

The remote control code consists of three parts
1. leader code 9ms high level + 4.5ms low level
2. System identification code different infrared remote control equipment
3. 8-bit operation code and 8-bit operation inverse code

The sender's level is reverse to the receiver's level.
After receiving the signal from the remote controller, the infrared receiving head decodes the data format as follows:
Write the program according to the format of the signal.
__________________               _______   _   _   _   _   _   _   _   _   ____   ____   ____   ____   ____   ____   ____   ____                                 ___________________________________               _______   ___________________________________________________________
|_____________|       |_| |_| |_| |_| |_| |_| |_| |_| |_|    |_|    |_|    |_|    |_|    |_|    |_|    |_|    |x x x x x x x x|x x x x x x x x|                                   |_____________|       |_|
|<-    9ms  ->|<4.5ms>|
----- leader code ----------- custom code 8bit ------------- custom code '8bit ----------- key data 8bit | key data'8bit | < ------ 40ms ----------- > < 9ms ----- > < 2.1ms > -- at this time, the high level is more than 40ms, then the low level of 9ms and the high level continuous code of 2.1ms appear----------------

0 and 1 start with a low level of 0.56ms (the actual measurement is 500us), the difference is the high level that appears later,
If the high level is 0.56ms (the actual measurement is 500us), it means 0; if the high level is 1.68ms(0.56*3=1.68), it means 1
0.56ms:|_|
_   _   _
0:     |_| |_| |
_   ____   ____
1:     |_|    |_|    |_

When writing code, you only need to detect the time of high level.
The following time is measured by oscilloscope.
High level of guide code: 4.5ms
High level of 0: 0.56ms (measured appearance of 0.5ms)
High level of 1: 1.68ms
High level of consecutive Code: 2.1ms

NEC code analysis

Code display:

```/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file           : main.c
* @brief          : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
*
* 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
*
******************************************************************************
*/
/* USER CODE END Header */

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

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* 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 */
uint32_t Remote_Order = 0;
uint8_t Remote_Count = 0 ;
uint8_t Remote_Reday = 0 ;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
uint8_t Pulse_Width_Check(void);
uint8_t Remote_Process(void);

void delay_us(int32_t nus)
{
int32_t temp;
SysTick->VAL=0X00;//Clear count
SysTick->CTRL=0X01;//Enable, reduce to zero is no action, use external clock source
do
{
}
while((temp&0x01)&&(!(temp&(1<<16))));//Waiting time arrives

SysTick->CTRL=0x00; //Off count
SysTick->VAL =0X00; //Clear count
}
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 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 */

/* 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_USART1_UART_Init();
/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

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

/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(red_GPIO_Port,red_Pin);
//  printf("order-code \r\n");
if(Remote_Reday)
{
uint8_t key = Remote_Process();
printf("order-code =  %08X , key-code = %02X \r\n",Remote_Order,key);
}
}
/* 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 PeriphClkInit = {0};

/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
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.PLLMUL = RCC_PLL_MUL12;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}

/* USER CODE BEGIN 4 */

#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
* @brief  Retargets the C library printf function to the USART.
* @param  None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

return ch;
}
// Pulse processing

uint8_t Pulse_Width_Check(void)
{
uint8_t t=0;
while(IR_IN == GPIO_PIN_SET)
{
t ++ ;
delay_us(20);
if(t==250) return t;
}
return t;
}
// Callback function of external interrupt

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
uint8_t res = 0 ;
uint8_t OK = 0;
uint8_t temp = 0;

if(GPIO_Pin & GPIO_PIN_0)
{
while(1)
{
if(IR_IN == GPIO_PIN_SET)
{
res = Pulse_Width_Check(); // Pulse width measurement
if(res == 250) break;
else if(res >= 200 && res < 250)  OK = 1;
else if(res >= 85 && res < 200)
{
Remote_Reday = 1;
Remote_Count ++;
break;
}
else if(res >= 50 && res < 85) temp = 1;
else if(res >= 10 && res < 50) temp = 0;

if(OK)
{
Remote_Order <<=1;
Remote_Order += temp;
Remote_Count = 0;
}
}
}
}
}

// Decoding processing

uint8_t Remote_Process(void)
{
uint8_t t1 ,t2 ;
t1 = Remote_Order >> 24 ;
t2 = (Remote_Order >> 16) & 0xFF ;
Remote_Reday = 0;
if(t1 ==(uint8_t) ~t2)
{
t1 = Remote_Order >> 8;
t2 = Remote_Order ;
if(t1 ==(uint8_t) ~ t2) return t1;
}
return 0;
}

/* 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(char *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****/
```