最近在做STM32工频相位及采集,主要用到TIM8_CH1及TIM4_CC_IRQ.将工作中使用的主要寄存器配置及主要思路记录下来,希望对即将从来该方面工作的研友们有所帮助,
也希望可以指引新人入门.同时希望前辈能给予指正,代码中存在问题及可改进之处.
由于工作时间有限,所记录之处难免有漏,像系统时钟及IO口配置等,默认研友们已作相应且正确配置.
思路
TIM8 的CH1通道1作为输入捕获.同时产生中断.
TIM4 的4路输出中的TIM4_CH1通道一作为输出比较,同时产生中断.
方法
1) 设置计数器向下计数模式,自动重载寄存器设置为:0xFFFF,这样计数器会循环计数
2) 设置工频周期计数(由TIM8_CH1通道1us采一次)为,当前TIM4_CH1预加载值(即将于定时器TIM4_CC1_CNT比较的值).
3) TIM4定时器通道设置为输出比较模式,并设置比较匹配时,产生相应的中断.
4) 在中断中将PF0(=1) 高压放电.
高级定时器TIM8_CH1,用于输入捕获.这在前面一遍工作笔记中已作描述,有不懂的可以留言探讨.
settimer.c如下:
extern volatile float Value;
void Tim4_SetupTIMOC(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 0xffff; //自动重载寄存器 ARR
TIM_TimeBaseStructure.TIM_Prescaler = 71; //分频系统720 PSCR TIM4系统时钟为:72MHZ 72MHZ/(71+1)=1MHZ 即:1us
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
/* Output Compare Timing Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse =(u32) (Value);//设置预加载值 CCR1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM4, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_ClearFlag(TIM4,TIM_FLAG_Update);//清中断,以免一启用中断后立即产生中断
Tim4_SetupNVIC();// 中断使能
}
void Tim4_EnableTIMOC(void)
{
// TIM IT enable 使能中断源
TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE);
// TIM4->DIER |=0x0002;
/* TIM4 总开关,开启enable counter */
TIM_Cmd(TIM4, ENABLE);
// TIM4->CR1 |=0x0081;
TIM_ARRPreloadConfig(TIM4, ENABLE);
TIM_OC1PreloadConfig(TIM4,TIM_OCPreload_Disable);//预加载值立即生效 这条语句很重要
}
void Tim4_DisableTIMOC(void)
{
// TIM IT enable 禁能中断源
TIM_ITConfig(TIM4, TIM_IT_CC1, DISABLE);
/* TIM2 总开关,开启enable counter */
TIM_Cmd(TIM4, DISABLE);
}
stm32f10x_it.c如下:
extern volatile bool Tim8_NVIC2_f;
extern volatile bool Phasic_F;
void TIM4_IRQHandler(void)//10us定时中断
{
if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)
{
GPIO_WriteBit(GPIOF,GPIO_Pin_0,(BitAction)(0)); // //打开PF0开关 主开关闭合
// u16 count="TIM"_GetCounter(TIM4); 调试用
Tim4_DisableTIMOC();
TIM4->CNT = 0;
TIM4->ARR = 65535;
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1);
Phasic_F=TRUE;
}
}
void TIM8_CC_IRQHandler(void)
{
if (TIM_GetITStatus(TIM8, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM8, TIM_IT_CC1);
if(Tim8_NVIC2_f) //相位同步触发用
{
Tim8_NVIC2_f=FALSE;
Tim4_SetupTIMOC();
Tim4_EnableTIMOC();
// TIM IT disable 禁能中断源
TIM_ITConfig(TIM8,TIM8_CC_IRQChannel, DISABLE);
/* TIM8 总开关,关闭Disable counter */
TIM_Cmd(TIM8, DISABLE);
}
else //工频周期采集用
{
Tim4_DisableTIMBASE();
if(HW_flag==0)
{
IC1[HW_NUM]=TIM8->CCR1;
if ( IC1[HW_NUM] != 0)
{
IC1[HW_NUM]=TIM8->CCR1;
TIM8->CNT = 0;
TIM8->ARR = 65535;
}
}
HW_NUM++;
if(HW_NUM>=14) //共采集14个数据作平均数
{
HW_NUM=0;
HW_flag=1;
}
}
}
}
main.c 如下:
#define Phasic 0x01 //定义工频投入 键码:0x01
main()
{
GET_period();
if(Phasic_F)
{
Phasic_F=FALSE;
//DoComplete();做相位同步完成的工作
}
if(GetKey() == Phasic)
{
Tim8_NVIC2_f=TRUE;
//other things...
}
}
void GET_period(void)
{
unsigned int temp;
unsigned int sum="0";
if(HW_flag==1)
{
for(i=0;i<14;i++)
{
temp="IC1";
sum +=temp;
}
ICValue="sum/14";
// ICValue="20000"; 调试用
if(IntnumTestphasic == 0)//将用户设定0度归为360度处理,提高相位同步精度.
{
IntnumTestphasic="360";
}
Value=( (ICValue)/360.0)*( IntnumTestphasic); //工频相位0~360度平均到1us 的预加载值
HW_flag=0;
}
}
文章评论(0条评论)
登录后参与讨论