要求:实现50HZ(20ms)交流电相位采集(0~360.).
实现:其中,用户需要的相位可以通过触摸屏实现(这将在下一次笔记中提起).
这里主要考虑到STM32通用定时器具有捕获输入/输出比较功能.由于其它定时器口线另作它用,故选TIM5_CH2 (PA1)作为交流脉冲输入端.
用TIM5的两次不同中断方式实现此功能.
程序步聚:打开系统所有复位时钟后
1.开TIM5的时钟
/*配置TIM5时钟 */
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM5, ENABLE);
2.配置IO口(PA1)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
/* TIM5 channel 2 pin (PA.01) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
3.TIM5的初始化(输入捕获和计数器自增加后中断输出)
void SetupPWM_Input(void)
{
/* TIM5 configuration: PWM Input mode ------------------------
The external signal is connected to TIM5 CH2 pin (PA.01),
The Rising edge is used as active edge,
The TIM5 CCR2 is used to compute the frequency value
The TIM2 CCR1 is used to compute the duty cycle value
------------------------------------------------------------ */
TIM_ICInitTypeDef TIM_ICInitStructure;
//The TIMxCLK frequency is set to 36 MHz, the Prescaler is 36 so the TIM5 counter
//clock is 1 MHz. 3600M/65535=55Hz The minmum value can be measured is 55Hz,the max is
TIM_PrescalerConfig(TIM5, 35, TIM_PSCReloadMode_Immediate); //TIM5CLK/(36)=1MHz
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;//通道2
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising ;//上升沿捕获
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//将TI2配置到PA1上
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//一次上升沿一个中断
TIM_ICInitStructure.TIM_ICFilter = 0x03;//脉冲滤波
TIM_ICInit(TIM5,&TIM_ICInitStructure);
TIM_PrescalerConfig(TIM5, 35, TIM_PSCReloadMode_Immediate); //TIM5CLK/(36)=1MHz
/* Select the TIM5 Input Trigger: TI1FP1 */
TIM_SelectInputTrigger(TIM5, TIM_TS_TI1FP1);
/* Select the slave Mode: Reset Mode */
TIM_SelectSlaveMode(TIM5, TIM_SlaveMode_Reset);
/* Enable the Master/Slave Mode */
TIM_SelectMasterSlaveMode(TIM5, TIM_MasterSlaveMode_Enable);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM5, TIM_IT_CC2, ENABLE);
/* TIM enable counter */
//TIM_Cmd(TIM2, ENABLE);
TIM_Cmd(TIM5, ENABLE);
TIM5_SetupNVIC();//相位输入中断
}
void SetupPWM_Output(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = PhisicVal;//计数周期
TIM_TimeBaseStructure.TIM_Prescaler = 35; //预分频35+1,得1K HZ 1ms
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
// TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
/*清中断,以免一启用中断后立即产生中断*/
TIM_ClearFlag(TIM5,TIM_FLAG_Update);
/* TIM IT enable 使能中断源*/
TIM_ITConfig(TIM5,TIM_IT_Update, ENABLE);
/* TIM5 总开关,开启enable counter */
TIM_Cmd(TIM5, ENABLE);
/*中断*/
TIM5_SetupNVIC();
}
4.TIM5中断
void TIM5_SetupNVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
/* Enable the TIM5 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
5.stm32f10x_it.c中断的处理函数
/*******************************************************************************
* Function Name : TIM5_IRQHandler
* Description : This function handles TIM5 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void TIM5_IRQHandler(void)
{
if (TIM_GetITStatus(TIM5,TIM_IT_CC2))//捕获输入
{
/* Clear TIM5 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM5, TIM_IT_CC2);
TIM_ITConfig(TIM5, TIM_IT_CC2, DISABLE);
/* Get the Input Capture value */
TIM_SetCompare2(TIM5, 0x0000);//TIM5->CCR2=0;//清捕获2的值
TIM_SetCounter(TIM5, 0x0000);//记数器清零
SetupPWM_Output();
}
if (TIM_GetITStatus(TIM5,TIM_IT_Update))//比较输出
{
//PhisicRecive_Flag=TRUE;
GPIO_WriteBit(GPIOA,GPIO_Pin_8,(BitAction)(1)); //打开P8开关 主开关闭合
TIM_ClearITPendingBit(TIM5, TIM_IT_Update);
TIM_ITConfig(TIM5, TIM_IT_Update, DISABLE);
}
}
6.主函数中:计算相位和计数器计数值之间的关系
因为TimCLK=36M/36=1M=1us;
交流电50HZ=20ms;
所以:当计数器值到达20ms/1us=20000时.相位为360度.
void CalcPhisicVal(void) //计算相位的预加载值
{
float PhisicVal_f;
if(IntnumTestphasic>=360) IntnumTestphasic="IntnumTestphasic"%360;
PhisicVal_f=20000.0*IntnumTestphasic/360.0;
PhisicVal=(vu16) PhisicVal_f;
}
至此,终于可以实现相位的采集和控制了.
问题总结:
1,TIM8用同样的方法捕获输入,脉冲来是中断无响应.不知道是不是还有其它控制位没有设置好,(已排除硬件问题)??---待高手指点
2,定时器的比较输出,只能将端口电平反转,不引起中断,我这里要引起中断,因此不好用---由于对此不熟悉,浪费了一些时间,故本小姐要引以为戒,下次看资料时要详细,且考虑问题要周全.
用户547841 2010-3-16 15:42
用户1492773 2009-9-11 14:29