|
使用STM32F401定时器3捕获输入信号,捕获信号的有效高电平,但是捕获的信号不完整,会漏掉几位。代码如下:
/*************************************** 配置部分代码 ************************************************/
TIM_HandleTypeDef TIM3_Handler; //定时器 3 句柄
TIM_HandleTypeDef TIM5_Handler; //定时器 5 句柄
void TIM5_Init(unsigned int arr,unsigned short psc)
{
__HAL_RCC_TIM5_CLK_ENABLE();
TIM5_Handler.Instance = TIM5; //通用定时器5
TIM5_Handler.Init.Prescaler = psc; //分频系数
TIM5_Handler.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数
TIM5_Handler.Init.Period = arr; //自动装载值
TIM5_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //时钟分频因子
HAL_TIM_Base_Init(&TIM5_Handler); //初始化定时器5
__HAL_TIM_ENABLE(&TIM5_Handler); //使能定时器5
}
/*********************
配置TIM3定时器输入捕获
*********************/
void TIM3_Cap_Init(unsigned int arr,unsigned short psc)
{
TIM_IC_InitTypeDef TIM3_CH1Config;
TIM3_Handler.Instance = TIM3; //通用定时器3
TIM3_Handler.Init.Prescaler = psc; //分频系数
TIM3_Handler.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数
TIM3_Handler.Init.Period = arr; //自动装载值
TIM3_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; //时钟分频因子
HAL_TIM_IC_Init(&TIM3_Handler); //初始化输入捕获时基参数
TIM3_CH1Config.ICPolarity = TIM_ICPOLARITY_RISING; //设置上升沿捕获
TIM3_CH1Config.ICSelection = TIM_ICSELECTION_DIRECTTI; //映射到TI1上
TIM3_CH1Config.ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
TIM3_CH1Config.ICFilter = 0; //设置输入滤波,不滤波
HAL_TIM_IC_ConfigChannel(&TIM3_Handler,&TIM3_CH1Config,TIM_CHANNEL_1); //配置TIM3通道1
HAL_TIM_IC_Start_IT(&TIM3_Handler,TIM_CHANNEL_1); //开启捕获通道,并开启捕获中断
__HAL_TIM_ENABLE_IT(&TIM3_Handler,TIM_IT_UPDATE); //使能更新中断
}
/**************************
定时器3 底层驱动,时钟使能,引脚配置
此函数会被HAL_TIM_IC_Init()调用
**************************/
void HAL_TIM_IC_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_TIM3_CLK_ENABLE(); //使能 TIM3 时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); //开启 GPIOA 时钟
GPIO_Initure.Pin = GPIO_PIN_6; //PA6
GPIO_Initure.Mode = GPIO_MODE_AF_OD; //复用推挽输出
GPIO_Initure.Pull = GPIO_PULLUP; //上拉
GPIO_Initure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //高速
GPIO_Initure.Alternate = GPIO_AF2_TIM3; //PA6复用为TIM3通道1
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
HAL_NVIC_SetPriority(TIM3_IRQn,2,0); //设置中断优先级,抢占 2,子优先级 0
HAL_NVIC_EnableIRQ(TIM3_IRQn); //开启 ITM3 中断通道
}
//捕获状态
//[7]:0,没有成功的捕获;1,成功捕获到一次.
//[6]:0,还没捕获到低电平;1,已经捕获到低电平了.
//[5:0]:捕获低电平后溢出的次数(对于 32 位定时器来说,1us 计数器加 1,溢出时间:4294 秒)
unsigned char TIM3CH1_CAPTURE_STA; //输入捕获状态
unsigned int TIM3CH1_CAPTURE_VAL; //输入捕获值(TIM2/TIM5 是 32 位)
unsigned int TIM3CH1_CAPTURE_OK = 0;
unsigned int TIM3CH1_CAPTURE_CNT = 0;
unsigned int TIM3CH1_CAPTURE_BIT_CNT = 0;
unsigned char TIM3CH1_CAPTURE_BUFF_LEN = 0;
unsigned char *TIM3CH1_CAPTURE = (unsigned char *)0x20000B00;
//定时器 3 中断服务函数
void TIM3_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM3_Handler);//定时器共用处理函数
}
//定时器更新中断(溢出)中断处理回调函数, 在 HAL_TIM_IRQHandler 中会被调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断发生时执行
{
if((TIM3CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if(TIM3CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM3CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
{
TIM3CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次
TIM3CH1_CAPTURE_VAL=65535;
}
else
TIM3CH1_CAPTURE_STA++;
}
}
}
//定时器输入捕获中断处理回调函数,该函数在 HAL_TIM_IRQHandler 中会被调用
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
{
if((TIM3CH1_CAPTURE_STA&0X80)==0) //还未成功捕获
{
if(TIM3CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
{
TIM3CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次高电平脉宽
TIM3CH1_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&TIM3_Handler,TIM_CHANNEL_1); //获取当前的捕获值
TIM_RESET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1); //清除设置
TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1,
TIM_ICPOLARITY_RISING); //上升沿捕获
}
else //还未开始,第一次捕获上升沿
{
TIM3CH1_CAPTURE_STA=0; //清空
TIM3CH1_CAPTURE_VAL=0;
TIM3CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
__HAL_TIM_DISABLE(&TIM3_Handler); //关闭定时器 3
__HAL_TIM_SET_COUNTER(&TIM3_Handler,0);
TIM_RESET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1); //清除原来设置
TIM_SET_CAPTUREPOLARITY(&TIM3_Handler,TIM_CHANNEL_1,
TIM_ICPOLARITY_FALLING); //下降沿捕获
__HAL_TIM_ENABLE(&TIM3_Handler); //使能定时器 3
}
}
}
/************************************************ 捕获信号处理代码 ****************************************************************/
unsigned char RecvData(unsigned char *byBuff)
{
unsigned char byCmdLen = 0;
if( TIM3CH1_CAPTURE_STA & 0x80 ) //捕获一次高电平
{
if( TIM3CH1_CAPTURE_VAL > 100 && TIM3CH1_CAPTURE_VAL < 600) //捕获有效高电平:0 小于400微秒 600 * 48 / 72000000
{
byTIM3CH1[TIM3CH1_CAPTURE_CNT] = TIM3CH1_CAPTURE_VAL;
byCap[TIM3CH1_CAPTURE_CNT] = 0;
TIM3CH1_CAPTURE_CNT++;
TIM3CH1_CAPTURE_OK = 1;
TIM3CH1_CAPTURE_BIT_CNT = 0;
}
else if( TIM3CH1_CAPTURE_VAL > 600 && TIM3CH1_CAPTURE_VAL < 800 ) //捕获有效高电平:1
{
byTIM3CH1[TIM3CH1_CAPTURE_CNT] = TIM3CH1_CAPTURE_VAL;
byCap[TIM3CH1_CAPTURE_CNT] = 1;
TIM3CH1_CAPTURE_CNT++;
TIM3CH1_CAPTURE_OK = 1;
TIM3CH1_CAPTURE_BIT_CNT = 0;
}
if( TIM3CH1_CAPTURE_OK == 1 ){
TIM3CH1_CAPTURE_BIT_CNT++;
__HAL_TIM_SET_COUNTER(&TIM5_Handler,0);
}
TIM3CH1_CAPTURE_STA = 0;
}
if( __HAL_TIM_GET_COUNTER(&TIM5_Handler) > 2000 && TIM3CH1_CAPTURE_OK == 1 )
{
SLK_OUT(0); //拉低,方便查看结束标志
TIM3CH1_CAPTURE_OK = 0;
TIM3CH1_CAPTURE_BIT_CNT = 0;
byCmdLen = Toyato_Decode(byBuff,TIM3CH1_CAPTURE_CNT);
TIM3CH1_CAPTURE_CNT = 0;
memset(byCap,0,256);
memset(byTIM3CH1,0,128);
}
return byCmdLen;
}
我想获取有效的高电平值得时候,只读到了一段信号,前后的信号丢失了,请大家帮忙看看是什么原因。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|