这个程序的要完成的任务是:通过定时器的输入捕获模式,测量4路信号的频率(频率的范围200—1000HZ),并且通过相应的DMA通道将测量的值传送到存储器部分一个数据缓冲区。
由于STM32的定时器一般都有4个独立的通道,可以考虑就用一个定时器的4个通道测量信号的频率,参见下图
我们不难发现只有TIM1,TIM2为其4个通道配备了DMA通道,因此只能选择TIM1,TIM2来应用。这里我实验选择了TIM2,但是ch2与ch4共用了一个DMA通道,所以我又开启了TIM4,利用了TIM4_CH2.
测量信号的4个TIM通道为:
TIM2_CH1
(PA0) DMA_CH5
TIM2_CH2
(PA1) DMA_CH7
TIM2_CH3
(PA2) DMA_CH1
TIM4_CH2
(PB7) DMA_CH4
以下为各个部分的配置步骤,全部以TIM2_CH1的配置作示例:
1:Stm32的TIM的输入模式的配置:
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输入模式。此模式是输入捕获模式的一种特殊应用,可以方便的计算出占空比,笔者只在IC1,IC2上试验成功,在IC3,IC4上没有测试
《二》: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分频。
4:DMA通道的初始化设置
这里只拿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讲采集信号的频率发送到存储器区域,于是有以下设置:
/*配置TIM2—ch1的MDA 并开启DMA【ch7】*/
TIM_DMAConfig(TIM2,TIM_DMABase_CCR1,TIM1_DMABurstLength_2Bytes);
TIM_DMACmd(TIM2, TIM_DMA_CC1, ENABLE);
这样中断与DMA通道的设置就同时被初始化,结果程序运行的时候,当发生TIM_IT_CC2中断请求的时候,程序并不能进入中断服务程序,只响应了相应的DMA请求,当我去掉以上DMA的设置程序的时候,程序很顺利就响应了中断请求进入了中断服务程序。
所以得到了以下结论:
中断与DMA的使能不必同时开启,及时都开启了,程序在接收到相应的请求信号时候,只会去响应dma请求。
6:GPIO的配置
/*
GPIOA Configuration 【设置TIM2的 ch1,ch2,ch3】*/
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: TIM2,TIM4
RCC_APB2PeriphClock: GPIOx
RCC_AHBPeriphClock:
DMA
8:关于调试过程中的MDK的使用
A:打开箭头指向的两项
B:在Address里面分别输入
0x40000038,0x4000003c,0x40000040以及0x40000838
就可以看到TIM2_CRR1,TIM2_CRR2,TIM2_CRR3以及TIM4_CRR2中的值也就是各个通道捕捉的值value
因为捕获的数十经过PSC10分频的所以用72MHZ/10*value就可以得到测量信号的频率
C:我们可以在这个框里点F2输入我们定义的缓冲区的名字
TIM2_Capture_value
TIM2_Capture_value1
TIM2_Capture_value2
TIM4_Capture_value
就可以看到DMA的各个通道传输到存储器区的数据,这个数据是跟步骤B里面的数据是一致的。缓冲区的大小为16,信号的频率在一段时间内是不变的那么这16个数就是一样的
同样用72MHZ/10*value就可以得到测量信号的频率
2008.10.13 15:05
用户377235 2013-9-14 21:12