forked from xiahouzuoxin/notes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSTM32用作编码器接口的原理.html
186 lines (179 loc) · 10.9 KB
/
STM32用作编码器接口的原理.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title></title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; }
code > span.dt { color: #902000; }
code > span.dv { color: #40a070; }
code > span.bn { color: #40a070; }
code > span.fl { color: #40a070; }
code > span.ch { color: #4070a0; }
code > span.st { color: #4070a0; }
code > span.co { color: #60a0b0; font-style: italic; }
code > span.ot { color: #007020; }
code > span.al { color: #ff0000; font-weight: bold; }
code > span.fu { color: #06287e; }
code > span.er { color: #ff0000; font-weight: bold; }
</style>
<link rel="stylesheet" href="../stylesheets/Github.css" type="text/css" />
<title>STM32用作编码器接口的原理</title>
</head>
<body>
<div id="header"><center>
<p class="header_titleline">
<a href="../index.html" target="_self" title="主页">主页 </a><a href="../Search.html" target="_self" title="站内搜索">站内搜索 </a><a href="../Projects.html" target="_self" title="项目研究">项目研究 </a><a href="../Archives.html" target="_self" title="文章存档">文章存档 </a><a href="../README.html" target="_self" title="分类目录">分类目录 </a><a href="../AboutMe.html" target="_self" title="关于我">关于我 </a>
</p>
</center></div>
<h1>STM32用作编码器接口的原理</h1>
<h4>2011-10-25,整理于2014-09-25 / xiahouzuoxin</h4>
<h4>Tags: ARM</h4>
转载请注明出处: <a href="http://xiahouzuoxin.github.io/notes/">http://xiahouzuoxin.github.io/notes/</a>
<div id="TOC">
<ul>
<li><a href="#关于定时器实现编码器计数的两点说明">关于定时器实现编码器计数的两点说明</a></li>
<li><a href="#实例代码调试通过">实例代码(调试通过)</a></li>
</ul>
</div>
<!---title:STM32用作编码器接口的原理-->
<!---keywords:ARM-->
<!---date:2011-10-25,整理于2014-09-25-->
<p>这是一篇旧文,早在上大二的时候,在地下室(当时实验室在防空地下室)顺手在word上写的,当时STM32正刚刚开始蓬勃发展,如今时隔3年,整理到这里!</p>
<h2 id="关于定时器实现编码器计数的两点说明">关于定时器实现编码器计数的两点说明</h2>
<ol style="list-style-type: decimal">
<li><p>外部编码器为定时器提供带有方向的时钟,如下图1右上角。通用定时器总共四种时钟提供方式,现在使用的即是TI1F和TI2F的组合时钟方式。</p>
<div class="figure">
<img src="../images/STM32用作编码器接口的原理/img1.png" alt="img1" /><p class="caption">img1</p>
</div></li>
<li><p>TI1、TI2作为编码器输入口,通过配置在TI1和TI2边沿的计数位置实现所谓的倍频特性,通过向上向下计数实现鉴相,若向上计数往前走,则向下计数则是往后退的过程。由图2和图3知,控制计数点的不同,只能0/2/4倍频。</p>
<p><img src="../images/STM32用作编码器接口的原理/img2.png" alt="img2" /> <img src="../images/STM32用作编码器接口的原理/img3.png" alt="img3" /></p></li>
</ol>
<h2 id="实例代码调试通过">实例代码(调试通过)</h2>
<pre class="sourceCode c"><code class="sourceCode c"><span class="co">/******************************************************************************</span>
<span class="co"> 使用到变量定义</span>
<span class="co">******************************************************************************/</span>
<span class="ot">#define PULSE_PER_CIRCLE 600 </span><span class="co">//编码器分辨率,即转一圈脉冲数</span>
<span class="ot">#define MAX_COUNT 800 </span><span class="co">//最大计数值,解决计数问题时要用</span>
<span class="ot">#define ENCODER_TIM_PERIOD (PULSE_PER_CIRCLE * 4 - 1) </span><span class="co">//定时器周期</span>
SINT32 encoder_last = <span class="dv">0</span>; <span class="co">//记录上一次采集编码器数值</span>
SINT32 encoder_cnt = <span class="dv">0</span>; <span class="co">//编码器采集值</span>
<span class="co">/******************************************************************************</span>
<span class="co"> TIM3定时器配置为编码器模式</span>
<span class="co">******************************************************************************/</span>
<span class="dt">void</span> EncodeInit(<span class="dt">void</span>)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM3_TimeBaseStructure;
TIM_ICInitTypeDef TIM3_ICInitStructure;
<span class="co">/*TIM2 Clock enable*/</span>
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
<span class="co">/*Configure PA6,7*/</span>
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
<span class="co">/*COnfigure TIM3*/</span>
TIM3_TimeBaseStructure.TIM_Prescaler = <span class="dv">0</span>; <span class="co">//TIM clock = 72MHz </span>
TIM3_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM3_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD;
TIM3_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM3_TimeBaseStructure.TIM_RepetitionCounter = <span class="dv">0</span>;
TIM_TimeBaseInit(TIM3, &TIM3_TimeBaseStructure);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising,
TIM_ICPolarity_Rising); <span class="co">//配置编码器模式,4倍频</span>
TIM_ICStructInit(&TIM3_ICInitStructure);
TIM3_ICInitStructure.TIM_ICFilter = <span class="dv">6</span>;
TIM_ICInit(TIM3, &TIM3_ICInitStructure);
<span class="co">/*Reset counter*/</span>
TIM3->CNT = <span class="dv">0</span>;
TIM_Cmd(TIM3, ENABLE);
}</code></pre>
<p>到此,编码器初始化就已经配置好了,按理应该接上就能用了。但是,STM32定时器是16位,假如计数值超过65535,数据会丢失。因此,参考了<http://www.21ic.com>上相关资料。定义32位全局变量存储脉冲数,通过下面的程序技巧实现计数,下面程序是关键。</p>
<pre><code>/*****************************************************************************/
Function Name: ENC_Get_Electrical_Angle
Author : 夏侯佐鑫
Date : 2011-10-22
******************************************************************************/
SINT16 ENC_Get_Electrical_Angle(void)
{
static UINT16 lastCount = 0;
UINT16 curCount = TIM3->CNT;
SINT32 dAngle = curCount - lastCount;
if(dAngle >= MAX_COUNT)
{
dAngle -= ENCODER_TIM_PERIOD;
}
else if(dAngle < -MAX_COUNT)
{
dAngle += ENCODER_TIM_PERIOD;
}
lastCount = curCount;
return (SINT16)dAngle;
}</code></pre>
<p>在SysTick中采集数值,SysTick配置为SysTick_Config(720000)即10ms。SysTick中断函数如下:</p>
<pre><code>/******************************************************************************
Function Name: SysTick_Handler
Author : 夏侯佐鑫
Date : 2011-04-22
******************************************************************************/
void SysTick_Handler(void)
{
/*Encoder*/
encoder_last = encoder_cnt;
encoder_cnt = encoder_cnt + ENC_Get_Electrical_Angle();
}</code></pre>
<p>到此,编码器记里程功能完美实现。此实现代码用于2012年全国电脑鼠走迷宫大赛的电脑鼠制作中。</p>
<div class="ds-thread" data-thread-key="STM32用作编码器接口的原理" data-title="STM32用作编码器接口的原理" data-url="xiahouzuoxin.github.io/notes/html/STM32用作编码器接口的原理.html"></div>
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"slide":{"type":"slide","bdImg":"5","bdPos":"right","bdTop":"300"},"image":{"viewList":["qzone","tsina","tqq","renren","weixin"],"viewText":"分享到:","viewSize":"16"},"selectShare":{"bdContainerClass":null,"bdSelectMiniList":["qzone","tsina","tqq","renren","weixin"]}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
<!-- 多说公共JS代码 start (一个网页只需插入一次) -->
<script type="text/javascript">
var duoshuoQuery = {short_name:"xiahouzuoxin"};
(function() {
var ds = document.createElement('script');
ds.type = 'text/javascript';ds.async = true;
ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
ds.charset = 'UTF-8';
(document.getElementsByTagName('head')[0]
|| document.getElementsByTagName('body')[0]).appendChild(ds);
})();
</script>
<!-- 多说公共JS代码 end -->
<div id="footer">
<p class="footer_subline">联系邮箱: xiahouzuoxin@163.com</p>
<p class="footer_subline">声明: 本站所有文章如非特别说明均为原创,转载请注明出处!
<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1253219218'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1253219218%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));</script>
</p>
</div>
<!-- 回到顶部 -->
<script>
lastScrollY=0;
function heartBeat(){
var diffY;
if (document.documentElement && document.documentElement.scrollTop)
diffY = document.documentElement.scrollTop;
else if (document.body)
diffY = document.body.scrollTop
else
{/*Netscape stuff*/}
percent=.1*(diffY-lastScrollY);
if(percent>0)percent=Math.ceil(percent);
else percent=Math.floor(percent);
document.getElementById("full").style.top=parseInt(document.getElementById("full").style.top)+percent+"px";
lastScrollY=lastScrollY+percent;
}
suspendcode="<div id=\"full\" style='right:1px;POSITION:absolute;TOP:600px;z-index:100'><a onclick='window.scrollTo(0,0);'><img src='../images/top.png'></a><br></div>"
document.write(suspendcode);
window.setInterval("heartBeat()",1);
</script>
</body>
</html>