1输入捕获作为定时器的一个功能.docx
《1输入捕获作为定时器的一个功能.docx》由会员分享,可在线阅读,更多相关《1输入捕获作为定时器的一个功能.docx(16页珍藏版)》请在冰点文库上搜索。
1输入捕获作为定时器的一个功能
输入捕获作为定时器的一个功能,在工业测速上有很大的应用。
STM32的一些定时器具有四个外部通道,可利用一个定时器采集外部四路脉冲频率,节约硬件资源和软件代码
如需要测量一个或多个外部方波脉冲频率,频率低于单片机运行频率,可如下操作:
(以TIM4为例)
初始化:
(省略GPIO配置,将TIM4的四个通道引脚配置为上拉或浮空输入,省略定时器RCC配置,省略中断NVIC配置)
1.
2.voidTIM_Configuration(void)
3.{
4.
5.TIM_ICInitTypeDef
6.TIM_ICInitStructure;
7.TIM_TimeBaseInitTypeDef
8.TIM_TimeBaseStructure;//TIM4时基
9.
10.TIM_DeInit(TIM4);
11. TIM_TimeBaseStructure.TIM_Period=
12.0xffff;
13.//自动重装值
14. TIM_TimeBaseStructure.TIM_Prescaler=
15.719;
16.//预分频值,使TIMx_CLK=100K =10us
17.
18.TIM_TimeBaseStructure.TIM_ClockDivision=
19.TIM_CKD_DIV1;
20.//输入时钟不分频
21. TIM_TimeBaseStructure.TIM_CounterMode=
22.TIM_CounterMode_Up;
23.//向上计数
24. TIM_TimeBaseInit(TIM4,
25.&TIM_TimeBaseStructure);
26.
27.//TIM4_TimeBase
28.// TIM_ICInitStructure.TIM_ICMode=
29.TIM_ICMode_ICAP;
30.//输入捕捉方式
31. TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;//|
32.TIM_Channel_2; //输入通道
33.
34.TIM_ICInitStructure.TIM_ICPolarity=
35.TIM_ICPolarity_Rising; //捕捉上升沿
36.
37.TIM_ICInitStructure.TIM_ICSelection=
38.TIM_ICSelection_DirectTI; //捕捉中断
39.
40.TIM_ICInitStructure.TIM_ICPrescaler=
41.TIM_ICPSC_DIV1; //捕捉不分频
42.
43.TIM_ICInitStructure.TIM_ICFilter=
44.0x0; //捕捉输入不滤波
45. TIM_ICInit(TIM4,&TIM_ICInitStructure);
46. TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;//|
47.TIM_Channel_2; //输入通道
48.
49.TIM_ICInitStructure.TIM_ICPolarity=
50.TIM_ICPolarity_Rising; //捕捉上升沿
51.
52.TIM_ICInitStructure.TIM_ICSelection=
53.TIM_ICSelection_DirectTI; //捕捉中断
54.
55.TIM_ICInitStructure.TIM_ICPrescaler=
56.TIM_ICPSC_DIV1; //捕捉不分频
57.
58.TIM_ICInitStructure.TIM_ICFilter=
59.0x0; //捕捉输入不滤波
60. TIM_ICInit(TIM4,&TIM_ICInitStructure);
61. TIM_ICInitStructure.TIM_Channel=TIM_Channel_3;//|
62.TIM_Channel_2; //输入通道
63.
64.TIM_ICInitStructure.TIM_ICPolarity=
65.TIM_ICPolarity_Rising; //捕捉上升沿
66.
67.TIM_ICInitStructure.TIM_ICSelection=
68.TIM_ICSelection_DirectTI; //捕捉中断
69.
70.TIM_ICInitStructure.TIM_ICPrescaler=
71.TIM_ICPSC_DIV1; //捕捉不分频
72.
73.TIM_ICInitStructure.TIM_ICFilter=
74.0x0; //捕捉输入不滤波
75. TIM_ICInit(TIM4,&TIM_ICInitStructure);
76. TIM_ICInitStructure.TIM_Channel=TIM_Channel_4;//|
77.TIM_Channel_2; //输入通道
78.
79.TIM_ICInitStructure.TIM_ICPolarity=
80.TIM_ICPolarity_Rising; //捕捉上升沿
81.
82.TIM_ICInitStructure.TIM_ICSelection=
83.TIM_ICSelection_DirectTI; //捕捉中断
84.
85.TIM_ICInitStructure.TIM_ICPrescaler=
86.TIM_ICPSC_DIV1; //捕捉不分频
87.
88.TIM_ICInitStructure.TIM_ICFilter=
89.0x0; //捕捉输入不滤波
90. TIM_ICInit(TIM4,&TIM_ICInitStructure);
91. /*TIMenablecounter*/
92. TIM_Cmd(TIM4,ENABLE);
93. /*EnabletheCC2InterruptRequest*/
94. TIM_ITConfig(TIM4,
95.TIM_IT_CC1,ENABLE);
96. TIM_ITConfig(TIM4,TIM_IT_CC2,ENABLE);
97.
98.TIM_ITConfig(TIM4,TIM_IT_CC3,ENABLE);
99. TIM_ITConfig(TIM4,TIM_IT_CC4,
100.ENABLE);
101.}
复制代码
其中:
TIM_TimeBaseStructure.TIM_Period=0xffff;为自动重装值,与普通单片机一样
TIM_TimeBaseStructure.TIM_Prescaler=719;预分频值,使TIMx_CLK=100KHz,系统时钟运行于72M时720分频,定时器运行于100KHZ,即10us每分度捕获一次
TIM_ICInitStructure.TIM_ICMode=TIM_ICMode_ICAP;此句选择定时器为输入捕获模式,但在我的库函数下未定义,所以注释掉,未影响程序执行
TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;配置通道1
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;上升沿捕获
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;捕获中断
TIM_ICInitStructure.TIM_ICFilter=0x0;不滤波
TIM_ICInit(TIM4,&TIM_ICInitStructure);将配置应用
以上每个通道都需要将整个配置再写一遍,使用与'|'是无效的。
TIM_Cmd(TIM4,ENABLE);使能定时器4
TIM_ITConfig(TIM4,TIM_IT_CC1,ENABLE);
TIM_ITConfig(TIM4,TIM_IT_CC2,ENABLE);
TIM_ITConfig(TIM4,TIM_IT_CC3,ENABLE);
TIM_ITConfig(TIM4,TIM_IT_CC4,ENABLE);打开四个通道的捕获中断
以上将TIM配置完成,下面是中断内代码:
1.
2.void
3.TIM4_IRQHandler(void)
4.{
5.
6.//频率缓冲区计数
7.staticu16this_time_CH1=0;
8.staticu16
9.last_time_CH1=0;
10.staticu8capture_number_CH1=0;
11.vu16
12.tmp16_CH1;
13.staticu16this_time_CH2=0;
14.staticu16last_time_CH2=0;
15.
16.staticu8capture_number_CH2=0;
17.vu16tmp16_CH2;
18.staticu16this_time_CH3=0;
19.staticu16last_time_CH3=0;
20.
21.staticu8capture_number_CH3=0;
22.vu16tmp16_CH3;
23.staticu16this_time_CH4=0;
24.staticu16last_time_CH4=0;
25.
26.staticu8capture_number_CH4=0;
27.vu16tmp16_CH4;
28.
29. if(TIM_GetITStatus(TIM4,TIM_IT_CC1)==SET)
30.
31. {
32.
33.TIM_ClearITPendingBit(TIM4,TIM_IT_CC1);
34. if(capture_number_CH1==0)
35.
36. {
37.
38.
39.capture_number_CH1=1;
40.
41.
42.last_time_CH1=TIM_GetCapture1(TIM4);
43.
44. }
45.
46. elseif(capture_number_CH1==1)
47.
48. {
49.
50.
51.capture_number_CH1=0;
52.
53.
54.this_time_CH1=TIM_GetCapture1(TIM4);
55.
56.if(this_time_CH1>last_time_CH1)
57.
58. {
59.
60.
61.tmp16_CH1=(this_time_CH1-last_time_CH1);
62.
63. }
64.
65. else
66.
67. {
68.
69.
70.tmp16_CH1=((0xFFFF-last_time_CH1)+this_time_CH1);
71.
72. }
73. //TIM2
74.counterclock=1MHz
75.
76.//
77.FreqBuf[cnt]=(1000000L*100)/
78.tmp16;
79.//*100为扩大显示量程
80. Freq_Value[0]=tmp16_CH1;
81.
82. }
83. }
84. if(TIM_GetITStatus(TIM4,TIM_IT_CC2)==SET)
85.
86. {
87.
88.TIM_ClearITPendingBit(TIM4,TIM_IT_CC2);
89. if(capture_number_CH2==0)
90.
91. {
92.
93.
94.capture_number_CH2=1;
95.
96.
97.last_time_CH2=TIM_GetCapture2(TIM4);
98.
99. }
100.
101. elseif(capture_number_CH2==1)
102.
103. {
104.
105.
106.capture_number_CH2=0;
107.
108.
109.this_time_CH2=TIM_GetCapture2(TIM4);
110.
111.if(this_time_CH2>last_time_CH2)
112.
113. {
114.
115.
116.tmp16_CH2=(this_time_CH2-last_time_CH2);
117.
118. }
119.
120. else
121.
122. {
123.
124.
125.tmp16_CH2=((0xFFFF-last_time_CH2)+this_time_CH2);
126.
127. }
128. //TIM2
129.counterclock=1MHz
130.
131.//
132.FreqBuf[cnt]=(1000000L*100)/
133.tmp16;
134.//*100为扩大显示量程
135. Freq_Value[1]=tmp16_CH2;
136.
137.
138.}
139.}
140.
141.if(TIM_GetITStatus(TIM4,TIM_IT_CC3)==SET)
142.
143. {
144.
145.TIM_ClearITPendingBit(TIM4,TIM_IT_CC3);
146. if(capture_number_CH3==0)
147.
148. {
149.
150.
151.capture_number_CH3=1;
152.
153.
154.last_time_CH3=TIM_GetCapture3(TIM4);
155.
156. }
157.
158. elseif(capture_number_CH3==1)
159.
160. {
161.
162.
163.capture_number_CH3=0;
164.
165.
166.this_time_CH3=TIM_GetCapture3(TIM4);
167.
168.if(this_time_CH3>last_time_CH3)
169.
170. {
171.
172.
173.tmp16_CH3=(this_time_CH3-last_time_CH3);
174.
175. }
176.
177. else
178.
179. {
180.
181.
182.tmp16_CH3=((0xFFFF-last_time_CH3)+this_time_CH3);
183.
184. }
185. //TIM2
186.counterclock=1MHz
187.
188.//
189.FreqBuf[cnt]=(1000000L*100)/
190.tmp16;
191.//*100为扩大显示量程
192. Freq_Value[2]=tmp16_CH3;
193.
194. }
195.}
196.
197.
198.if(TIM_GetITStatus(TIM4,TIM_IT_CC4)==SET)
199.
200. {
201.
202.TIM_ClearITPendingBit(TIM4,TIM_IT_CC4);
203. if(capture_number_CH4==0)
204.
205. {
206.
207.
208.capture_number_CH4=1;
209.
210.
211.last_time_CH4=TIM_GetCapture4(TIM4);
212.
213. }
214.
215. elseif(capture_number_CH4==1)
216.
217. {
218.
219.
220.capture_number_CH4=0;
221.
222.
223.this_time_CH4=TIM_GetCapture4(TIM4);
224.
225.if(this_time_CH4>last_time_CH4)
226.
227. {
228.
229.
230.tmp16_CH4=(this_time_CH4-last_time_CH4);
231.
232. }
233.
234. else
235.
236. {
237.
238.
239.tmp16_CH4=((0xFFFF-last_time_CH4)+this_time_CH4);
240.
241. }
242. //TIM2
243.counterclock=1MHz
244.
245.//
246.FreqBuf[cnt]=(1000000L*100)/
247.tmp16;
248.//*100为扩大显示量程
249. Freq_Value[3]=tmp16_CH4;
250.
251. }
252.}
253.//
254.GPIO_WriteBit(GPIOC,GPIO_Pin_13,
255.(BitAction)((1-GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_13))));
256.}
复制代码
中断内四部分代码完全一样,只分析其中一段
输入捕获的原理是,定时器正常计数运行,当外部脉冲到来时,将定时器计数值存起来,当下次脉冲到来时,求出这两次计数值差值,即为这两段脉冲的周期。
例如,定时器计数到10,外部脉冲到来,使用last_time_CH1存储10,下次脉冲到来,此时定时器计数值运行到110,使用this_time_CH1存储110,之后做差,tmp16_CH1存储差值100,由于定时器运行于100KHZ,10us计数值增加一次,所以脉冲周期为100*10=1000us=1ms,即为1KHZ。
当然,定时器会溢出重装,此时需要将差值补偿运算,tmp16_CH1=