测试芯片STM32F103C8T6,外部时钟
1、输入捕获通道测试
TIM1的CH1N,无法进行输入捕获(估计是没找到其他原因,测试就也没有测试出来效果),直接改用TIM1的CH1通道进行测试,可以进行捕获中断测试;
在用CH1的通道输入捕获配置时,必须TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;对此初始化,第一次测试发现这个参数默认是10,不知道什么原因,后来加上这句好就好了,意思代表的是多少次计数周期更新一次中断事件;
2、输入捕获中断中不要做太多事情,尽量用寄存器操作
初始配置采用的上升沿配置,在捕获中断中更改捕获中断的沿方式;
一进入捕获中断,先对TIM1->CNT = 0;,然后再是其他操作,注意操作顺序,顺序不同会导致误差不同,见代码;
3、设置的存储计数器的值,采用的变量类型是volatile,否则会导致偶尔数据不对;
4、在用串口显示测试信号的信息时,会关闭总中断,执行结束后,再打开,否则会导致偶尔数据不对;
5、实际用捕获中断进行捕获时,总会存在误差的,在此我在串口输出显示时,做了矫正处理,每个处理器不同,矫正的大小也不同,尤其在TIM1更新中断发生时,产生的误差更大;
6、用PB0(输出PWM)和PA8(检测信号频率)进行测试的
当PB0输出较低频率时,会导致TIM_Period超过65535,实际测试好像超过也没什么问题;
//
/*************************1---main函数串口信息打印********************************/
while(1)
{
if(delayFlag == 1)//定时1s
{
delayFlag = 0;
if(IC_OccurFlag == 1)
{
__disable_irq();
CheckNoSignalCount = 0;
IC_OccurFlag = 0;
// LED_On_OFF();
PWM_OverFlow_temp1 = PWM_OverFlow_temp11;
PWM_OverFlow_temp2 = PWM_OverFlow_temp22;
IC1_High_temp = IC1_High;
IC1_Low_temp = IC1_Low+81;//矫正,只需矫正这一个,高电平不用矫正
printf("高电平溢出次数:%d \r\n",PWM_OverFlow_temp1);
printf("低电平溢出次数:%d \r\n",PWM_OverFlow_temp2);
while(PWM_OverFlow_temp1--)
{
IC1_High_temp += (65536-5528);//矫正
}
while(PWM_OverFlow_temp2--)
{
IC1_Low_temp += (65536-5528);//矫正
}
printf("高电平时间:%.1f us\r\n",IC1_High_temp/Calc_PWM_TimerFreq_M);
printf("低电平时间:%.1f us\r\n",IC1_Low_temp/Calc_PWM_TimerFreq_M);
TestPWM_Period = (float)((float)IC1_High_temp+IC1_Low_temp)/Calc_PWM_TimerFreq_M;
printf("测试信号周期:%.1f us\r\n",TestPWM_Period);
TestPWM_Freq = (float)(1000000.0f)/TestPWM_Period;
printf("测试信号频率:%.2f HZ\r\n",(TestPWM_Freq));
printf("-----------------------------------------\r\n");
IC1_High_temp = IC1_Low_temp = 0;
__enable_irq();
}
else
{
if(CheckNoSignalCount++ >= 3)
{
CheckNoSignalCount = 3;
printf("没有检测到测试信号\r\n");
}
}
}
if(EXTIFlag == 1)
{
EXTIFlag = 0;
printf("外部中断进入");
}
}
/*************************2---PWM输出信号********************************/
#ifndef __PWM_OUT_H
#define __PWM_OUT_H
#include "stm32f10x.h"
#define PWM_Out_GPIO GPIOB
#define PWM_Out_Pin GPIO_Pin_0
#define PWM_Out_Timer TIM3
#define PWM_Out_TimerFreq (u32)(72000000)
#define PWM_Out_TimerPre (u16)(72)
#define PWM_Out_Freq (u16)(1200)//
#define PWM_Out_TimerPeriod (u16)(PWM_Out_TimerFreq/PWM_Out_TimerPre/PWM_Out_Freq)
void PWM_OUT_Config(void);
#endif
#include "PWM_Out.h"
void PWM_OUT_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;//定义结构体
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE );
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
GPIO_InitStructure.GPIO_Pin = PWM_Out_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 上拉输入
GPIO_Init(PWM_Out_GPIO, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = PWM_Out_TimerPeriod; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
TIM_TimeBaseStructure.TIM_Prescaler = PWM_Out_TimerPre-1; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(PWM_Out_Timer, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//选择定时器模式,TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//输出比较极性低
TIM_OC3Init(PWM_Out_Timer, &TIM_OCInitStructure);//根据结构体信息进行初始化
TIM_OC3PreloadConfig(PWM_Out_Timer, TIM_OCPreload_Enable); //使能定时器TIM2在CCR2上的预装载值
TIM_Cmd(PWM_Out_Timer, ENABLE);
TIM_SetCompare3(PWM_Out_Timer,(u32)PWM_Out_TimerPeriod*3/4);//得到占空比为50%的pwm波形
}
/*************************3---检测信号的频率********************************/
#ifndef __CALC_PWM_H
#define __CALC_PWM_H
#include "stm32f10x.h"
#define Calc_PWM_GPIO GPIOA
#define Calc_PWM_Pin GPIO_Pin_8
#define Calc_PWM_Timer TIM1
#define Calc_PWM_TimerFreq (u32)(72000000)
#define Calc_PWM_TimerFreq_M (u32)(Calc_PWM_TimerFreq/1000000)
#define Calc_PWM_TimerPre (u16)(1)
#define Calc_PWM_Freq (u16)(1200)//测试最小PWM频率
#define Calc_PWM_TimerPeriod (u16)(Calc_PWM_TimerFreq/Calc_PWM_TimerPre/Calc_PWM_Freq)//此值最大65535 ;833us的周期时间
extern volatile float IC1_High,IC1_Low,IC1_Period;
extern volatile float IC1_High_temp,IC1_Low_temp;
extern volatile u8 IC_OccurFlag;
extern volatile u8 Control_OccurFlag;
extern volatile u16 PWM_OverFlow,PWM_OverFlow_temp1,PWM_OverFlow_temp11,PWM_OverFlow_temp2,PWM_OverFlow_temp22;
void Calc_PWM_Config(void);
#endif
#include "Calc_PWM.h"
volatile float IC1_High,IC1_Low,IC1_Period;
volatile float IC1_High_temp,IC1_Low_temp;
volatile u8 IC_OccurFlag;
volatile u8 Control_OccurFlag;
volatile u16 PWM_OverFlow=0,PWM_OverFlow_temp1,PWM_OverFlow_temp11,PWM_OverFlow_temp2,PWM_OverFlow_temp22;
void Calc_PWM_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;//定义结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE );
GPIO_InitStructure.GPIO_Pin = Calc_PWM_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO_Mode_IN_FLOATING GPIO_Mode_Out_PP GPIO_Mode_AF_PP
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(Calc_PWM_GPIO, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = Calc_PWM_TimerPeriod;
TIM_TimeBaseStructure.TIM_Prescaler = Calc_PWM_TimerPre-1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
// TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(Calc_PWM_Timer, &TIM_TimeBaseStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(Calc_PWM_Timer, &TIM_ICInitStructure);
TIM_SelectInputTrigger(Calc_PWM_Timer, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(Calc_PWM_Timer, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(Calc_PWM_Timer,TIM_MasterSlaveMode_Enable);
//
// TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//选择定时器模式,TIM脉冲宽度调制模式2
// TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
// TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//输出比较极性低
// TIM_OC1Init(Calc_PWM_Timer, &TIM_OCInitStructure);//根据结构体信息进行初始化
// TIM_OC1PreloadConfig(Calc_PWM_Timer, TIM_OCPreload_Enable); //使能定时器TIM2在CCR2上的预装载值
TIM_ClearITPendingBit(Calc_PWM_Timer,TIM_IT_Update);
TIM_ITConfig(Calc_PWM_Timer, TIM_IT_CC1, ENABLE);
TIM_ITConfig(Calc_PWM_Timer, TIM_IT_Update, ENABLE);
TIM_Cmd(Calc_PWM_Timer, ENABLE);
// TIM_SetCompare1(Calc_PWM_Timer,Calc_PWM_TimerPeriod/3);//得到占空比为50%的pwm波形
//TIM_CtrlPWMOutputs(TIM1, ENABLE); //pwm输出
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;//捕获中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;//更新中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
extern void Test_PA1_HighLow(void);
extern void Test_PA1_High(void);
extern void Test_PA1_Low(void);
void TIM1_UP_IRQHandler(void)
{
if(TIM_GetITStatus(Calc_PWM_Timer,TIM_IT_Update) != RESET)
{
//Test_PA1_HighLow();
TIM_ClearITPendingBit(Calc_PWM_Timer, TIM_IT_Update);
PWM_OverFlow++;
}
}
void TIM1_CC_IRQHandler(void)
{
if (TIM_GetITStatus(Calc_PWM_Timer, TIM_IT_CC1) != RESET)
{
// Calc_PWM_Timer->SR = ~(TIM_IT_CC1);
// if(Control_OccurFlag == 1)
// {
// if(IC1_High>14200)//
// {
// Calc_PWM_Timer->CNT = 0;
// }
// }
Calc_PWM_Timer->CNT = 0;
//
if(TIM1->CCER & 0X0002)//判断下降沿
{
//TIM_OC1PolarityConfig(Calc_PWM_Timer,TIM_OCPolarity_High);
IC1_High = Calc_PWM_Timer->CCR1;//TIM_GetCapture1(Calc_PWM_Timer);
PWM_OverFlow_temp11 = PWM_OverFlow;
PWM_OverFlow = 0;
TIM1->CCER &= 0XFFFD;
IC_OccurFlag = 1;
}
else
{
// TIM_OC1PolarityConfig(Calc_PWM_Timer,TIM_OCPolarity_Low);
IC1_Low = Calc_PWM_Timer->CCR1;//TIM_GetCapture1(Calc_PWM_Timer);
//Calc_PWM_Timer->CNT = 0;
PWM_OverFlow_temp22 = PWM_OverFlow;
PWM_OverFlow = 0;
TIM1->CCER |= 0X0002;
}
TIM_ClearITPendingBit(Calc_PWM_Timer, TIM_IT_CC1|TIM_IT_Update);
//
//Calc_PWM_Timer->CNT = 0;//加上这句,实际测试信号周期时间偏小;
}
}