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

背景介绍:

上一篇文章我们详细介绍了红外解码的原理与实现,这里我们来介绍下红外编码的原理以及实现。

 

内容概述:

1 红外信号发射端原理

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

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

 

1 红外信号发射端原理

首先是红外信号发射的器件本身,它一般长下面这样:

图片中的这个红外二极管直径是3mm的,另外还有一种是5mm的。

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

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

 

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

说到这里,需要跟大家更正下上一篇文章中的一个错误。

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

其实实际波形中,发射端的蓝色部分不是一个简单的0.56ms的高电平。而是0.56ms的38kHz的pwm波。

实际测量的波形如下图:

 

图中发射端的波色部分波形详情如下图:

可以看出,这个密集方波的频率是38kHz。

这里总结下:红外遥控器发射端与接收端的对应关系:

发射端输出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 BEGIN 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;
    	}

    }
}

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

 

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

 

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

 

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

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

  • 14
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值