原创 调试TIM输入比较模式笔记

2008-10-13 19:12 7400 5 6 分类: MCU/ 嵌入式


【原创】调试stm32TIM输入捕获模式

应用平台为英贝特EMSTM32V1开发板
下载例程:https://static.assets-stash.eet-china.com/album/old-resources/2008/10/13/7a65b455-187b-4847-87a7-767f4a60a546.rar



这个程序的要完成的任务是:通过定时器的输入捕获模式,测量4路信号的频率(频率的范围200—1000HZ),并且通过相应的DMA通道将测量的值传送到存储器部分一个数据缓冲区。



由于STM32的定时器一般都有4个独立的通道,可以考虑就用一个定时器的4个通道测量信号的频率,参见下图

点击看大图


























我们不难发现只有TIM1TIM2为其4个通道配备了DMA通道,因此只能选择TIM1TIM2来应用。这里我实验选择了TIM2,但是ch2ch4共用了一个DMA通道,所以我又开启了TIM4,利用了TIM4_CH2.



测量信号的4TIM通道为:



TIM2_CH1  
(PA0)    DMA_CH5



TIM2_CH2  
(PA1)    DMA_CH7



TIM2_CH3  
(PA2)    DMA_CH1



TIM4_CH2  
(PB7)    DMA_CH4



以下为各个部分的配置步骤,全部以TIM2_CH1的配置作示例:



 



1Stm32TIM的输入模式的配置:



TIM_ICInitStructure.TIM_ICMode =
TIM_ICMode_ICAP;                 //
配置为输入捕获模式         



TIM_ICInitStructure.TIM_Channel =
TIM_Channel_1;                              //
选择通道2



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_ICInit(TIM2, &TIM_ICInitStructure);



注意点:《一》:TIM_ICMode只有两种模式供选择1. TIM_ICMode_ICAP 输入捕获模式



2. TIM_ICMode_PWMI   PWM输入模式。此模式是输入捕获模式的一种特殊应用,可以方便的计算出占空比,笔者只在IC1IC2上试验成功,在IC3IC4上没有测试



《二》:TIM_ICSelection  是为设置通道的方向以及ICx的映射,可以参考CCMRx这个寄存器的低两位以及8.9两位



2



  /*
Select the TIM2 Input Trigger: TI2FP2
【输入触发源选择】*/



 
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);                      //
参考TIM结构图选择滤波后的TI2输入     寄存器SMCR



 



  /*
Select the slave Mode: Reset Mode */



 
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);              //
复位模式-选中的触发输入(TRGI)的上升沿初始化计数器,并且产生一个更新线号



 



  /*
Enable the Master/Slave Mode */



 
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);       //
主从模式选择



TIM2作为例子,要想把TIM2的一个channel配置为输入模式这三个函数是必要的



3:预分频的设置



由于stm32的输入捕获模式下,在没有分频的情况下可以捕获的信号的频率最小为72MHZ/65536约为1100HZ;所以为了满足测量200-1000HZ的要求,需要配置预分频系数:



TIM2->PSC
= 10;
在实际应用中为了满足要求,并且提高精度可以选取6分频。



 



 



4DMA通道的初始化设置



这里只拿channel5作为示例



  /* DMA channel5 configuration
----------------------------------------------*/



  DMA_DeInit(DMA_Channel5);



  DMA_InitStructure.DMA_PeripheralBaseAddr =
TIM2_CRR1_Address ;



  DMA_InitStructure.DMA_MemoryBaseAddr =
(u32)&TIM2_Capture_value;



  DMA_InitStructure.DMA_DIR =
DMA_DIR_PeripheralSRC;                          
//
设置外设为源地址



  DMA_InitStructure.DMA_BufferSize = 16;



  DMA_InitStructure.DMA_PeripheralInc =
DMA_PeripheralInc_Disable;             //
外设地址不要递增



  DMA_InitStructure.DMA_MemoryInc =
DMA_MemoryInc_Enable;



  DMA_InitStructure.DMA_PeripheralDataSize =
DMA_PeripheralDataSize_HalfWord;



  DMA_InitStructure.DMA_MemoryDataSize =
DMA_MemoryDataSize_HalfWord;



  DMA_InitStructure.DMA_Mode =
DMA_Mode_Circular;



  DMA_InitStructure.DMA_Priority =
DMA_Priority_High;



  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                                                        //不是存储器到存储器



  DMA_Init(DMA_Channel5,
&DMA_InitStructure);



这里要注意的是:



1.DMA_InitStructure.DMA_PeripheralBaseAddr
= TIM2_CRR1_Address ;



前面有定义 #define TIM2_CRR1_Address ((u32)0x40000034)



在调试的时候,TIM2的三个通道全部调试通过,但是只有TIM_CH2收不到信号,这里就是地址没有搞对,因为TIM4的地址要在TIM2的基址上加0x0800;所以折腾了大半天也没有收到信号,这里要注意一下



2.DMA_InitStructure.DMA_Mode
= DMA_Mode_Circular;



这里我们的数据是连续不断的采集的所以需要一个循环缓冲区,只好设置为DMA_Mode_Circular;



 



5:关于中断与DMA



在调试程序的过程中,我遇到这样的情况:



设置了TIM2的中断使能信号



      /* Enable the CC1 Interrupt Request */



  TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);



 



  /* Enable the CC2 Interrupt Request */



  TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);



同时我需要通过DMA_Channel_7讲采集信号的频率发送到存储器区域,于是有以下设置:



  /*配置TIM2ch1MDA 并开启DMAch7*/



 
TIM_DMAConfig(TIM2,TIM_DMABase_CCR1,TIM1_DMABurstLength_2Bytes);



 



  TIM_DMACmd(TIM2, TIM_DMA_CC1, ENABLE);



这样中断与DMA通道的设置就同时被初始化,结果程序运行的时候,当发生TIM_IT_CC2中断请求的时候,程序并不能进入中断服务程序,只响应了相应的DMA请求,当我去掉以上DMA的设置程序的时候,程序很顺利就响应了中断请求进入了中断服务程序。



所以得到了以下结论:



中断与DMA的使能不必同时开启,及时都开启了,程序在接收到相应的请求信号时候,只会去响应dma请求。



6GPIO的配置



  /*
GPIOA Configuration
【设置TIM2 ch1ch2ch3*/



 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;



 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;          
//
浮点输入



 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;



 



 
GPIO_Init(GPIOA, &GPIO_InitStructure);



7:注意打开相应外设的时钟



RCC_APB1PeriphClock: TIM2TIM4



RCC_APB2PeriphClock: GPIOx



RCC_AHBPeriphClock: 
DMA



8:关于调试过程中的MDK的使用















A:打开箭头指向的两项

d08d848a-b521-4398-aa91-a71a72447c6d.jpg



B:在Address里面分别输入



0x400000380x4000003c0x40000040以及0x40000838



就可以看到TIM2_CRR1,TIM2_CRR2,TIM2_CRR3以及TIM4_CRR2中的值也就是各个通道捕捉的值value



因为捕获的数十经过PSC10分频的所以用72MHZ/10*value就可以得到测量信号的频率

0f88ff1a-d3e1-4528-b758-18e22b55431a.jpg







C:我们可以在这个框里点F2输入我们定义的缓冲区的名字



TIM2_Capture_value



TIM2_Capture_value1



TIM2_Capture_value2



TIM4_Capture_value



就可以看到DMA的各个通道传输到存储器区的数据,这个数据是跟步骤B里面的数据是一致的。缓冲区的大小为16,信号的频率在一段时间内是不变的那么这16个数就是一样的



同样用72MHZ/10*value就可以得到测量信号的频率

e3e4becc-17fa-4826-850d-feac2f557372.jpg







 



2008.10.13  1505



文章评论1条评论)

登录后参与讨论

用户377235 2013-9-14 21:12

把程序发给我一份 不胜感激 617502523
相关推荐阅读
用户165162 2010-10-15 23:43
CANopen简介
CANopen简介    CANopen协议集定义了基于CAN的分布式工业自动化系统的应用标准以及CAN应用层通信标准。CANopen是CAN-in-Automation(CiA)定义的标准之一,并且...
用户165162 2009-03-04 22:34
TServerSocket和TClientSocket地运用(转载)
在网络编程中,WinSocket API编程是最基本,也是最麻烦的地方(说句不怕影响形象的话,我对此就是一知半解)。但是,如果你是使用C++Builder作为编程平台,你就偷着乐吧,有了BCB,菜鸟变...
用户165162 2008-11-09 11:40
奥巴马就职演讲
Hello, Chicago!   芝加哥,你好!If there is anyone out there who still doubts that America is a place where...
用户165162 2008-11-02 12:43
STM32 RTC 对晶振的要求实在不地道
zhwxc 发表于 2008-8-19 18:00 ST MCU ←返回版面 楼主: STM32 RTC 对晶振的要求实在不地道今天到电子市场找了一下,几乎都是12.5p负载电容的32768晶...
用户165162 2008-11-01 14:50
模糊K均值算法的C++实现
//****************************************************************************////文件名:kaverage.cpp  ...
用户165162 2008-10-20 17:50
10种软件滤波方法的示例程序[转帖]
1、限副滤波 /* A值可根据实际情况调整 value为有效值,new_value为当前采样值 滤波程序返回有效的实际值 */ #define A 10 char value; char filter...
我要评论
1
5
关闭 站长推荐上一条 /2 下一条