音响设备的音量调节,以往通常采用电位器,通过可调电位器阻值大小,调节电流的大小,控制音量大小;

而编码器 (encoder) 是将 **信号 **或 数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。更多用于频段选择,场景识别等应用。

目前,很多高端音响功放等设备都采用了 旋转编码器 来实现音量大小的调节。

那么, 编码器如何实现音量调节?

简而言之,旋转编码器 通过与 单片机(MCU) 的配合使用,可实现音量大小的调节。

原理如图所示:

当 顺时针旋转 编码器时,编码器 A端子 的输出信号A 信号相位超前;

当 **逆时针旋转 **编码器时,编码器 B端子 的输出信号B 信号相位超前;

我们把 A/B端信号 分别接到 MCU的 两个输入端口 ,同时在MCU内 设置一个音量计数器

就可以用软件来判别编码器是 顺时针旋转 还是 逆时针旋转;

通过此方法来识别是增加还是减少音量计数器的值,

最后把这个计数值送到相应的电子音量控制芯片即可实现音量(或者其他需要增量/减量的)控制。

编码器一般音量调节操作

1.机械的编码器要24脉冲/每转,牵强能够分辩3到4种速度(每隔100ms核算一次速度),机械的缺陷是有毛刺,并且寿命短,通常在1万转左右,不过LJV旋转编码器通常为30000次。

由于旋转编码器的寿命长达几十万次之多,比普通的电位器使用寿命长很多,还不会因为机械的磨损导致阻值偏差,影响音响设备声音正常输出,调节精度取决于与MCU配合的音量控制芯片的控制级数,与旋转编码器本身无关,这也是普通一般电位器无法做到的。2.期望编码器每转的脉冲越多越好,LJV的编码器和旋转编码器脉冲都许多,并且性价比很高。

编码器音量调节图

3.需求旋转编码器的旋转速度快,调理就快相反速度慢,调理就慢。

旋转编码器检测转变方向的电路,在检测转变方向时,用数字输出检测马达轴旋转,方向的传感器,输出相位相差90℃的两相(A相和B相)数字信号,使用两相信号检测出现在方向,对每个A相和B相信号的各沿(前沿和后沿)外加时标脉冲,脉冲的前沿同步输出旋转方向检测信号。

http://www.crystalradio.cn/thread-1419316-1-1.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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438


#include <reg52.h>


sbit     BMA    = P1^4;	// 编码开关A引脚


sbit     BMB    = P1^5;	// 编码开关B引脚


sbit     BMC    = P1^6;	// 编码开关 下按引脚





unsigned char  display[3];


unsigned char  code  LEDData[ ] = { 


   0xC0,0xF9,0xA4,0xB0,0x99,0x92,


   0x82,0xF8,0x80,0x90,0xff


}; 


unsigned char  counter = 0;     //编码器脉冲计数 


unsigned char  n,shift;





/**********************************************************	  


ms延时子函数


**********************************************************/


void delayms(unsigned int ms)


{


  	unsigned char k; 


	while (ms--)


	{


	    for (k = 0; k < 114; k++) 


		;


	}


}





/**********************************************************	 


扫描编码器子函数  


在编码器 引脚A 为 低电平期间:


  编码器 引脚B 从0到1为 正转,编码器引脚 B从1到0为 反转。


**********************************************************/


void scan_encoder(void) 


{ 


   	static  bit  Curr_b;  //定义一个变量来储存 当前B 信号 


   	static  bit  Last_b;  //定义一个变量来储存 上次B脚 信号 


   	static  bit  update= 0;





   	if( BMA && BMB)           //编码器无转动退出


   	{


     	update = 0; 


     	return;


   	}





   	Last_b = BMB;       	//记录B信号





   	while(!BMA)         	//等待 A由低变高


   	{ 


     	Curr_b = BMB;     	//记录等待期间的B信号(指当前B信号)


     	update = 1;


   


   	 	if(!BMC)           //当按下旋钮时


     	{


       		counter = 0;   //计数单元清零(归位)


       		delayms(10);


     	}   


   	} 





   	if(update)


   	{


   		update = 0 ;


	    if( (Last_b == 0)&&(Curr_b== 1) ) 		//B从0到1为正转


	    { 


	   		if(counter == 255)


	   		{


	   			return;


			}	   


	       counter++;          //正转计数加


	    } 


	    else if((Last_b == 1)&&(Curr_b == 0)) //B从1到0为反转


	    { 


		    if(counter == 0)


		    {


		       	return;


			}   


		    counter--;         //反转计数减


	    } 


   	}


}





/**********************************************************	 


主函数		 


**********************************************************/


void  main(void)


{


   P0 = 0xff;


   P1 = 0xff;


   P2 = 0xff;





   T2CON = 0x00;               	// 设置T2CON寄存器   


   TH2 = 0xfc;                 	// 1ms定时


   TL2 = 0x66;


   ET2 = 1;                    	// 启用Timer2中断


   EA = 1;                     	// 总中断允许


   TR2 = 1;                    	// 启动 定时器2


   counter = 0;                	// 计数单元清零





   while(1)


   { 


   	  scan_encoder();


      if(!BMC)                	//当按下旋钮时


      {


        counter = 0;            	//计数单元清零(归位)


        delayms(10);


      } 


    }


}





/*********************************************************	 


Timer2中断函数	   


**********************************************************/


void  timer2() interrupt 5 


{ 


	TR2 = 0;


   	TF2 = 0;                         //手工清中断标志  


   	TH2 = 0xfc;                      //1ms定时常数


   	TL2 = 0x66;





   	if(n >= 3)                       //3位数码管显示


   	{


     	n = 0;


     	shift = 0x7f;                  //送位码初值


     	P2 = 0xff;                     //关闭显示


   	}


   	else


   	{


     	display[0] = counter%10;       //个位数据


     	display[1] = (counter%100)/10; //十位数据


     	display[2] = counter/100;      //百位数据


   


     	if(display[2] == 0)


     	{


       		display[2] = 0x0a;           //百位为0,不显示


       		if(display[1] == 0)


       		{


       			display[1]  =0x0a;           //十位为0,不显示   


			}   


		}





     	P0 = LEDData[display[n++]];    //送段码


     	P2 = shift;                    //送位码


     	shift = (shift>>1)|0x80;       //调整位码


   	}


   	TR2 = 1;


}





/*********************************************************/