学习stm32已经有一段时间了,接到第一个项目的时候是关于stm32f051的ad配置和da配置,本科时候连51都没接触过的人一上来就是32位单片机,着实让我蛋疼菊紧的很。还好慢慢的啃了中文手册和网上的一些例程,总算是完成的功能。这些个有时间再整理上传吧。
之后又弄了些103的东西,今天主要整理一下在进行信号频率计算的时候遇到的一些问题和解决办法,以便日后查看。也希望给碰到类似问题的童鞋一些启发。
实验要求:使用tim3_etr实现对高频脉冲的频率检测
硬件要求:stm32f103为核心,频率输入管脚为PD2(uart5_rx/t3_etr)
刚拿到这个实验的时候我连tim3是什么东西都不知道,然后查阅手册对tim3的了解如下:(个人见解)
1.timx可以定时,可以进行输入捕获,输入捕获可以测频率可测脉冲宽度,这就是这个实验要用到的功能
2.timx_CCR1 捕获/比较使能寄存器是一个比较重要的寄存器,该寄存器用来存储捕获发生时TIMx_CNT值,我们从TIMx_CCR1中就可以读出通道一捕获发生时刻的TIMx_CNT的值,通过两次捕获(上升沿一次,下降沿一次)的差值,就可以计算出高电平脉冲的宽度,f=1/脉宽。不过貌似这只适用于低频脉冲。我没有用这种方法。
3.TIMx_etr 是外部触发的第二种模式,主要用于脉冲计数。我们要用的就是他
大体了解之后就开始在网上找各种代码来看,大同小异,不过不修改的话都不太能直接用。测频率无非就是两个值,一个是基准时间t,一个是脉冲个数n。f = n/t 就OK了
现在要解决的问题,就是如何测量脉冲个数的问题。每一个TIM都一个自己的计数器,和一个自己的预装载寄存器ARR.这里既然这是为了计数,那么设置ARR的值为0xFFFF,最大值。
配置代码如下所示
TIM_DeInit(TIM3);
TIM_TimeBaseStructure.TIM_Period =0xFFFF;//当计数器从0记到FFF为一个周期,自动装载寄存器ARR中的值
TIM_TimeBaseStructure.TIM_Prescaler = 0X00;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;//设置时钟系数 不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); // Time base configuration
TIM_ITRxExternalClockConfig(TIM3,TIM_TS_ETRF); //配置外部触发,否则不会计数
TIM_ETRClockMode2Config(TIM3, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_Inverted, 0);
TIM_SetCounter(TIM3, 0); //设置计数器为0
TIM_Cmd(TIM3, ENABLE);
至此tim3_etr配置完毕。
接下来要解决的问题是如何进行10ms精确定时。使用tim2实现,配置如下
void Tim2_Config(){
TIM_TimeBaseInitTypeDef TIM2_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_DeInit(TIM2);
TIM2_TimeBaseStructure.TIM_Period =10000;
TIM2_TimeBaseStructure.TIM_Prescaler = 71;
TIM2_TimeBaseStructure.TIM_ClockDivision = 0x0;//ÉèÖÃʱÖÓϵÊý ²»·ÖƵ
TIM2_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//ÏòÉϼÆÊýģʽ
TIM_TimeBaseInit(TIM2, &TIM2_TimeBaseStructure); // Time base configuration
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//Çå³þ¸üбê־λ
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}
中断函数配置如下
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update );
Frequency_value = TIM_GetCounter(TIM3)*10/0.01/1000;//单位khz
TIM_SetCounter(TIM3, 0);
}
}
通过串口发送出去,串口发送配置如下
void uart_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
int fputc(int ch, FILE *f){
USART_SendData(USART1, (unsigned char) ch);
//while (!(USART1->SR & USART_FLAG_TXE));
while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);
return (ch);
}
void UART_send_byte(uint8_t byte)
{
while(!((USART1->SR)&(1<<7)));
USART1->DR=byte;
}
void UART_Send(uint8_t *Buffer, uint32_t Length)
{
TIM_ITConfig(TIM2,TIM_IT_Update,DISABLE ); //此处一定要有否则串口会发送错误
while(Length != 0)
{
while(!((USART1->SR)&(1<<7)));//µÈ´ý·¢ËÍÍê
USART1->DR= *Buffer;
Buffer++;
Length--;
}
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );
}
至此,实验结束。验证通过