一客户,一周前说要做TIM3_CH2定时器输入捕获,一直说搞不定,我让他参考此贴:
http://www.openedv.com/posts/list/16962.htm
此贴1楼就有我发的TIM5_CH1的输入捕获例程,按理说,依葫芦画瓢,实在很容易搞定.
结果,一周过去了,客户果然按时来求助,说还未搞定....
他说:TIM4_CH1用PB6,可以实现,TIM3_CH2用PB5就不行,搞了好久,处于崩溃边缘.
客户原话如下:
XXXX (10:23:59):
正点哥 我还是没弄出来 你说周一弄不出来写 但是我还是坚持的改了又改 还是弄不出来
TIM3->CCMR1|=1<<7; //CC2S=01 选择输入端 IC2映射到TI2上
TIM3->SMCR|=6<<4; //触发选择:滤波后的定时器输入2(TI1FP2)
TIM3->SMCR|=7<<0; //外部时钟模式1
TIM3->CR1|=1<<0; //启动计数器,CEN=1
其他的没问题 应该只需要改这几段代码 怎么改都不行
由于我也很忙,直接就不和他扯那么多了,直接拷贝我之前的代码来修改.
测试平台是战舰板,简单看下原理图,PB5是接的LED,直接将PE2和PB5用杜邦线连接,然后按下KEY2,就会产生低电平脉冲,所以
用了下降沿触发.一切准备就绪后,修改代码如下:
[mw_shl_code=c,true]//TIM5,外部计数模式
void TIM3_CH2_Excnt_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1; //TIM3 时钟使能
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOB->CRL&=0XFF0FFFFF; //PB5 清除之前设置
GPIOB->CRL|=0X00800000; //PB5 输入
GPIOB->ODR|=1<<5; //PB5 上拉
TIM3->ARR=arr; //设定计数器自动重装值
TIM3->
SC=psc; //预分频器
TIM3->CCMR1|=1<<8; //CC2S=01 选择输入端 IC2映射到TI2上
TIM3->CCMR1|=0<<12; //IC2F=0000 配置输入滤波器 不滤波
TIM3->CCER|=1<<5; //CC1P=0 下降沿计数
TIM3->SMCR|=6<<4; //触发选择:滤波后的定时器输入2(TI2FP2)
TIM3->SMCR|=7<<0; //外部时钟模式1
TIM3->CR1|=1<<0; //启动计数器,CEN=1
}
[/mw_shl_code]
main函数代码如下:
[mw_shl_code=c,true]int main(void)
{
u32 oldcnt=0;
Stm32_Clock_Init(9); //系统时钟设置
uart_init(72,9600); //串口初始化为9600
delay_init(72); //延时初始化
TIM3_CH2_Excnt_Init(0XFFFF,0); //外部计数,最大值0xffff
while(1)
{
delay_ms(10);
if(oldcnt!=TIM3->CNT)
{
oldcnt=TIM3->CNT;
printf("cnt:%d
",oldcnt);
}
}
}
[/mw_shl_code]
然后编译,无错误,直接下载.
测试,发现不对,串口没有输出.
于是乎,仿真查看TIM3的寄存器状态,如下:
可以看到,定时器3的时钟是开启了的(这个必须开启,否则没戏)
通道2的设置,也是正常的.
为什么不行呢?难道我的PB5设置错了,再看PB5的寄存器状态:
可以看到,PB5时钟也开启了,上拉输入也正常.这就奇怪了.
于是我再去看开发板的原理图,如下:
不看不知道,一看吓一跳.
原来PB5根本就没有TIM3_CH2的复用功能(默认的复用功能,不包括重映射,重映射得查看参考手册的Remap部分).
PB5默认的复用功能是:I2C1_SMBAI,或者SPI3_MOSI,或者I2S3_SD.
就没有TIM3_CH2的复用功能!!!
现在知道问题了,继续看原理图,找一下TIM3_CH2在哪里,如下:
原来TIM3_CH2在PA7上面,所以立即修改代码如下:
[mw_shl_code=c,true]//TIM5,外部计数模式
void TIM3_CH2_Excnt_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1; //TIM3 时钟使能
RCC->APB2ENR|=1<<2; //使能PORTA时钟
GPIOA->CRL&=0X0FFFFFFF; //PA7 清除之前设置
GPIOA->CRL|=0X80000000; //PA7 输入
GPIOA->ODR|=1<<7; //PA7 上拉
TIM3->ARR=arr; //设定计数器自动重装值
TIM3->
SC=psc; //预分频器
TIM3->CCMR1|=1<<8; //CC2S=01 选择输入端 IC2映射到TI2上
TIM3->CCMR1|=0<<12; //IC2F=0000 配置输入滤波器 不滤波
TIM3->CCER|=1<<5; //CC1P=0 下降沿计数
TIM3->SMCR|=6<<4; //触发选择:滤波后的定时器输入2(TI2FP2)
TIM3->SMCR|=7<<0; //外部时钟模式1
TIM3->CR1|=1<<0; //启动计数器,CEN=1
} [/mw_shl_code]
再下载到开发板.
然后用跟杜邦线连接PE2和PA7,再按KEY2按键,哈哈,期待的结果出来了:
至此,由TIM5_CH1,移植到TIM3_CH2的外部脉冲计数问题圆满解决.
后面我问客户,你的TIM3_CH2,根本不在PB5上面,客户说,我用的STM32F407....
好吧,我又一次无语了....
407暂时没时间帮客户写了,但是客户发的代码,存在的问题其实只有一个:
TIM3->CCMR1|=1<<7; //CC2S=01 选择输入端 IC2映射到TI2上
这句话,很明显的错了,打开参考手册,数数CCMR1到底第几位开始,是配置TI2,就知道问题所在了.
以上就是帮客户解决由TIM5_CH1移植到TIM3_CH2问题的过程.
总结下来,有以下几点需要初学者注意:
1,学会看原理图,知道原理图上/后面的内容的意思,类似TIMx_CHx在哪个IO口上?ADCx_CHx在哪个IO口上的问题,都是从原理图上,就能找到答案的.所以学会看原理图是必须的.
2,写代码要细心.比如客户写错的这句话,1<<7,改为1<<8就对了,这就是看寄存器不细心导致的.还搞了一个星期....这都够把整个手册看一遍的时间了....
3,要学会分析问题. 比如我修改PB5后,发现不能达到预期结果,立即想到的就是仿真,仿真后,原来TIM3_CH2配置没问题,PB5设置也没问题,这个如果不用仿真,就比较难排查了.
说不清到底是哪里的问题.利用仿真,立即知道问题所在,排除软件问题后,考虑是不是硬件有问题.从而快速定位到TIM3_CH2,不在PB5上,这个关键问题所在.
以上就是本案例带给大家的,我从来都推荐大家要学会学习,希望大家从这个例子里面,找到一些学习的办法,从而少走弯路,快速高效的解决问题.
[mw_shl_code=c,true][/mw_shl_code]
一周热门 更多>