作者:陈广
日期:2021-12-22
#include "tim.h"
void MX_TIM3_Init(void)
{
LL_TIM_InitTypeDef TIM_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
/**TIM3 GPIO Configuration
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* TIM3 interrupt Init */
NVIC_SetPriority(TIM3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(TIM3_IRQn);
TIM_InitStruct.Prescaler = 71;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 65535;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_DisableARRPreload(TIM3);
LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
LL_TIM_DisableMasterSlaveMode(TIM3);
LL_TIM_IC_SetActiveInput(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI);
LL_TIM_IC_SetPrescaler(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
LL_TIM_IC_SetFilter(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1);
LL_TIM_IC_SetPolarity(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_FALLING);
/* USER CODE BEGIN TIM3_Init 2 */
LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH2); //启用通道2
LL_TIM_EnableCounter(TIM3); //使能定时器计数器
/* USER CODE END TIM3_Init 2 */
}
/* USER CODE BEGIN 1 */
volatile int cnt, end;
volatile uint8_t data[4] = {0};
/* 描述:等待红外信息并返回解析结果
* 参数:
* addr:存放地址码的uint8_t指针
* 返回:
* >=0:命令码
* -1:重复码
* -2:前导码的高电平错误
* -3:前导码低电平错误
* -4:数字码高电平错误
* -5:数字码低电平错误
* -6:等待超时
* -7:地址码校验错误
* -8:命令码校验错误
*/
int Wait_For_IR(uint8_t *addr)
{
cnt = -2;
end = 0;
data[0] = 0;
data[1] = 0;
data[2] = 0;
data[3] = 0;
TIM3->CCER |= 0x20; //设置为下降沿触发
TIM3->SR = 0; //清除中断标志位
TIM3->DIER = 5; //打开更新和CC2中断
while(!end);
TIM3->DIER = 0; //关闭更新和CC2中断
if(end < 0) return end;
if(data[0] != (uint8_t)(~data[1])) return -7;
if(data[2] != (uint8_t)(~data[3])) return -8;
*addr = data[0];
return data[2];
}
void TIM3_IRQHandler(void)
{
if(TIM3->SR & 1) //定时器到期中断
{
TIM3->SR &= ~1; //清除中断标志位
if(cnt >= -1 && cnt <= 32)
{
end = -6; //接收超时
}
}
if(TIM3->SR & 4) //通道2中断
{
if(TIM3->CCER & 0x20) //如果为下降沿
{
uint32_t falling = TIM3->CCR2;
TIM3->CNT = 0; //清空计数器
TIM3->CCER &= ~0x20; //转换为上升沿触发
if(cnt == -1) //前导码
{ //重复码高电平为2.25ms
if(falling > 2000 && falling < 3000)
{
end = -1;
return;
}
//前导码高电平错误,正确为4.5ms
if(falling < 3500 || falling > 5000) end = -2;
}
else if(cnt >= 0)
{ //数字码高电平错误
if(falling < 500 || falling > 1800)
{
end = -4;
return;
}
//将读取到的数据压入data数组
if(falling > 1125)
{
data[cnt / 8] |= 1 << (cnt % 8);
}
}
cnt++;
}
else //如果为上升沿
{
uint32_t rising = TIM3->CCR2;
TIM3->CNT = 0; //清空计数器
TIM3->CCER |= 0x20; //转换为下降沿触发
if(cnt == -1) //前导码
{ //前导码低电平错误,正确为9ms
if(rising < 8000 || rising > 10000) end = -3;
}
else
{ //数字码低电平错误,正确为560us
if(rising < 500 || rising > 700)
{
end = -5;
return;
}
if(cnt == 32) end = 1; //命令码读取结束
}
}
}
}
/* USER CODE END 1 */
#include "tim.h"
/* TIM3 init function */
void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
LL_TIM_InitTypeDef TIM_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
/**TIM3 GPIO Configuration
PA7 ------> TIM3_CH2
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_7;
GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* TIM3 interrupt Init */
NVIC_SetPriority(TIM3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
TIM_InitStruct.Prescaler = 71;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 65535;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_DisableARRPreload(TIM3);
LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
LL_TIM_DisableMasterSlaveMode(TIM3);
LL_TIM_IC_SetActiveInput(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI);
LL_TIM_IC_SetPrescaler(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
LL_TIM_IC_SetFilter(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1);
LL_TIM_IC_SetPolarity(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_FALLING);
/* USER CODE BEGIN TIM3_Init 2 */
LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH2); //启用通道2
LL_TIM_EnableCounter(TIM3); //使能定时器计数器
/* USER CODE END TIM3_Init 2 */
}
/* USER CODE BEGIN 1 */
volatile int cnt, end;
volatile uint8_t data[4] = {0};
/* 描述:等待红外信息并返回解析结果
* 参数:
* addr:存放地址码的uint8_t指针
* 返回:
* >=0:命令码
* -1:重复码
* -2:前导码的高电平错误
* -3:前导码低电平错误
* -4:数字码高电平错误
* -5:数字码低电平错误
* -6:等待超时
* -7:地址码校验错误
* -8:命令码校验错误
*/
int Wait_For_IR(uint8_t *addr)
{
cnt = -2;
end = 0;
data[0] = 0;
data[1] = 0;
data[2] = 0;
data[3] = 0;
//设置为下降沿触发
LL_TIM_IC_SetPolarity(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_FALLING);
LL_TIM_ClearFlag_UPDATE(TIM3); //清除计数器中断标志位
LL_TIM_ClearFlag_CC2(TIM3); //清除通道2中断标志位
LL_TIM_EnableIT_UPDATE(TIM3); //使能更新中断
LL_TIM_EnableIT_CC2(TIM3); //使能通道2中断
while(!end);
LL_TIM_DisableIT_UPDATE(TIM3); //关闭更新中断
LL_TIM_DisableIT_CC2(TIM3); //关闭通道2中断
if(end < 0) return end;
if(data[0] != (uint8_t)(~data[1])) return -7;
if(data[2] != (uint8_t)(~data[3])) return -8;
*addr = data[0];
return data[2];
}
void TIM3_IRQHandler(void)
{
if(LL_TIM_IsActiveFlag_UPDATE(TIM3)) //定时器到期中断
{
LL_TIM_ClearFlag_UPDATE(TIM3); //清除中断标志位
if(cnt >= -1 && cnt <= 32)
{
end = -6; //接收超时
}
}
if(LL_TIM_IsActiveFlag_CC2(TIM3)) //通道2中断
{
if(LL_TIM_IC_GetPolarity(TIM3, LL_TIM_CHANNEL_CH2) == LL_TIM_IC_POLARITY_FALLING) //如果为下降沿
{
uint32_t falling = LL_TIM_IC_GetCaptureCH2(TIM3);
LL_TIM_SetCounter(TIM3, 0); //清空计数器
LL_TIM_IC_SetPolarity(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING); //转换为上升沿触发
if(cnt == -1) //前导码
{ //重复码高电平为2.25ms
if(falling > 2000 && falling < 3000)
{
end = -1;
return;
}
//前导码高电平错误,正确为4.5ms
if(falling < 3500 || falling > 5000) end = -2;
}
else if(cnt >= 0)
{ //数字码高电平错误
if(falling < 500 || falling > 1800)
{
end = -4;
return;
}
//将读取到的数据压入data数组
if(falling > 1125)
{
data[cnt / 8] |= 1 << (cnt % 8);
}
}
cnt++;
}
else //如果为上升沿
{
uint32_t rising = LL_TIM_IC_GetCaptureCH2(TIM3);
LL_TIM_SetCounter(TIM3, 0); //清空计数器
LL_TIM_IC_SetPolarity(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_FALLING); //转换为下降沿触发
if(cnt == -1) //前导码
{ //前导码低电平错误,正确为9ms
if(rising < 8000 || rising > 10000) end = -3;
}
else
{ //数字码低电平错误,正确为560us
if(rising < 500 || rising > 700)
{
end = -5;
return;
}
if(cnt == 32) end = 1; //命令码读取结束
}
}
}
}
/* USER CODE END 1 */
;