Download this article in PDF format.
When you need to convert a measurement signal from the digital to the analog domain, this design is a suitable solution with only two chips. Frequency-to-voltage conversion has many applications in instrumentation circuits.
This design(Fig. 1)基于14针PIC MicroController 16F753,该器具有嵌入式16位计数器和9位数字到Analog转换器(DAC)。该设计的输入频率范围在0到50 kHz之内,其输出电压在0到4.99 V范围内,分辨率为10 mV。
To achieve the conversion, the input frequency is separated into four scales, which are manually selected by the inputs SEL1 and SEL2(Fig. 2).
当DAC输入代码为1FFH(511D)时,DAC的最大值为4.99 V,对于000H输入值,DAC的最大值为0.000V。对于第一刻度,我们获得以下转换方程中替换的最大和最小值:
代替这些值,我们得到了两个方程:
求解我们得到的两个方程式:
And solving for M, we get:
在等式1中替换两个值,我们获得了偏移值,结果是公式3:
现在,方程3可以在PIC基本代码中实现。但是首先,我们需要使用Timer1以1.00秒的间隔测量输入频率:如下:
TMR1L = 0;Clearing TIMER1 registers TMR1H = 0; T1CON.0 = 1; TIMER 1 Enabled PAUSE 1000; for 1.00 Seconds T1CON.0 = 0; TIMER 1 Disabled COUNTER.BYTE0 = TMR1L; Storing both register in two bytes COUNTER.BYTE1 = TMR1H;
Now we can apply Equation 3 as follows:
DIV = COUNTER *1000 DAC = DIV32 9784 DAC = DAC + offset; freq offset = 0;If we get 2,500 pulses in TIMER1, for example, we can get the DAC’s value by dividing the pulses read by the constant 9.784 that we found previously:
然后,将其转换为软件代码,我们得到:
现在我们可以确定多少脉冲等效于每位测量(Fig. 3).
For each scale, it’s necessary to obtain the constants by doing the same method used for Equations 1, 2, and 3. Thus, for the second scale (5-10 kHz),we get Equation 4:
Then we determine how many pulses are equivalent to each bit(Fig. 4).
For the third scale (10-15 kHz), we getEquation 5:
Then, we determine how many pulses are equivalent to each bit(Fig. 5).
For the fourth scale (10-50 kHz), we get Equation 6:
Then, finally, we determine how many pulses are equivalent to each bit inFigure 6.
图7和8show two cases in the scope for different input frequencies with their respective voltage output. The code listing below shows the software code implemented in the PIC16F753.
Ricardo Jimenezholds a Master’s degree in electronics. He is the author of the book “The PIC Microcontroller Notebook, Vol 3,” ISBN: 978-1-7325906-1-8.
Gabriel Lee Álvarez isan Electronics Engineering student at ITM.
Software Code for the Frequency-to-Voltage Converter Based on the PIC16F753
'*名称:freq-to-wttage.bas'*作者:里卡多·希门尼斯(Ricardo Jimenez)和加布里埃尔·李·阿尔瓦雷斯(Gabriel Lee Alvarez)'*版本:1;PIC16F753;电压转换器的频率;0Hz -5kHz = 0v -5 V;第一比例; 5kHz -10kHz = 0-5V;第二个比例; 10kHz -15kHz = 0-5V;第三刻度; 10kHz -50kHz = 0-5V;第四刻度; pic16f753;振荡器和端口配置OSCCON = $ 26;= $ 26; Clock set to 4 MHz OSCTUNE = 0; TRISA = %111110; RA0 IS A OUTPUT, RA1:RA5 AS INPUTS ANSELA = %000010; RA0:RA5 DIGIITALS TRISC = %0000000; RC0:RC2 AS INPUTS, RC3:RC5 AS OUTPUTS ANSELC = %000000; RC0:RC5 AS DIGITALS WPUA = %011100; RA2,RA3 PULL IS ENABLE WPUC = %000000 DEFINE LCD_DREG PORTC ' PORTC is LCD data port DEFINE LCD_DBIT 0 ' PORTC.0 is the data LSB DEFINE LCD_RSREG PORTC ' RS is connected to PORTC.4 DEFINE LCD_RSBIT 4 DEFINE LCD_EREG PORTC ' E is connected to PORTC.5 DEFINE LCD_EBIT 5 DEFINE LCD_BITS 4 ' 4 data line are used DEFINE LCD_LINES 2 ' It is a 2-line display DEFINE LCD_COMMANDUS 1500 ' Use 1500uS command delay DEFINE LCD_DATAUS 44 ' Use 44uS data delay ;---------SETTING UP LCD-------------------------------------------------------- LCDOUT $FE,$28; $28 FUNCTION SET, 4 BITS LCDOUT $FE,$10; $10 SHIFT DISPLAY LCDOUT $FE,$0C; $0C DISPLAY ON LCDOUT $FE,$06; $06 ENTRY MODE SET ;------------TIMER CONFIG ---------- T1CON = %10000100; $84 TIMER 1 DISABLE ;---HPWM SET to 250 Hz, when needed remove semicolons --- ;CCP1CON = %00001100; PWM mode selection and CCPx enabled ;PR2 = 79; Value obtained from equation ;T2CON = %00000100; enabling timer 2, PRESCALER 16 ;CCP1CON.5 =0 ;CCP1CON.4 =0 ;CCPR1L = %000101000; ;ADC ENABLED ADCON0 = %10000111; ENABLE ADC ADCON1 = %00000000;FOSC/2 ;-------- DAC CONFIG --------------------------------------- DAC1CON0 = %11100000;$E0, DAC ENABLED RIGHT JUSTIFIED ;---------DECLARING VARIABLES COUNTER VAR WORD; DECLARING COUNTING VARIABLES ;COUNTER.BYTE0 VAR TMR1L ;COUNTER.BYTE1 DAC VAR WORD; VARIABLE TO BE USED BY DAC SEL VAR BYTE; SCALE SELECTOR HZ VAR BYTE[5]; DIGITS FOR HERTZ DIV VAR WORD; IN VAR BYTE; VBE var word OUT VAR BYTE; I VAR WORD; I2 VAR WORD; ID VAR BYTE[3]; VIN VAR WORD; VID VAR BYTE[4]; VED VAR BYTE[4]; VIN2 VAR WORD; INVERT VAR PORTA.2; PIN FOR INVERTING DATA x var byte; VO VAR WORD[4]; OPTION_REG.7 = 0; ;--------PROGRAM STARTING ---------------- RPT: ;FIRST TEST, LET'S DO THE FIRST SCALE ;QUANTITY OF BITS IN THE DAC = 511, SO 5KHZ/511 ;5KHZ/511 = 9.7843 ;K=9.7843 FOR X = 0 TO 5; STARTING LOOPS HZ[X] = "0"; VO[X] = "0"; VIN = 0; CLEARING VARIABLES IN = 0; OUT = 0; SEL = 0; DAC = 0; DIV = 0; DAC = 0; VID[X] = "0"; ID[X] = "0" NEXT X; LCDOUT $FE,$C0,"WAITING FOR SCALE " OBTAIN_PULSES:; LCDOUT $FE,$80,"HZ= ",HZ[4],HZ[3],HZ[2],HZ[1],HZ[0]," Vout= ",VO[2],".",VO[1],VO[0]; TMR1L = 0; CLEARING REGISTERS IN TIMER1 TMR1H = 0; T1CON.0 = 1; TIMER 1 ENABLED PAUSE 1000; T1CON.0 = 0; TIMER 1 DISABLED COUNTER.BYTE0 = TMR1L; STORING LOW BYTE REGISTERS COUNTER.BYTE1 = TMR1H; STORING HI-BYTE REGISTERS FOR X = 0 TO 4; IN = COUNTER DIG X; GETTING DIGITS LOOKUP IN,["0123456789"],OUT; DECODING EACH DIGIT HZ[X] = OUT; STORING DIGITS NEXT X; LCDOUT $FE,$80,"HZ= ",HZ[4],HZ[3],HZ[2],HZ[1],HZ[0]," Vout= ",VO[2],".",VO[1],VO[0]; ;-----SELECTION------------ ;FOR X= 0 TO 255 SEL = (PORTA & %011000)>>3; READING PORTA ANS SHIFT RIGHT BITS 3 SPACES ;SELECTING SCALE IF SEL = %00 THEN GOSUB ESC1; 0-5KHZ IF SEL = %01 THEN GOSUB ESC2; 10K-50K IF SEL = %10 THEN GOSUB ESC3; 10KHZ-15KHZ IF SEL = %11 THEN GOSUB ESC4; 5KHZ-10KHZ IF INVERT = 0 THEN DAC = 511-DAC; INVERT DATA IF = 0 GOSUB V_DAC; LCDOUT $FE,$80,"HZ= ",HZ[4],HZ[3],HZ[2],HZ[1],HZ[0]," Vout= ",VO[2],".",VO[1],VO[0]; GOSUB DAC_OUT; GOTO OBTAIN_PULSES; GO TO LABEL OBTAIN_PULSES; ;------------------ FIRST SCALE ------------------------------ ESC1:; 0HZ A 5KHZ ; getting Scale values DIV = COUNTER *1000 DAC = DIV32 9784 IF (COUNTER >5000) THEN DAC = 0; ; EQUAL TO ZERO IF NOT IN RANGE LCDOUT $FE,$C0,"0-5KHZ DAC= ",dec dac," " RETURN; ;----------------------4th SCALE------------------- ESC4:; 10KHZ-50KHZ DIV = COUNTER*100 DAC = DIV32 7827 DAC = DAC - 127; IF (COUNTER >50000) OR (COUNTER <10000) THEN DAC = 0;EQUAL TO ZERO IF NOT IN RANGE LCDOUT $FE,$C0,"10-50KHZ DAC= ",DEC DAC," " RETURN; ;-----------------------3rd scale----------------- ESC3: ; ESCALA 10KHZ - 15KHZ DIV = COUNTER*1000 DAC = DIV32 9784 DAC = DAC - 1022; IF (COUNTER >15000) OR (COUNTER <10000) THEN DAC = 0; DAC=0 IF NOT IN RANGE LCDOUT $FE,$C0,"10-15KHZ DAC= ",DEC DAC," " RETURN; ;------------------------------------------------------------------------------ ESC2:; SCALE 5KHZ - 10KHZ ; --------------getting the values for this Scale IF (COUNTER >10000) OR (COUNTER <5000) THEN DAC = 0; DAC=0 IF NOT IN RANGE LCDOUT $FE,$C0,"5-10KHZ DAC= ",DEC DAC," " DIV = COUNTER*1000 DAC = DIV32 9784 DAC = DAC - 511; IF (COUNTER >10000) OR (COUNTER <5000) THEN DAC = 0 LCDOUT $FE,$C0,"5-10KHZ DAC= ",DEC DAC ," " RETURN; ;--VOLTAJE DAC--------- V_DAC: DISABLE VO[1]= DAC*976; GETTING VOLTAGE FROM DAC VO[3]= DIV32 100; WITH RESPECT TO NUMBER ENABLE FOR X = 0 TO 2; IN = VO[3] DIG (X+1); FIND THE RESPECTIVE DIGITS LOOKUP IN,["0123456789"],OUT;DECODING DIGITS VO[X] = OUT; STORE DIGITS NEXT X; RETURN; ;------------------------------------------------------------------------------- DAC_OUT: DAC1REFL = DAC.BYTE0; modifying the DAC0 register DAC1REFH = DAC.8; modifying DAC0-bit 8 RETURN; ;------------------------------ END;