STM32F103C8T6单片机使用CubeMX软件,基于HAL库实现定时器的定时、PWM、输入捕获功能。

一、定时功能实现

        设计一个1s的定时中断,基于定时器1,如何配置?

        定时器时钟输入源都是72Mhz;

        预分频器PSC通常可以设置为7200 * 100 -1,进入CNT的时钟信号周期为100us;

        自动重装载寄存器CAR可以设置为1000 * 10 - 1,定时中断周期则为1s。

        特别注意:预分频和自动重装载寄存器都是16位的,不要溢出。

        CubeMX软件设置:

设置完CubeMX软件按下生成代码后,要在生成的代码工程里添加:

        实现一秒周期翻转一次LED灯状态。

二、PWM脉宽调制功能实现

        设计输出一个周期500us(频率2Khz),占空比50%的PWM,基于定时器1通道1,如何配置?

         CubeMX软件设置:

设置完CubeMX软件按下生成代码后,要在生成的代码工程里添加:

三、输入捕获功能实现

        实现红外接收功能。

        CubeMX软件设置:

infrared_driver.c 文件

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "stm32f1xx.h"
#include "tim.h"
#include "infrared_driver.h"

#define TICK_HEAD_MAX     20000    // 表示引导码周期最大值20000us
#define TICK_HEAD_MIN     10000    // 表示引导码周期最小值10000us
#define TICK_0_MAX        1800     // 表示二进制0周期最大值1800us
#define TICK_0_MIN        500      // 表示二进制0周期最小值500us
#define TICK_1_MAX        3000     // 表示二进制1周期最大值3000us
#define TICK_1_MIN        1800     // 表示二进制1周期最小值1800us

static uint8_t g_irCodeBuffer[4];
static bool g_irCodeFlag;

static void ParseIrFrame(uint32_t tickNum)
{
	static bool s_headFlag = false;
	static uint8_t s_index = 0;
	
	/* 先判断tickNum是不是引导码 */
	if ((tickNum > TICK_HEAD_MIN) && (tickNum < TICK_HEAD_MAX))
	{
		s_headFlag = true;
		return;
	}
	
	/* 如果不是引导码,并且引导码已经解析到,判断是不是0/1码 */
	if (!s_headFlag)
	{
		return;
	}
	
	/*0X5C: 0 1 0 1 1 1 0 0 ,接收到的顺序 0 0 1 1 1 0 1 0 先发低位,先接收低位*/	
	
	/*如果是1码,将对应位置1*/
	if (tickNum > TICK_1_MIN && tickNum < TICK_1_MAX)
	{
#if 0
		if (s_index >= 0 && s_index <= 7)
		{
		/*
			0000 0000 | 0000 0100 (0000 0001 << 2 -> 0000 0100)
			0000 0100 | 0000 1000 (0000 0001 << 3 -> 0000 1000)
		*/
			g_irCodeBuffer[0] = (g_irCodeBuffer[0] | (1 << s_index));
		}
		else if (s_index >= 8 && s_index <= 15)
		{
			g_irCodeBuffer[1] = (g_irCodeBuffer[1] | (1 << (s_index - 8)));
		}
		else if (s_index >= 16 && s_index <= 23)
		{
			g_irCodeBuffer[2] = (g_irCodeBuffer[2] | (1 << (s_index - 16)));
		}
		else
		{
			g_irCodeBuffer[3] = (g_irCodeBuffer[3] | (1 << (s_index - 24)));
		}
#endif
		g_irCodeBuffer[s_index / 8] = (g_irCodeBuffer[s_index / 8] | (1 << (s_index % 8)));
		s_index++;
	}
	
		/*如果是0码,将对应位清0*/
	if (tickNum > TICK_0_MIN && tickNum < TICK_0_MAX)
	{
		g_irCodeBuffer[s_index / 8] = (g_irCodeBuffer[s_index / 8] & (~(1 << (s_index % 8))));
		s_index++;
	}
	
	/*如果接收到了32位,校验数据码*/
	if (s_index == 32)
	{
		if (g_irCodeBuffer[2] == (uint8_t)(~g_irCodeBuffer[3])) // 判断用户码和反码是否对应 0xff :~0x000000ff->0xFFFFFF00, (__parseRes[2] ^ __parseRes[3]) == 0xFF
		{
			g_irCodeFlag = true;
		}
		else
		{
			g_irCodeFlag = false;
		}
		s_headFlag = false;
		s_index = 0;
	}
}

uint8_t GetIrCode(void)
{
	if (!g_irCodeFlag)
	{
		return 0;
	}
	g_irCodeFlag = false;
	return g_irCodeBuffer[2];
}

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == TIM1)
	{
		uint32_t icValue;
		icValue = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_4);
		__HAL_TIM_SET_COUNTER(&htim1, 0);
		ParseIrFrame(icValue);
	}
}


infrared_driver.h 文件

#ifndef __INFRARED_DRIVER_H__
#define __INFRARED_DRIVER_H__

#include <stdint.h>

#define irKey1 	  0X45
#define irKey2 	  0X46
#define irKey3 	  0X47
#define irKey4 	  0X44
#define irKey5 	  0X40
#define irKey6 	  0X43
#define irKey7 	  0X07
#define irKey8 	  0X15
#define irKey9 	  0X09
#define irKey10   0X16
#define irKey11   0X19
#define irKey12   0X0D
#define irKey13   0X0C
#define irKey14 	0X18
#define irKey15 	0X5E
#define irKey16 	0X08
#define irKey17 	0X1C
#define irKey18 	0X5A
#define irKey19 	0X42
#define irKey20 	0X52
#define irKey21 	0X4A

uint8_t GetIrCode(void);

#endif /* __INFRARED_DRIVER_H__ */
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐