第一次自己写完整的硬件驱动,发上来给大家看看,顺便吸收些改进方案,希望各位能够不吝赐教,指出代码的不足之处。同时我也很高兴这代码能给你带来帮助。
工程使用CubeMX创建,使用VS Code编程,单片机为STM32F103VCT6。

首先配置时钟,下载方式,开启USART以方便调试,这里就不具体展示了。开启某个定时器的输入捕获【Input Capture direct mode】预分频系数设为(72-1),开启捕获中断【TIM1 capture compare interrupt】优先级最好高一些(默认为0),其他设置默认。
这里以定时器1的通道一为例:将红外接收模块的输出端接入PA8即可,由于STM32F103VCT6的最高主频为72MHz故预分频系数设为(72-1),这样可以使计数每1μs加一,方便计算时间,开启捕获中断:
生成代码。将IR.c及IR.h文件添加到工程中(这两个文件将会放在在文章的下面,有较全的注释)
在相应位置修改main.c:

/* USER CODE BEGIN Includes */
#include "IR.h"
/* USER CODE END Includes *//* USER CODE BEGIN PV */
uint32_t temp = 0;//用于接收数据
/* USER CODE END PV *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if (IR_Scanf(&temp)){printf("%X\r\n", temp);//这里需要重定向至串口后使用}}/* USER CODE END 3 *//* USER CODE BEGIN 4 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获回调函数
{if (TIM1 == htim->Instance){IR_CaptureCallback();}
}
/* USER CODE END 4 */

修改完成后即可编译下载。打开串口助手就可以看到遥控器发来的信息了。

基本上换个遥控器只需修改IR.h文件的内容就可以了,包括使用的定时器及其通道、各种逻辑的持续时间(我这个遥控器就不完全是NEC编码所以会有些不同,还请自己测试后修改)、是否检查编码正确性等可以方便修改的地方。
下面就是所需要的文件:
IR.c:

//csdn_可谓不低
#include "IR.h"
#include "main.h"
#include "tim.h"#define CHECK_TIME_LOGIC_0() (CaptureBuf >= IR_us_LOGIC_0 - IR_DEVIATION && CaptureBuf <= IR_us_LOGIC_0 + IR_DEVIATION)
#define CHECK_TIME_LOGIC_1() (CaptureBuf >= IR_us_LOGIC_1 - IR_DEVIATION && CaptureBuf <= IR_us_LOGIC_1 + IR_DEVIATION)
#define CHECK_TIME_START() (CaptureBuf >= IR_us_START - IR_DEVIATION && CaptureBuf <= IR_us_START + IR_DEVIATION)
#define CHECK_TIME_REPEAT_START() (CaptureBuf >= IR_us_REPEAT_START - IR_DEVIATION && CaptureBuf <= IR_us_REPEAT_START + IR_DEVIATION)
#define CHECK_TIME_REPEAT_END() (CaptureBuf >= IR_us_REPEAT_END - IR_DEVIATION && CaptureBuf <= IR_us_REPEAT_END + IR_DEVIATION)uint16_t CaptureBuf = 0; //存放捕获缓存
uint8_t CaptureFlag = 1; //捕获标志位
uint8_t IRData[4] = {0};//存放数据
uint8_t IRFlag = 0;//红外接收状态
uint8_t IRReceiveFlag = 0;//完成接收标志void IR_Init()
{__HAL_TIM_SET_CAPTUREPOLARITY(&IR_TIM, IR_TIM_CHANNE, TIM_INPUTCHANNELPOLARITY_RISING); //改为上升沿HAL_TIM_IC_Start_IT(&IR_TIM, IR_TIM_CHANNE);                             //启动输入捕获
}
void IR_CaptureCallback()
{if (CaptureFlag){__HAL_TIM_SET_COUNTER(&IR_TIM, 0);__HAL_TIM_SET_CAPTUREPOLARITY(&IR_TIM, IR_TIM_CHANNE, TIM_ICPOLARITY_FALLING); //设置为下降沿捕获CaptureFlag = 0;                                                                                                                          //状态标志位置0}else{CaptureBuf = HAL_TIM_ReadCapturedValue(&IR_TIM, IR_TIM_CHANNE);                                              //获取当前的捕获值.__HAL_TIM_SET_CAPTUREPOLARITY(&IR_TIM, IR_TIM_CHANNE, TIM_INPUTCHANNELPOLARITY_RISING); //改为上升沿CaptureFlag = 1;                                                                                                                                             //状态标志位置1if (CHECK_TIME_START())    //接收到数据开始位{IRFlag = 1;for (uint8_t i = 0; i < 4; i++){IRData[i] = 0;//清空数据}return; //退出,等待接收数据}else if (CHECK_TIME_REPEAT_START()) //接收到循环开始位{IRFlag = 40; //重复码标记return;           //退出,等待循环第二位}if (IRFlag && IRFlag <= 32)//接收数据{if (CHECK_TIME_LOGIC_1()) //判断为逻辑1{IRData[(IRFlag - 1) / 8] |= (1 << (7 - (IRFlag - 1) % 8));}else if (!CHECK_TIME_LOGIC_0()) //判断不是逻辑0{IRFlag = 0; //直接退出接收return;}IRFlag++;if (IRFlag == 33)//接收32个,接收完成{if(IR_CHECK_ADDRESS && IRData[0] != (uint8_t)~IRData[1] || IR_CHECK_COMMAND && IRData[2] != (uint8_t)~IRData[3])//校验{return;}IRReceiveFlag = 1;return;}}if (IRFlag == 40){if (CHECK_TIME_REPEAT_END()){IRReceiveFlag = IR_CHECK_REPEAT;}}}
}
uint8_t IR_Scanf(uint32_t* data)
{if(IRReceiveFlag)IRReceiveFlag=0;else return 0;*data=0;for(uint8_t i=0;i<4;i++){*data|=IRData[i]<<8*(3-i);}return 1;
}

IR.h:

//csdn_可谓不低
#ifndef __IR_H
#define __IR_H#include "main.h"#define IR_TIM htim1
#define IR_TIM_CHANNE TIM_CHANNEL_1#define IR_us_LOGIC_0 560
#define IR_us_LOGIC_1 1640
#define IR_us_START 4480
#define IR_us_REPEAT_START 39350
#define IR_us_REPEAT_END 2220
#define IR_DEVIATION 100    //误差范围#define IR_CHECK_ADDRESS 1  //1:检查地址位 0:取消
#define IR_CHECK_COMMAND 1  //1:检查数据位 0:取消
#define IR_CHECK_REPEAT 1   //1:检查重复   0:取消void IR_Init(void);
void IR_CaptureCallback(void);
uint8_t IR_Scanf(uint32_t* data);#endif
/**************************************** 1        00FFA25D* 2        00FF629D* 3        00FFE21D* 4        00FF22DD* 5        00FF02FD* 6        00FFC23D* 7        00FFE01F* 8        00FFA857* 9        00FF906F* *        00FF6897* 0        00FF9867* #        00FFB04F* up       00FF18E7* left     00FF10EF* OK       00FF38C7* right    00FF5AA5* down     00FF4AB5
*****************************************/
/***************************************** 放入捕获中断回调函数中使用,按需修改TIM1
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{if (TIM1 == htim->Instance){IR_CaptureCallback();}
}
******************************************/

STM32 CubeMX HAL库 之红外接收(NEC协议)定时器捕获相关推荐

  1. stm32捕获占空比_【电机控制】六步法驱动BLDC电机,使用硬件COM事件,STM32+CUBEMX(HAL库)配置...

    现在我也只能说是电机入门,但是想要把电机作为终身事业,从有霍尔到无霍尔,从方波到正弦波,现在把其中的一些知识点分享出来,因为电机控制其实的资料比较难找的,前人栽树,后人乘凉,如果我有什么错误,在知乎上 ...

  2. 【电机控制】六步法驱动BLDC电机,使用硬件COM事件,STM32+CUBEMX(HAL库)配置

    已经做了半年的BLDC驱动器了,目前是做到了电流转速双闭环,期间遇到了很多很多问题,一个是资料难找,再加上公司要求使用CUBEMX,本身HAL库的资料也难找,难上加难啊,可能是用CUBEMX做出来的大 ...

  3. 【STM32+CubeMX+HAL库】摩尔斯译码器开发

    虽然寄存器开发执行效率很高,但代码的移植性只能说一般,标准库导入文件,相对来说也比较麻烦,那么CubeMX和HAL库的出现,让广大开发者们多了一份选择. STM32CubeMX给了想上手开发STM32 ...

  4. STM32基于HAL库自由启动和关闭定时器:

    最近在利用hal库做STM32的按键消抖的时候采用进入外部中断后开启10ms定时器中断的方式,但是要求进入定时器中断后就关闭定时器,也就相应需要开启和关闭定时器的函数,然后遇到了一个兄台发布的问题及解 ...

  5. 【STM32】CubeMX+HAL库之 硬件IIC+DMA控制OLED(兼容SSD1306SH1106驱动)

    [STM32]CubeMX+HAL库之 硬件IIC+DMA控制1.3寸OLED 前言 目前网上大多数驱动OLED屏都采用软件IIC,因为HAL库的升级使得硬件IIC的稳定性得到了保障,所以想采用硬件I ...

  6. 【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(一)

    前言: 本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 本文 1首先讲解什么是FMC及SDRAM,W9825G6KH芯片原理,2基于CubeMx创建工程 ...

  7. 【STM32】HAL库 STM32CubeMX教程十四---SPI

    前言: 本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 在我们的HAL库中,对硬件SPI函数做了很好的集成,使得之前SPI几百行代码,在HAL库中,只需 ...

  8. STM32的HAL库分析及使用

    STM32的三种开发方式 通常新手在入门STM32的时候,首先都要先选择一种要用的开发方式,不同的开发方式会导致你编程的架构是完全不一样的.一般大多数都会选用标准库和HAL库,而极少部分人会通过直接配 ...

  9. 正点原子STM32(基于HAL库)0

    目录 开发环境搭建与使用 常用开发工具简介 MDK 安装 仿真器驱动安装 CH340 USB 虚拟串口驱动安装 使用MDK5 编译例程 使用串口下载程序 使用DAP 下载与调试程序 使用DAP 下载程 ...

最新文章

  1. python-回调函数和递归函数
  2. error LNK2019: 无法解析的外部符号 __imp__inet_ntoa@4
  3. android学习笔记Fragment的使用
  4. 建立单独的解决方案来开发DNN模块
  5. windows命令提示符下输入net start/stop mysql发生系统错误5,拒绝访问的解决方法
  6. linux下装jdk以及failed /usr/local/jdk1.6.0_10/jre/lib/i386/client/libjvm.so,
  7. 软件工程——结对编程第二次作业
  8. Android RecyclerView (一) 使用完全解析
  9. 【BZOJ2054】疯狂的馒头(并查集)
  10. msys2软件包管理工具pacman常用命令
  11. jsf标签_JSF Facelet标签示例教程
  12. 模块电源(二):电感式DC-DC升压器
  13. Android开发22——广播接收者BroadcastReceiver的原理和注册方式
  14. 监听套接字为什么要设置成非阻塞的?
  15. mysql查询最接近的记录
  16. NornJ-javascript模版引擎
  17. 关于word的标题处小黑点的去除
  18. love2d角度,方向以及旋转
  19. book--Unix Linux大学教程
  20. Qt开源作品35-秘钥生成器

热门文章

  1. 从头开始制作51智能车——循迹+遥控+避障
  2. 使用并行的方法计算斐波那契数列 (Fibonacci)
  3. Unity游戏运行闪退问题定位与解决(标签:Oops、crashed、System out of memory、UnityEngine.AssetBundle:LoadAsset_Internal)
  4. IntelliJ IDEA 外接显示器 分屏后,窗口打不开,不会显示
  5. git 使用writer_「github 教程」写给大家看的教程:从零开始在GitHub上部署个人博客 - seo实验室...
  6. excel模板文件下载与导入校验
  7. 交换式路由器与路由式交换机
  8. 搭档之家:以中位数碾压腾讯平均数!网曝台积电普通员工年薪约37.4万元
  9. 解决ubuntu过热:gnome-shell扩展 cpu power manager
  10. 两种启动模式安装windows操作系统