资讯详情

红外遥控器发射端原理与实现

背景介绍:

在最后一篇文章中,我们详细介绍了红外解码的原理和实现。在这里,我们将介绍红外编码的原理和实现。

内容概述:

1 红外信号发射端原理

2 红外信号发射端与接收端的对应关系

3 实现红外发射端功能实例

1红外信号发射端原理

第一个是红外信号发射器本身,它通常长如下:

图中的红外二极管直径为3mm另一种是5mm的。

它们和发光led长得几乎一模一样,所以也是长引脚时接正极,另一个接负极。

最简单的驱动电路是正极街3.3v上,中间加个1k限流电阻,然后将负极连接到单片机IO上图:

2 红外信号发射端与接收端的对应关系

说到这里,我们需要纠正下一篇文章中的一个错误。

上文中这张图片中提到发射端与接收端信号电平是相反的。也就是如上图中红色和蓝色方框中圈出的内容一样。

事实上,在实际波形中,发射端的蓝色部分并不是一个简单的0.56ms高电平.56ms的38kHz的pwm波。

实际测量的波形如下图所示:

如下图所示:

可种密集方波的频率为38kHz。

以下是红外遥控器发射端与接收端的对应关系:

3 实现红外发射端功能实例

进入编程实践。

根据前面的介绍,要实现红外遥控器的功能,首先要实现两个基本功能:

1 38kHz的方波输出

2 控制38kHz所需时间打开和关闭方波

首先是38kHz我们使用方波输出pwm波来生成可以在这里使用定时器pwm功能。我在这里用的是STM32L011F4P6低功耗芯片

用代码生成工具神器cube生成代码:

初始化代码:

static void MX_TIM21_Init(void) {    /* USER CODE BEGIN TIM21_Init 0 */    /* USER CODE END TIM21_Init 0 */    TIM_ClockConfigTypeDef sClockSourceConfig = {0};   TIM_MasterConfigTypeDef sMasterConfig = {0};   TIM_OC_InitTypeDef sConfigOC = {0};    /* USER CODE BEGIN TIM21_Init 1 */    /* USER CODE END TIM21_Init 1 */   htim21.Instance = TIM21;   htim21.Init.Prescaler = 15;   htim21.Init.CounterMode = TIM_COUNTERMODE_UP;   htim21.Init.Period = 25;   htim21.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;   htim21.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;   if (HAL_TIM_Base_Init(&htim21) != HAL_OK)   {     Error_Handler();   }   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;   if (HAL_TIM_ConfigClockSource(&htim21, &sClockSourceConfig) != HAL_OK)   {     Error_Handler();   }   if (HAL_TIM_PWM_Init(&htim21) != HAL_OK)   {     Error_Handler();   }   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;   if (HAL_TIMEx_MasterConfigSynchronization(&htim21, &sMasterConfig) != HAL_OK)   {     Error_Handler();   }   sConfigOC.OCMode = TIM_OCMODE_PWM1;   sConfigOC.Pulse = 11;   sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;   sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;   if (HAL_TIM_PWM_ConfigChannel(&htim21, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)   {     Error_Handler();   }   /* USER CODE BEGIN TIM21_Init 2 */    /* USER CODE END TIM21_Init 2 */   HAL_TIM_MspPostInit(&htim21);  }

启动关闭pwm代码:

//start the pwm HAL_TIM_PWM_Start(&htim21,TIM_CHANNEL_1);  //stop the pwm HAL_TIM_PWM_Stop(&htim21,TIM_CHANNEL_1);

然后按照编码规则打开或关闭pwm使用定时器中断波的功能,然后修改下次中断的时间pwm波开关时间长度:

初始化:

static void MX_TIM2_Init(void) {    /* USER CODE BEGIN TIM2_Init 0 */    /* USER CODE END TIM2_Init 0 */    TIM_ClockConfigTypeDef sClockSourceConfig = {0};   TIM_MasterConfigTypeDef sMasterConfig = {0};    /* USER CODE BEGIN TIM2_Init 1 */    /* USER CODE END TIM2_Init 1 */   htim2.Instance = TIM2;   htim2.Init.Prescaler = 159;   htim2.Init.CounterMode = TIM_COUNTERMODE_UP;   htim2.Init.Period = 999;   htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;   htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;   if (HAL_TIM_Base_Init(&htim2) != HAL_OK)   {     Error_Handler();   }   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;   if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)   {     Error_Handler();   }   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;   if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)   {     Error_Handler();   }   /* USER CODE EGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

中断处理代码:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	//fans remote control
    if (htim == (&htim2)){

    	switch(remote_ctl.state){
    	case PRECODE_H:
    		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
    		HAL_TIM_PWM_Stop(&htim21,TIM_CHANNEL_1);
    		TIM2->ARR = 900 - 1;//9ms
    		remote_ctl.state = PRECODE_L;
    		break;
    	case PRECODE_L:
    		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
    		HAL_TIM_PWM_Start(&htim21,TIM_CHANNEL_1);
    		TIM2->ARR = 450 - 1;//4.5ms
    		remote_ctl.state = USERCODE_H;
    		break;
    	case USERCODE_H:
    		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
    		HAL_TIM_PWM_Stop(&htim21,TIM_CHANNEL_1);
    		TIM2->ARR = 56 - 1;//0.56ms
    		remote_ctl.state = USERCODE_L;
    		break;
    	case USERCODE_L:
    		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
    		HAL_TIM_PWM_Start(&htim21,TIM_CHANNEL_1);
    		if(remote_ctl.usercode >> remote_ctl.usercnt & 0x01)
    			TIM2->ARR = 169 - 1;//1.69ms
    		else
    			TIM2->ARR = 56 - 1;//0.565ms
    		remote_ctl.usercnt++;
    		if(remote_ctl.usercnt >= 16){
    			remote_ctl.usercnt = 0;
    			remote_ctl.state = CTLCODE_H;
    		} else {
    			remote_ctl.state = USERCODE_H;
    		}
    		break;
    	case CTLCODE_H:
    		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
    		HAL_TIM_PWM_Stop(&htim21,TIM_CHANNEL_1);
    		TIM2->ARR = 56 - 1;//0.56ms
    		remote_ctl.state = CTLCODE_L;
    		break;
    	case CTLCODE_L:
    		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
    		HAL_TIM_PWM_Start(&htim21,TIM_CHANNEL_1);
    		if(remote_ctl.ctlcode >> remote_ctl.ctlcodecnt & 0x01)
    			TIM2->ARR = 169 - 1;//1.69ms
    		else
    			TIM2->ARR = 56 - 1;//0.565ms
    		remote_ctl.ctlcodecnt++;
    		if(remote_ctl.ctlcodecnt >= 17){
    			remote_ctl.ctlcodecnt = 0;
    			remote_ctl.state = CTLSTOP;
    		} else {
    			remote_ctl.state = CTLCODE_H;
    		}
    		break;
    	case CTLSTOP:
    		HAL_TIM_PWM_Stop(&htim21,TIM_CHANNEL_1);
    		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
    		remote_ctl.state = PRECODE_H;
    		HAL_TIM_Base_Stop_IT(&htim2);
    		break;
    	default:
    		break;
    	}

    }
}

这里还有一些编码数据的细节就不贴出来了,如果需要更多源代码的话欢迎各位留言,我会尽快为你们提供详细代码。

 

最后为大家贴上一个我调试的风扇遥控器的实例效果:

 

如果各位喜欢的话,欢迎各位给我

 

最后,在这里向大家推荐我自己的个人公众号 “四点能”

公众号里我会根据前面的技术制作出有趣的东西,我们一起体会技术的乐趣

标签: 3mm发射二极管

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台