使用定时器实现定时、PWM、输入捕获功能
·
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__ */
更多推荐



所有评论(0)