STM8L101F3输入捕获测脉宽及占空比

本文主要介绍通过STM8L10X固件库实现对脉宽调制波的检测




近期空闲时做了一个STM8L101芯片的PWM检测程序,在此发表个人见解。

预备知识:

STM8L库函数的使用、STM8L定时器的使用,相关资料自行百度

目标:通过TIM3输出PWM波,将输出的波输入至TIM2的捕获通道。

好了,接下来进入正题。

STM8L10X的定时器的功能比较丰富,而且价格低廉,做输入捕获还是挺好的

首先介绍一个STM8L101X固件库的一个函数,在固件库的

 line 444 of file stm8l10x_tim2.c.

	TIM2_PWMIConfig是专门用来配置PWM输入模式的库函数,网上关于此处的介绍比较少,这里简要介绍并应用

该函数原型如下:

00420 /**
00421   * @brief  Configures the TIM2 peripheral in PWM Input Mode according to the
00422   *         specified parameters.
00423   * @param  TIM2_Channel: TIM2 Channel				输入捕获的通道
00424   *          This parameter can be one of the following values:
00425   *            @arg TIM2_Channel_1: Channel 1
00426   *            @arg TIM2_Channel_2: Channel 2     
00427   * @param  TIM2_ICPolarity: Input Capture Polarity		PWM开始的极性,可选为上升沿/下降沿
00428   *          This parameter can be one of the following values:
00429   *            @arg TIM2_ICPolarity_Rising: Input Capture on Rising Edge
00430   *            @arg TIM2_ICPolarity_Falling: Input Capture on Falling Edge  
00431   * @param  TIM2_ICSelection: Input Capture Selection		输入通道与捕获通道的连接,此处
								TIM2_ICSelection_DirectTI表示捕获通道1与输入通道1连接
								
					TIM2_ICSelection_IndirectTI表示捕获通道1与输入通道2连接
第三个值好像是与另外一个管脚连接,应该是TRGI
00432 * This parameter can be one of the following values:
00433   *   @arg TIM2_ICSelection_DirectTI: Input Capture mapped on the direct input
00434   *    @arg TIM2_ICSelection_IndirectTI: Input Capture mapped on the indirect input
00435   *            @arg TIM2_ICSelection_TRGI: Input Capture mapped on the Trigger Input  
 00436   * @param  TIM2_ICPrescaler: Input Capture Prescaler		分频,表示多少个电位突变触发一个事件
00437   *          This parameter can be one of the following values:
00438   *            @arg TIM2_ICPSC_DIV1: Input Capture Prescaler = 1 (one capture every 1 event)
00439   *            @arg TIM2_ICPSC_DIV2: Input Capture Prescaler = 2 (one capture every 2 events)
00440   *            @arg TIM2_ICPSC_DIV4: Input Capture Prescaler = 4 (one capture every 4 events)
00441   *            @arg TIM2_ICPSC_DIV8: Input Capture Prescaler = 8 (one capture every 8 events) 
00442   * @retval None
00443   */
00444 void TIM2_PWMIConfig(TIM2_Channel_TypeDef TIM2_Channel,
00445                      TIM2_ICPolarity_TypeDef TIM2_ICPolarity,
00446                      TIM2_ICSelection_TypeDef TIM2_ICSelection,
00447                      TIM2_ICPSC_TypeDef TIM2_ICPrescaler,
00448                      uint8_t TIM2_ICFilter)
00449 {
00450   uint8_t icpolarity = (uint8_t)TIM2_ICPolarity_Rising;
00451   uint8_t icselection = (uint8_t)TIM2_ICSelection_DirectTI;
00452 
00453   /* Check the parameters */
00454   assert_param(IS_TIM2_CHANNEL(TIM2_Channel));
00455 
00456   /* Select the Opposite Input Polarity */
00457   if (TIM2_ICPolarity == TIM2_ICPolarity_Rising)		//配置开始时触发方式
00458   {
00459     icpolarity = (uint8_t)TIM2_ICPolarity_Falling;
00460   }
00461   else
00462   {
00463     icpolarity = (uint8_t)TIM2_ICPolarity_Rising;
00464   }
00465 
00466   /* Select the Opposite Input */
00467   if (TIM2_ICSelection == TIM2_ICSelection_DirectTI)		//另外一个捕获通道触发方式相反
00468   {
00469     icselection = (uint8_t)TIM2_ICSelection_IndirectTI;
00470   }
00471   else
00472   {
00473     icselection = (uint8_t)TIM2_ICSelection_DirectTI;
00474   }
00475 
00476   if (TIM2_Channel == TIM2_Channel_1)			
00477   {
00478     /* TI1 Configuration */
00479     TI1_Config(TIM2_ICPolarity, TIM2_ICSelection,
00480                TIM2_ICFilter);
00481 
00482     /* Set the Input Capture Prescaler value */
00483     TIM2_SetIC1Prescaler(TIM2_ICPrescaler);
00484 
00485     /* TI2 Configuration */
00486     TI2_Config((TIM2_ICPolarity_TypeDef)icpolarity, (TIM2_ICSelection_TypeDef)icselection, TIM2_ICFilter);
00487 
00488     /* Set the Input Capture Prescaler value */
00489     TIM2_SetIC2Prescaler(TIM2_ICPrescaler);
00490   }
00491   else
00492   {
00493     /* TI2 Configuration */
00494     TI2_Config(TIM2_ICPolarity, TIM2_ICSelection,
00495                TIM2_ICFilter);
00496 
00497     /* Set the Input Capture Prescaler value */
00498     TIM2_SetIC2Prescaler(TIM2_ICPrescaler);
00499 
00500     /* TI1 Configuration */
00501     TI1_Config((TIM2_ICPolarity_TypeDef)icpolarity, (TIM2_ICSelection_TypeDef)icselection, TIM2_ICFilter);
00502 
00503     /* Set the Input Capture Prescaler value */
00504     TIM2_SetIC1Prescaler(TIM2_ICPrescaler);
00505   }
00506 }
00507 
 
 


部分注释见上,简要分析可知,该函数将选择的输入通道连接到定时器的捕获通道1和捕获通道2上,并且捕获通道1为检测开始沿,捕获通道2则检测

第二个电位沿,比如配置为上升沿为PWM开始,则PWM中间为下降沿


好了,该函数功能就是这样了,下面是一些检测函数,环境为STVD:


Tim2_Impulse_Detection.h头文件

#ifndef Tim2_Impulse_Detection
#define Tim2_Impulse_Detection




/*
此库文件用于捕获Tim2通道1的输入并检测频率以及脉宽
*/
#include <stm8l10x.h>
#include <stm8l10x_clk.h>
#include <stm8l10x_tim2.h>
#include <stm8l10x_tim3.h>
#include <stm8l10x_gpio.h>




extern u8 temp; //中间变量,用于判断上升0/下降1
extern int ICValue1; //上升沿记录的值
extern int ICValue2; //下降沿记录的值
extern int ICValue3; //第二个上升沿记录的值
extern u8 update_high; //高电位溢出总数
extern u8 update_count; //溢出总数
extern u8 rate; //占空比,丢弃小数位




void Tim2_Impulse_Detection_Init(void); //Tim2_Impulse_Detection初始化
@far @interrupt void TIM2_Capture_Compare_HandledInterrupt (void); //捕获中断服务函数
@far @interrupt void TIM2_Update_Overflow_Trigger_Break_HandledInterrupt (void); //溢出中断服务函数
void Tim2_Impulse_Detection_Get_Cycle(int* cycle_ms,int* cycle_us,u8* rate); //获得输入信号周期以及脉宽
void Tim3_PWM_Out(void); //Tim3输出PWM波






#endif


Tim2_Impulse_Detection.c源文件

#include <Tim2_Impulse_Detection.h>


/*
脉冲周期范围(建议值):50us~1s
脉宽时间范围(建议值):50us~1s
*/


u8 temp; //中间变量,用于判断第一次进入上升沿捕获0/第二次上升沿捕获1
int ICValue1; //上升沿记录的值
int ICValue2; //下降沿记录的值
int ICValue3; //第二个上升沿记录的值
u8 update_high; //高电位溢出总数
u8 update_count; //溢出总数


/**************************************
函数名:Tim2_Impulse_Detection_Init
功能:初始化Tim2为输入捕获
参数:无
返回值:无
描述:
**************************************/
void Tim2_Impulse_Detection_Init(void) //Tim2_Impulse_Detection初始化
{
CLK_MasterPrescalerConfig(CLK_MasterPrescaler_HSIDiv8); //系统时钟频率2Mhz
GPIO_Init(GPIOB , GPIO_Pin_0 , GPIO_Mode_In_PU_No_IT);//TIM2_CH1   PB0端口
CLK_PeripheralClockConfig(CLK_Peripheral_TIM2,ENABLE); //使能时钟

TIM2_DeInit();
TIM2_TimeBaseInit(TIM2_Prescaler_2, TIM2_CounterMode_Up, 30000);//计数周期1us,向上计数,溢出值为30000
TIM2_PWMIConfig(TIM2_Channel_1,
                 TIM2_ICPolarity_Rising,
                     TIM2_ICSelection_DirectTI,
                 0x00,
                     0x00);
//PWN输入配置:通道1,上升沿,直接输入,无分频,无滤波
//该函数配置捕获通道1为上升沿,捕获通道2为下降沿
}




/**************************************
函数名:TIM2_Capture_Compare_HandledInterrupt
功能:TIM2_Capture_Compare_HandledInterrupt中断服务程序
参数:无
返回值:无
描述:
**************************************/
@far @interrupt void TIM2_Capture_Compare_HandledInterrupt (void) //捕获中断服务函数
{
if((TIM2_GetITStatus(TIM2_FLAG_CC1)) != RESET)
{
if(temp)
{
ICValue3=TIM2_GetCapture1();

TIM2_ClearFlag(TIM2_FLAG_CC1); //清除通道中断标志
TIM2_ClearITPendingBit(TIM2_IT_CC1);
TIM2_ITConfig( TIM2_IT_Update, DISABLE); //关闭溢出中断
TIM2_CCxCmd(TIM2_Channel_1, DISABLE); //关闭通道1
TIM2_ITConfig(TIM2_IT_CC1, DISABLE); //关闭捕获通道1中断
TIM2_CCxCmd(TIM2_Channel_2, DISABLE); //关闭通道2
TIM2_ITConfig(TIM2_IT_CC2, DISABLE); //关闭捕获通道2中断
temp=0;
}
else
{
ICValue1=TIM2_GetCapture1();

TIM2_ITConfig( TIM2_IT_Update, ENABLE); //使能溢出中断
TIM2_ClearITPendingBit(TIM2_IT_Update);
TIM2_ClearITPendingBit(TIM2_IT_CC1);
TIM2_ClearFlag(TIM2_FLAG_CC1); //清除中断标志
TIM2_CCxCmd(TIM2_Channel_2,ENABLE); //使能捕获通道2
TIM2_ITConfig( TIM2_IT_CC2 , ENABLE);//使能TIM2输入通道2中断
TIM2_ClearFlag(TIM2_FLAG_CC2); //清除通道中断标志
TIM2_ClearITPendingBit(TIM2_IT_CC2);
temp=1;

}
}
if((TIM2_GetITStatus(TIM2_FLAG_CC2)) != RESET)
{
ICValue2=TIM2_GetCapture2();

update_high=update_count;
TIM2_ClearFlag(TIM2_FLAG_CC2); //清除通道中断标志
TIM2_ClearITPendingBit(TIM2_IT_CC2);
TIM2_CCxCmd(TIM2_Channel_2,DISABLE); //失能捕获通道2
TIM2_ITConfig( TIM2_IT_CC2 , DISABLE);//失能TIM2输入通道2中断
}
}






/**************************************
函数名:TIM2_Update_Overflow_Trigger_Break_HandledInterrupt
功能:TIM2_Update_Overflow_Trigger_Break_HandledInterrupt中断服务程序
参数:无
返回值:无
描述:
**************************************/
@far @interrupt void TIM2_Update_Overflow_Trigger_Break_HandledInterrupt (void) //溢出中断服务函数
{
update_count++;
TIM2_ClearITPendingBit(TIM2_IT_Update);
TIM2_ClearFlag(TIM2_IT_Update);
}




/**************************************
函数名:Tim2_Impulse_Detection_Get_Cycle
功能:Tim2_Impulse_Detection_Get_Cycle获取输入PWM波的脉宽与占空比
参数:
cycle_ms 一个储存周期毫秒数的指针
cycle_us 一个储存周期微秒数的指针
rate 一个储存占空比的指针
返回值:无
描述:初始化完毕后,直接调用即可取得脉宽与占空比
**************************************/
void Tim2_Impulse_Detection_Get_Cycle(int* cycle_ms,int* cycle_us,u8* rate) //获得输入信号周期以及脉宽
{
double cycle;
double cycle_high;
_asm("sim"); //关闭总中断

temp=0;
ICValue1=0;
ICValue2=0;
ICValue3=0;
update_high=0;
update_count=0;
//清零所有变量




TIM2_CCxCmd(TIM2_Channel_1,ENABLE); //使能捕获通道1
TIM2_ITConfig( TIM2_IT_CC1 , ENABLE);//使能TIM2输入通道1中断
TIM2_ClearFlag(TIM2_FLAG_CC1); //清除通道中断标志
TIM2_Cmd(ENABLE);
_asm("rim"); //开启总中断

while(!temp);
while(temp);

*cycle_ms=30*update_count+(ICValue3-ICValue1)/1000;
*cycle_us=(ICValue3-ICValue1)%1000;
cycle=(*cycle_ms)*1000+(*cycle_us);
cycle_high=30*update_high*1000+ICValue2-ICValue1;
*rate=cycle_high/cycle*100;

TIM2_Cmd(DISABLE); //关闭TIM2
}


/**************************************
函数名:Tim3_PWM_Out
功能:Tim3输出PWM波
参数:无
返回值:无
描述:
**************************************/
void Tim3_PWM_Out(void) //Tim3输出PWM波
{
GPIO_Init(GPIOB , GPIO_Pin_1 , GPIO_Mode_Out_PP_Low_Fast);//TIM3_CH1   PB1端口
CLK_PeripheralClockConfig(CLK_Peripheral_TIM3,ENABLE); //使能时钟

TIM3_DeInit();
TIM3_TimeBaseInit(TIM3_Prescaler_2, TIM3_CounterMode_Up, 500);//计数周期1us,向上计数,周期500us
TIM3_OC1Init(TIM3_OCMode_PWM1,TIM3_OutputState_Enable,250,TIM3_OCPolarity_High,TIM3_OCIdleState_Reset);
TIM3_Cmd(ENABLE);
TIM3_CtrlPWMOutputs(ENABLE);
}

简单的检测程序(UART串口通讯需自行编辑):


/*
脉冲输入端为   PB0(HS)/TIM2_CH1/COMP1_CH1
*/
#include <UART.h>
#include <Tim2_Impulse_Detection.h>








void main()
{
int cycle_ms;
int cycle_us;
u8 rate;


_asm("sim");
UART_Init();
GPIO_Init(GPIOA,GPIO_Pin_2|GPIO_Pin_3,GPIO_Mode_Out_PP_Low_Fast); //推挽输出
Tim2_Impulse_Detection_Init();
Tim3_PWM_Out();
while(1)
{
GPIO_SetBits(GPIOA,GPIO_Pin_2);
Tim2_Impulse_Detection_Get_Cycle(&cycle_ms,&cycle_us,&rate);
GPIO_ResetBits(GPIOA,GPIO_Pin_2);///
GPIO_ResetBits(GPIOA,GPIO_Pin_3);///
USART_Send_One_Byte(0x00);
USART_Send_One_Byte(0x00);
USART_Send_One_Byte((u8)(cycle_ms>>8));
USART_Send_One_Byte((u8)(cycle_ms&0xff));
USART_Send_One_Byte(0x00);
USART_Send_One_Byte((u8)(cycle_us>>8));
USART_Send_One_Byte((u8)(cycle_us&0xff));
USART_Send_One_Byte(0x00);
USART_Send_One_Byte(rate);
USART_Send_One_Byte(0x00);
USART_Send_One_Byte(0x00);


}
}

结果如下,其中显示的为16进制,脉冲周期501us,占空比49%,还行吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值