当前位置: 首页 > backend >正文

第十章、无线通信之红外遥控协议NEC及红外接收模块驱动的构建

第一节、红外遥控协议NEC介绍:

这里使用逻辑分析仪分析接收到的红外波形,截取了几种关键波形作分析

下图是长按红外遥控按键“1”数秒后松手产生的波形

 下图是起始信号波形(9ms的低电平,4ms的高电平,总共13ms)

下图是数据帧中的“0”信号(640us的低电平,500us的高电平,总共1.14ms)

下图是数据帧中的“1”信号(640us的低电平,1.6ms的高电平,总共2.25ms)

下图是结束信号(640us的脉冲)

下图是重复信号(9ms的低电平,2ms的高电平,总共11ms)

第二节、使用cubeMX快速初始化

厂商的21键红外遥控器的键值对照表:

第三节、红外遥控接收模块驱动的构建

1.代码实例irr.c:

#include "irr.h"
#include "tim.h"
#include "main.h"
#include <stdint.h>// 1.红外接收模块的定时器初始化
void irr_init(void)
{HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);
}typedef struct {//1.是否为第一个边沿:uint8_t is_frist;//2.是否为前导码:uint8_t is_leadcode;//3.是否为重复码:uint8_t is_recode;//4.是否接收完32位数据:uint8_t is_finish;
}Dection_status_t;//检测边沿的状态机对象:
Dection_status_t dec_status = {0};
//接受数据的缓冲区buf;
uint8_t irr_data[4] = {0};//定义开始边沿的计数据:
uint32_t start_down_cnt = 0;//定义下一个边沿的计数值
uint32_t next_down_cnt = 0;//前后两个边沿的宽度:
uint32_t width = 0;//定义一个位索引:
uint8_t bitcount = 0;void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if(htim != &htim2){return;}	if(dec_status.is_frist == 0){__HAL_TIM_SetCounter(&htim2,0);dec_status.is_frist = 1;}if(dec_status.is_frist == 1){next_down_cnt = __HAL_TIM_GetCompare(&htim2, TIM_CHANNEL_3);if(next_down_cnt >= start_down_cnt){width = next_down_cnt - start_down_cnt;}else{width = 65535 - start_down_cnt + 1 + next_down_cnt;}	//对这个宽度进行判断,来识别是前导码,还是逻辑0,或 1,或重复码?if(width > 12500 && width < 15000) //前导码{dec_status.is_leadcode = 1;dec_status.is_recode = 0;}if(width > 10000 && width < 12000) //重复码{dec_status.is_leadcode = 0;dec_status.is_recode = 1;}if(dec_status.is_leadcode == 1){if(width > 900 && width < 1500) //bit 0{irr_data[bitcount /8] >>=1;bitcount++;}else if(width > 2000 && width < 2500) //bit 1{irr_data[bitcount /8] >>=1;irr_data[bitcount /8] |= 0x80;bitcount++;}if(bitcount == 32){dec_status.is_frist = 0;bitcount = 0;next_down_cnt = start_down_cnt = 0;dec_status.is_finish = 1;}}//next下降沿又是下一个检测的起始下降沿。start_down_cnt = next_down_cnt;}}// 2.获取红外数据
bool get_irr_data(uint8_t *data)
{// 获取数据的逻辑...if(!dec_status.is_finish){return false;}if((irr_data[2] & irr_data[3]) == 0)//校验命令码是否正确。{*data = irr_data[2];dec_status.is_finish = 0;return true;}else{return false;}}// 3.是否是重复码
bool is_recode(void)
{return dec_status.is_recode;
}//4.清空重复码状态标记:
void clearReCodeFlag(void)
{dec_status.is_recode = 0;
}

2.应用测试main.c:

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2024 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 "tim.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "irr.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 */
int fputc(int c, FILE* f)
{HAL_UART_Transmit(&huart1, (uint8_t*)&c, 1, HAL_MAX_DELAY);return c;
}
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* 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_TIM2_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */printf("Hello World IRR \n");//初始红外接收:irr_init();uint8_t data = 0;while (1){if(get_irr_data(&data) == true){printf("irr data = %#x \n", data);}/* USER CODE END WHILE */if(is_recode() == true){HAL_Delay(300);printf("recode data = %#x \n", data);//清除标记:clearReCodeFlag();}/* 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};/** Initializes the RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != 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_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/* 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 */__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 */

http://www.xdnf.cn/news/13323.html

相关文章:

  • 洛谷P1923 【深基9.例4】求第 k 小的数
  • 【SQL学习笔记2】深入理解 CASE WHEN 的魔法用法
  • 可视化在车间质量管控中的创新应用,提升品质
  • python模拟键盘 鼠标操作 通过ctypes调用Windows API实现底层输入模拟
  • filebeat原理架构
  • css~word-break属性
  • 核方法、核技巧、核函数、核矩阵
  • 模型训练-关于token【低概率token, 高熵token】
  • 【Python】 -- 趣味代码 - 飞船大战游戏
  • DiffBP: generative diffusion of 3D molecules for target protein binding
  • 智慧园区综合运营管理平台(SmartPark)和安全EHS平台的分工与协作
  • 电动汽车VCU扭矩控制模式分类方法
  • 【javascript】泡泡龙游戏中反弹和查找匹配算法
  • Jaeger开源分布式追踪平台深度剖析(三)Jaeger默认存储Badger原理剖析
  • 网格布局示例代码解析
  • (三)总结(缓存/ETag请求头)
  • CentOS7下的Redis部署
  • XS2105M IEEE 802.3af 兼容、受电设备接口控制器
  • Day27 函数专题2:装饰器
  • 从中科大镜像获取linux内核5.10.168的git方法
  • Python 字符串、字节串与编解码:数据转换的奥秘
  • 【Redis/1-前置知识】分布式系统概论:架构、数据库与微服务
  • 【力扣数据库知识手册笔记】索引
  • java--怎么定义枚举类
  • 状态模式:对象行为的优雅状态管理之道
  • 图像直方图分析:全面掌握OpenCV与Matplotlib绘制技巧
  • 《通信之道——从微积分到 5G》读书总结
  • 最短回文串解题思路分享
  • 基于大模型预测的输尿管上段积水诊疗方案研究报告
  • 【TinyWebServer】HTTP连接处理