lilith 发表于 2013-1-25 17:34:35

也算是电源吧-续:上来亮骚一下最近做的样机

在热心网友 TR 的帮助下,最近做了几台新的样机,修正了之前的一些问题,上来亮骚一下 {:lol:}另外把电路原理图整理了一下,原来画的图比较乱,程序也模块化整理了一下,并增加了对硬件的启动自检部分以方便 DIY 的时候排查错误。




这个是用金箔电阻的版本



这个是普通电阻版本


开机



自检



测试中

kevinstar888 发表于 2013-1-25 17:37:35

不错,期待楼主的资料

lilith 发表于 2013-1-25 17:38:58

上一版传送门:http://www.amobbs.com/thread-5483204-1-1.html

整理后的电路图,和上一版相比
1、主 DAC 为更加稳定的 MAX541(DAC5541),副 DAC 为 MAX515 不变
2、将副 DAC 输出电路更改为一个 x-1 反相放大器以调整电路的零点失调
3、使用了光耦(磁耦)将模数完善隔离了

lilith 发表于 2013-1-25 17:40:13

本版程序(陆续编写中,所以一些注释还没写,我会慢慢加上)

'///////////////////////////////////////////////////////////////////////////////////////////////////

                                                                                'Voltage Generator
                                                                                'By Lilith Washu

'///////////////////////////////////////////////////////////////////////////////////////////////////
$Device= m32                        ' 使用的单片机名称
$Stack = 32                               
$Clock = 11.0592                          ' 使用的单片机主频
$ShiftIn Data = PORTB.4, Clock = PORTB.3, Msb
$ShiftOut Data = PORTB.1, Clock = PORTB.2, Msb
$Baud = 19200,n,8,1
$1Wire = PORTD.6
$LeadChar="0", Format(2,6)

'************** Config the IO **************
' the Display Screen IO Connect
$Def IO_SCR_RST = PORTC.7
$Def IO_SCR_CSA = PORTC.6
$Def IO_SCR_CSB = PORTC.5
$Def IO_SCR_DoI = PORTC.4
$Def IO_SCR_RoW = PORTC.3
$Def IO_SCR_STB = PORTC.2
$Def IO_SCR_DAT = PORTA
' the Analog Board IO Connect
$Def IO_REG_STB = PORTB.0
$Def IO_REG_DAT = PORTB.1
$Def IO_REG_CLK = PORTB.2
$Def IO_ADC_CLK = PORTB.3
$Def IO_ADC_DAT = PINB.4
$Def IO_KEY_STB = PORTB.5
$Def IO_KEY_DAT = PINB.6
$Def IO_KEY_CLK = PORTB.7
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Constant
'///////////////////////////////////////////////////////////////////////////////////////////////////
Const fMasterReference = 7.042665e+00'7.080451E+00                'LM399 Voltage Value
Const fDACReference = 5.000000E+00                        'DAC Voltage Reference Value
Const fDACenter = 2.500000E+00                                'Slave DAC Default Output Voltage Value
Const fDACGain = 2.500000E+06                                'DAC Output buff Gain
Const fMResistance = 2.49E+02                                'DAC Voltgae Compound Resistance, the Master
Const fSResistance = 1E+06                                        'DAC Voltgae Compound Resistance, the Slave
Const Quadratic = -3.6031e+00                                'No-line Error Adjuest Quadratic Coefficient        二次项系数
Const Linear = 4.5495e+01                                        'No-line Error Adjuest Linear Coefficient                一次项系数
Const Constant = 5.6295e+01                                        'No-line Error Adjuest Offset Coefficient                常数
Const fDacal = 1.005258e+00'1.012857e+00                                        'DAC Fullscale Error Adjuest Vale
Const Synthesis = &b00000001                                ' Analog Switch = Synthesis Voltage Output                | DG412 Pin
Const Reference = &b00000010                                   ' Analog Switch = Internal Reference(LM399)                | DG412 Pin
Const ExternaIN = &b00000100                                ' Analog Switch = Externa Voltage Input                        | DG412 Pin
Const GndOffset = &b00001000                                ' Analog Switch = Auto Zero                                                | DG412 Pin
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' String Variables
'///////////////////////////////////////////////////////////////////////////////////////////////////
Dim Ft1 As Flash Byte        ' 软字体码表
Dim Ft2 As Flash Byte        ' 软字体码表
Dim Charat As String *33' 要显示的字符缓冲区
Dim tTxt As String *15
Dim tm As String *7
Dim tCmd As String *4
Dim iCursors(8) As Byte
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Gen Variables
'///////////////////////////////////////////////////////////////////////////////////////////////////
Dim i As Byte       
Dim bUartset As Byte
Dim bUartlk As Byte
Dim bAdjuest As Byte
Dim bDigitaLoop As Byte
Dim bRun As Byte
Dim bTrigcompleted As Byte
Dim bRefsource As Byte

Dim iErrlimit As Byte

Dim bSregister As Byte
Dim iSmlen As Byte               
Dim iSmsetp As Byte
Dim iBusystp As Byte
Dim iTrd As Byte
Dim iDraw As Word
Dim CurrentChannel As Byte
Dim bNextchannel As Byte
Dim itm As Byte
Dim iDa As Byte
Dim iDb As Byte
Dim iDc As Byte
Dim iDd As Byte
Dim iTa As Byte
Dim iTb As Byte
Dim iTc As Byte
Dim iTd As Byte
Dim bADCResult(3) As Byte
Dim bREGa(64) As Byte
Dim bREGb(64) As Byte
Dim bREGc(64) As Byte
Dim bREGd(64) As Byte
Dim dTempdatum(1) As Byte
Dim dTempresult As Word
Dim iError As Integer
Dim wError As Word

Dim IsTempresultSense As Byte
Dim iTestcode As Byte
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Float Variables
'///////////////////////////////////////////////////////////////////////////////////////////////////
Dim fTrn As Float
Dim fOut As Float
Dim fGndOffset As Float
Dim fReference As Float
Dim fSynthesis As Float
Dim fCalsacles As Float
Dim fCalfSynth As Float
Dim fSetting As Float
Dim fVoltage As Float
Dim fError As Float
Dim fVset As Float
Dim fVtrn As Float
Dim fTemperature As Float
Dim Vseth As Word
Dim Vsetl As Word
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                ' Screen Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
Declare Function WriteKS(Code As Byte, Channel As Byte) As Byte                                ' 向显示屏写数据的函数
Declare Function SetKS(Code As Byte, Channel As Byte) As Byte                                ' 向显示屏写指令的函数
Declare Function InitKS() As Byte                                                                                        ' 初始化显示屏
Declare Function ResetKS() As Byte                                                                                        ' 显示屏上电函数,可用硬件电路代替
Declare Function ClsKS(GRAM As Byte) As Byte                                                                ' 清屏函数
Declare Function DrawPix(x As Byte, y As Byte) As Byte                                                ' 在显示屏上画一个点
Declare Function DrawPage(x As Byte, Page As Byte, Code As Byte) As Byte        ' 在显示屏上画一个页
Declare Function DrawChr(x As Byte, Page As Byte) As Byte                                        ' 显示一行标准 ASCII 字符
Declare Function DrawChrLarge(x As Byte, Page As Byte) As Byte                                        ' 显示一行标准 ASCII 字符
Declare Function DrawCursors(x As Byte, Page As Byte, Length As Byte) As Byte
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                                ' IO Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
Declare Function WriteSReg(bDat As Byte) As Byte
Declare Function SetChannel(Channel As Byte) As Byte
Declare Function ReadADC() As Byte
Declare Function ReadKEY() As Byte
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                        ' Mathematical Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
Declare Function SetVoltage(fVoltage As Float) As Byte
Declare Function Getinlerr(fVoltage As Float) As Float

Declare Function ReadADConvert(NextChannel As Byte) As Long
Declare Function FixADCResult() As Byte
Declare Function WriteResultREG(bSetp As Byte, bArea As Byte) As Byte
Declare Function MoveResultREG(bSetp As Byte, bArea As Byte) As Byte
Declare Function ReadADCResult(bChannel As Byte) As Float
Declare Sub StatusDisplay()
Declare Function UpdateTempresultInfo() As Byte
Declare Sub Trigcompleted()
Declare Function ADCheck(bNextChannel As Byte) As Integer
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                        ' UART Interrupt
'///////////////////////////////////////////////////////////////////////////////////////////////////
Declare Interrupt Urxc()                                               
Enable Interrupts
Enable Urxc
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Config the MCU IO Register
'///////////////////////////////////////////////////////////////////////////////////////////////////
DDRA = &b11111111                'Display Screen Data Bus
                                                        'Parallel 8bit Data bus
DDRC = &b11111111                'Display Screen Control Bus
                                                        'PC0: (Saved)
                                                        'PC1: (Saved)
                                                        'PC2: Screen Strobe
                                                        'PC3: Screen Write or Read
                                                        'PC4: Screen Data or Instructions
                                                        'PC5: Screen Area Enable LO Bit
                                                        'PC6: Screen Area Enable HI Bit
                                                        'PC7: Screen Reset
DDRB = &b10101111                'Analog Board Connect
                                                        'REG STB <--- PB0
                                                        'REG DAT <--- PB1
                                                        'REG CLK <--- PB2
                                                        'ADC CLK <--- PB3
                                                        'ADC DAT ---> PB4
                                                        'KEY STB <--- PB5
                                                        'KEY DAT ---> PB6
                                                        'KEY CLK <--- PB7
DDRD = &b11111111                'INT, UART and PWM Control
                                                        'PD0: UART RX
                                                        'PD1: UART TX
                                                        'PD2: INT0 TRIG(Key)
                                                        'PD3: INT1 TRIG(Saved)
                                                        'PD4: PWM OC1B(Saved)
                                                        'PD5: PWM OC1A(Saved)
                                                        'PD6: 1Wire BUS(DS18b20)
                                                        'PD7: PWM OC2(Saved)               
PORTA = &b00000000                                               
PORTB = &b00000000
PORTC = &b00000000
PORTD = &b00000000
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                        ' Program Initialization
'///////////////////////////////////////////////////////////////////////////////////////////////////                                               
' Analog Board Initialization, Open all Analog Switch
bSregister = &b00000000
WriteSReg(bSregister)
' DAC Initialization to 0V Output
SetVoltage(0)
InitKS()                                ' 初始化显示屏
ClsKS(0)                                ' 清屏
' LCD Test and Init Display Charat
                        Charat = "Voltage Generator" : DrawChrLarge(6,1)
                        Charat = "Version 1.0" : DrawChr(32,3)
                        Charat = "Build 173" : DrawChr(44,4)
                        Charat = "By Lilith Washu" : DrawChr(38,6)

Wait 2                                        'Wait the LM399 Initialization
ClsKS(0)
Charat = "Initialization" : DrawChr(1,0)
'Initialization Var?

Charat = "Initialization   OK" : DrawChr(1,0)
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                        ' EEPROM Initialization
'///////////////////////////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                        ' Self Test
'///////////////////////////////////////////////////////////////////////////////////////////////////
iTestcode = 0
Charat = "Self Test......" : DrawChr(1,1)
Format(5,0)
' Check the Tempresult Sense(DS18b20)
IsTempresultSense = 1Wreset
If Not(IsTempresultSense) Then
        Charat = ">TepSense not install" : DrawChr(1,2)
        IsTempresultSense = 0
Else
        Charat = ">TemperatureSense Chk" : DrawChr(1,2)
        1Wwrite &hcc; &h44
        WaitMs 500
        1Wreset
        1Wwrite &hcc; &hbe
        1Wread dTempdatum ,2
        1Wreset
        1Wwrite &hcc; &h44
        dTempresult = dTempdatum(0)
        'Charat = Str(dTempresult) : DrawChr(156,2)
        If dTempresult = 0 Then
                Charat = ">TemperatureSense Err" : DrawChr(1,2)
                IsTempresultSense = 0
                iTestcode = iTestcode Or &b00000001
        Else
                Charat = ">Temperature Sense OK" : DrawChr(1,2)
                IsTempresultSense = 1
        End If
End If
' Check the ADC(LTC2400)
'Charat = ">ADC Checked..." : DrawChr(1,3)
If IO_ADC_DAT = 1 Then
        Charat = ">ADC Detect...Failed" : DrawChr(1,3)
        iTestcode = iTestcode Or &b00000010
Else
        SetChannel(GndOffset)
        bADCResult(3) = ShiftIn : bADCResult(2) = ShiftIn : bADCResult(1) = ShiftIn : bADCResult(0) = ShiftIn
        iBusystp = 0
        For i = 1 To 200
                iBusystp = iBusystp + 1
                If IO_ADC_DAT = 0 Then Exit For
                WaitMs 1
        Next i
        If iBusystp < 155 Or iBusystp > 166 Then
                Charat = ">ADC ChK Failed" : DrawChr(1,3)
                Charat = Str(iBusystp) : DrawChr(94,3)
                iTestcode = iTestcode Or &b00000100
        Else
                Charat = ">ADC Checked...Passed" : DrawChr(1,3)
                iError = ADCheck(Reference)                                                                'Result = GND Offset < +10~-10 >
                If iError <> 0 Then
                        If iError > -10 And iError < 10 Then
                                Charat = ">COM Checked...Passed" : DrawChr(1,4)
                        Else
                                Charat = ">COM ChK Failed " : DrawChr(1,4)
                                Charat = Str(iError) : DrawChr(94,4)
                                iTestcode = iTestcode Or &b00001000
                        End If
                Else
                        Charat = ">COM Checked...Passed" : DrawChr(1,4)
                End If       
                'Check the Reference
                Charat = ">Reference Chk:" : DrawChr(1,5)
                SetVoltage(0) : WaitMs 10
                iError = ADCheck(Synthesis)                                                                'Result = Reference, Next is Synthesis Out Voltage <6500*1.024~7500*1.024 / 6655~7680>
                wError = iError * 25 / 8
                If wError > 6800 And wError < 7475 Then
                        Charat = ">REF Checked...Passed" : DrawChr(1,5)
                Else
                        Charat = Str(wError) : DrawChr(94,5)
                        iTestcode = iTestcode Or &b00010000
                End If
                'Check the DAC Offset
                Charat = ">DAC Check 1st." : DrawChr(1,6)
                WaitMs 200                                                                                                'Wait the ADC to Converting...
                SetVoltage(12000000) : WaitMs 10                                                'Set Next Check Item = DAC Fullscale Out
                iError = ADCheck(Synthesis)                                                                'Result = Synthesis Out Voltage(Set=0V) <+~-1>
                If iError <> 0 Then
                        If iError > -10 And iError < 10 Then
                                Charat = ">DAC Check 1st Passed" : DrawChr(1,6)
                        Else
                                Charat = Str(iError) : DrawChr(94,6)
                                iTestcode = iTestcode Or &b00100000
                        End If
                Else
                        Charat = ">DAC Check 1st Passed" : DrawChr(1,6)
                End If       
                'Check the DAC Full Scale
                Charat = "2nd" : DrawChr(67,7)
                WaitMs 200
                'SetVoltage(0)
                iError = ADCheck(Synthesis)                                                                'Result = Synthesis Out Voltage(Set=12V) <12282 +/- 10word, 12270~12295>
                wError = (iError / 2) * 25 / 4
                If wError > 12000 And wError < 12575 Then
                        Charat = "Passed" : DrawChr(91,7)
                Else
                        Charat = Str(wError) : DrawChr(94,7)
                        iTestcode = iTestcode Or &b01000000
                End If
        End If
End If
If iTestcode > 1 Then
        Charat = "Failed" : DrawChr(91,1)
        Charat = "Code:" : DrawChr(1,7)
        Format(3,0) : Charat = Str(iTestcode) : DrawChr(31,7)
        End
Else
        Charat = "OK" : DrawChr(115,1)
End If



'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                        ' Self Test End
'///////////////////////////////////////////////////////////////////////////////////////////////////



Wait 1        'Wait the LM399 Warmed
ClsKS(0)
' Screen Fixed Display Initialization
                        Charat = "SET:"
                        DrawChrLarge(1,0)
                        Charat = "REB:"
                        DrawChrLarge(1,2)
                        Charat = "VDC"
                        DrawChrLarge(105,0)
                        DrawChrLarge(105,2)
' Right Sataus Lable Display
                        'Charat = "MH:"
                        'DrawChr(156,0)
                        'Charat = "ML:"
                        'DrawChr(156,1)
                        'Charat = "SH:"
                        'DrawChr(156,2)
                        'Charat = "SL:"
                        'DrawChr(156,3)
                        'Charat = "WAT:" : DrawChr(156,4)
                        'Charat = "ADJ:"
                        'DrawChr(156,5)
'Botton Sataus Label Display
                        Charat = "IGNO" : DrawChr(9,4)
                        Charat = "EXEC" : DrawChr(9,5)
                        'Charat = "TemP" : DrawChr(12,6)
                        'Charat = "Filt" : DrawChr(96,6)
                        Charat = "ErroR" : DrawChr(52,6)
                        Charat = "RuN" : DrawChr(100,5)
                        Charat = "StP" : DrawChr(100,4)
' Cursors Draw
                        'MemLoad(VarPtr(iCursors), &b00001000, &b00011100, &b00111110, &b01111111) : DrawCursors(1, 4, 4)                                ' Display a "<" Cursors
                        'MemLoad(VarPtr(iCursors), &b01111111, &b00111110, &b00011100, &b00001000) : DrawCursors(1, 4, 4)                                ' Display a ">" Cursors
                        'MemLoad(VarPtr(iCursors), &b00000100, &b00000110, &b00000111, &b00000110, &b00000100) : DrawCursors(1, 4, 5)         ' Display a "^" Cursors
If IsTempresultSense = 1 Then
                        MemLoad(VarPtr(iCursors), &b00000110, &b00001001, &b00001001, &b000000110) : DrawCursors(31, 7, 4)                                ' Display aDegree Cursors
                        Charat = "C" : DrawChr(37,7)
                        UpdateTempresultInfo()
End If
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                        ' Program Initialization End
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Start the Temperature Sense(DS18b20) Convert
'1Wreset
'1Wwrite &hcc; &h44
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                                        ' RunningRegister Initialization
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Init the DAC Output Default
fSetting = 10000000
fVoltage = fSetting
' Program Reset Point:
stt:                                                               
fVoltage = fVoltage / fDacal
SetVoltage(fVoltage)
' All Setting Register Value Initialization to Default
fReference = 0
fSynthesis = 0
fCalsacles = fMasterReference
iSmlen = 16                                ' the Sommth Length, 1 Trig Cycle(Adjuest Cycle) = 3 x Sommth Length
bDigitaLoop = 1                        ' Digital Loop = Close Loop(0=Open Loop)
itm = 0
iSmsetp = 0                                ' Current Program Running Setp
bRun = 1                                ' Flag the Program Run or Setp, 1 = Run
bRefsource = 0                        ' Flag the Reference Source, 0 = INT, 1 = EXT
bNextchannel = 0                ' Flag the Analog Switch Channel
bAdjuest = 0                        ' Flag is/isnot Adjuest Output Voltage
bUartlk = 1                                ' Flag the UART Port Talk,bit 8 = All Talk; bit 1 = talk when Trigcompleted.
bUartset = 2
' Display and Update the Output Voltage Setting Value
Format(2,0)
Charat = Str(iSmlen) : DrawChr(104,7)
'Charat = Str(iSmlen * 3 + 1) : DrawChr(179,7)
Charat = "pt":DrawChr(116,7)
Charat = "/" :DrawChr(98,7)

Format(2,6)
fTrn = fSetting / 1000000
Charat = Str(fTrn)
DrawChrLarge(28,0)

'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

                                                                                'Program Main Loop

'///////////////////////////////////////////////////////////////////////////////////////////////////
Do
        If bRun = 0 Then
                Charat = " ---------" : DrawChrLarge(28,2)
                MemLoad(VarPtr(iCursors), &h00, &h00, &h00, &h00) : DrawCursors(122, 5, 4)
                MemLoad(VarPtr(iCursors), &h08, &h1C, &h3E, &h7F) : DrawCursors(122, 4, 4)
                iSmsetp = 0
                WaitMs 100
                GoTo Runout
        Else
                MemLoad(VarPtr(iCursors), &h00, &h00, &h00, &h00) : DrawCursors(122, 4, 4)
                MemLoad(VarPtr(iCursors), &h08, &h1C, &h3E, &h7F) : DrawCursors(122, 5, 4)       
        End If
       
        bNextchannel = bNextchannel + 1
        If bNextchannel > 3 Then bNextchannel = 1
        iBusystp = 0
        Do
                iBusystp = iBusystp + 1
                WaitMs 1
        Loop While IO_ADC_DAT = 1
        Select Case bNextChannel
                        Case 1 : CurrentChannel = SetChannel(Reference)
                        Case 2 : CurrentChannel = SetChannel(GndOffset)
                        Case 3 : CurrentChannel = SetChannel(Synthesis)
        End Select
       
       
        'Charat = Hex(iBusystp) : DrawChr(64,4)
        bADCResult(3) = ShiftIn
        bADCResult(2) = ShiftIn
        bADCResult(1) = ShiftIn
        bADCResult(0) = ShiftIn
        FixADCResult()
       
        For i = 1 To iSmlen
                MoveResultREG(i, bNextchannel)
        Next i
        WriteResultREG(iSmlen, bNextchannel)
       
        iSmsetp = iSmsetp + 1
        Format(2,0)
        Charat = Str(iSmsetp/3)
        DrawChr(86,7)
       
        fSynthesis = ReadADCResult(1) 'syn
        fReference = ReadADCResult(2) 'ref
        fGndOffset = ReadADCResult(3) 'gnd
       
        fCalfSynth = (fSynthesis - fGndOffset) / ((fReference - fGndOffset) / fCalsacles)
        'fCalfSynth = fCalfSynth - Getinlerr(fCalfSynth) * 1000000
        fError = fSetting - fCalfSynth * 1000000
        iError = fError
        wError = iError * iError
       
        Format(2,6)
        Charat = Str(fCalfSynth)
        DrawChrLarge(28,2)
               
        Format(4,0)
        Charat = "   " : DrawChr(52,7)
        Charat = Str(iError) : DrawChr(52,7)
        'Charat = Str(wError) : DrawChr(1,5)
       
        iErrlimit = 0
        If wError > 99 Then iErrlimit = 1
        bAdjuest = bDigitaLoop And iErrlimit
       
        'Format(2,0)
        'Charat = Str(bAdjuest) : DrawChr(180,5)
       
        If iSmsetp = iSmlen * 3 + 1 Then
                iSmsetp = 0
                Trigcompleted()
        End If
       
        Runout:
        If bUartset = 1 Then
                bUartset = 0
                iSmsetp = 0
                fVoltage = fSetting
                fVoltage = fVoltage / fDacal
                SetVoltage(fVoltage)
                fTrn = fSetting / 1000000
                Format(2,6)
                Charat = Str(fTrn)
                DrawChrLarge(28,0)
        End If
       
        If bUartset = 2 Then
                bUartset = 0
                StatusDisplay()
        End If
Loop
End

'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

                                                                                'Operation Sub and Function

'///////////////////////////////////////////////////////////////////////////////////////////////////
Sub StatusDisplay()
If bDigitaLoop = 1 Then
        MemLoad(VarPtr(iCursors), &h00, &h00, &h00, &h00) : DrawCursors(1, 4, 4)
        MemLoad(VarPtr(iCursors), &h7F, &h3E, &h1C, &h08) : DrawCursors(1, 5, 4)
Else
        MemLoad(VarPtr(iCursors), &h00, &h00, &h00, &h00) : DrawCursors(1, 5, 4)
        MemLoad(VarPtr(iCursors), &h7F, &h3E, &h1C, &h08) : DrawCursors(1, 4, 4)
End If

End Sub

Function UpdateTempresultInfo() As Byte
        1Wreset
        1Wwrite &hcc; &hbe
        1Wread dTempdatum ,2
        1Wreset
        1Wwrite &hcc; &h44
        dTempresult = dTempdatum(0)
        fTemperature = dTempresult
        fTemperature = fTemperature / 16
        Format(2,1) : Charat = Str(fTemperature) : DrawChr(1,7)
End Function

Sub Trigcompleted()
        If bAdjuest = 1 Then
                fVoltage = fVoltage + fError
                SetVoltage(fVoltage)
        End If
        If IsTempresultSense = 1 Then UpdateTempresultInfo()
        If bUartlk = 1 Then
                Format(5,2)
                Print fError; fTemperature
        End If
End Sub

'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Return the 24bit Result from 32bit Data
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function FixADCResult() As Byte
iDa = bADCResult(3)
iDb = bADCResult(2)
iDc = bADCResult(1)
iDd = bADCResult(0)
' Casting out the lower 4bit Data and Return the low 8bit Result
iDd = iDd And &b11110000
iDd = Swap(iDd)
iTrd = iDc And &b00001111
iTrd = Swap(iTrd)
iTd = iDd + iTrd
' Move and Return the middle 8 bit Result
iTrd = iDc And &b11110000
iTc = Swap(iTrd)
iTrd = iDb And &b00001111
iTrd = Swap(iTrd)
iTc = iTrd + iTc
' Move and Return the hihg 8 bit Result
iTrd = iDb And &b11110000
iTb = Swap(iTrd)
iTrd = iDa And &b00001111
iTrd = Swap(iTrd)
iTb = iTrd + iTb
' Return the Overload and Sign Bit
iTrd = iDa And &b00110000
iTa = Swap(iTrd)
' Copy Result to Public Array
bADCResult(3) = iTa
bADCResult(2) = iTb
bADCResult(1) = iTc
bADCResult(0) = iTd
Return 0
End Function

'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Write a ADC Result to FIFO Movewindow Array
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function WriteResultREG(bSetp As Byte, bArea As Byte) As Byte
iTrd = (bArea - 1) * iSmlen + bSetp
bREGa(iTrd) = bADCResult(3)
bREGb(iTrd) = bADCResult(2)
bREGc(iTrd) = bADCResult(1)
bREGd(iTrd) = bADCResult(0)
End Function

'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Move the FIFO Array
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function MoveResultREG(bSetp As Byte, bArea As Byte) As Byte
iTrd = (bArea - 1) * iSmlen + bSetp
bREGa(iTrd) = bREGa(iTrd + 1)
bREGb(iTrd) = bREGb(iTrd + 1)
bREGc(iTrd) = bREGc(iTrd + 1)
bREGd(iTrd) = bREGd(iTrd + 1)
End Function

'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Return a Float Format Smohth ADC Result
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function ReadADCResult(bChannel As Byte) As Float
fTrn = 0
fOut = 0
For i = 1 To iSmlen
        iTrd = (bChannel - 1) * iSmlen + i
        iTa = bREGa(iTrd)
        iTb = bREGb(iTrd)
        iTc = bREGc(iTrd)
        iTd = bREGd(iTrd)
        fTrn = 5 * 2.5 * (16777216 * iTa + 65536 * iTb + 256 * iTc + iTd - 33554432) / 16777216
        fOut = fOut + fTrn
Next i
fOut = fOut / iSmlen
Return fOut
End Function



Function DrawCursors(x As Byte, Page As Byte, Length As Byte) As Byte
For i = 0 To Length - 1
        DrawPage(x + i, Page, iCursors(i))
Next i
End Function


Function ADCheck(bNextChannel As Byte) As Integer
Local iChkresutl As Integer
Local iChk1 As Byte
Local iChk2 As Byte
Local iChk3 As Byte
Local iChk4 As Byte
Do
Loop While IO_ADC_DAT = 1
SetChannel(bNextChannel) : WaitMs 10
iChk4 = ShiftIn : iChk3 = ShiftIn : iChk2 = ShiftIn : iChk1 = ShiftIn
iChkresutl = iChk4 * 4
iChkresutl = iChkresutl * 256 + iChk3 * 4 - 32768
Return iChkresutl / 4
End Function

'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

                                                                                'Shiftreg IO

'///////////////////////////////////////////////////////////////////////////////////////////////////



'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Wrtie the Analog board Control Shift-Register
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function WriteSReg(bDat As Byte) As Byte
Local i As Byte
Local bWritedat As Byte
Local bWritebit As Byte
bWritedat = bDat
IO_REG_DAT = 0
IO_REG_CLK = 0
IO_REG_STB = 0
WaitUs 1
For i = 1 To 8
    bWritebit = bWritedat And &b10000000
    If bWritebit = 128 Then
       IO_REG_DAT = 1
    Else
       IO_REG_DAT = 0
    End If
    WaitUs 1
    IO_REG_CLK = 1 : WaitUs 1 : IO_REG_CLK = 0
    bWritedat = Shift(Left, 1, bWritedat)
Next i
WaitUs 1
IO_REG_STB = 1 : WaitMs 1 : IO_REG_STB = 0
IO_REG_DAT = 0
IO_REG_CLK = 0

Return 0
End Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Setting the Analog Switch(ADC Input Channel)
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function SetChannel(Channel As Byte) As Byte                               
Local Channelset As Byte
Channelset = bSregister And &b11110000
WriteSReg(Channelset)                ' Open all Analog Switch when Close Next Switch
WaitMs 10
bSregister = Channelset + Channel
WriteSReg(bSregister)
Return bSregister
End Function

'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Read Analog Board ADC Result Shift-Register
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function ReadADC() As Byte
Local myByte As Byte
Local i As Byte
myByte = 0
' Read 8bit = 1 Byte Result form ADC Shift-Out Register(2Wire Serial Bus ADC)
For i = 0 To 7
    IO_ADC_CLK = 1   
    Rotate(Left,1,myByte)
    myByte = myByte + IO_ADC_DAT
    WaitUs 1
    IO_ADC_CLK = 0
    WaitUs 1      
Next i
' Return 1 Byte Result to Function
Return myByte
End Function

'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Read MCU Block Keyboard Status Shift-Register
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function ReadKey() As Byte
Local myByte As Byte
Local i As Byte
myByte = 0
' Read 8bit = 1 Byte Result form Keyboard Shift-Out Register(74HC165)
For i = 0 To 7
    Rotate(Left,1,myByte)
    myByte = myByte + IO_KEY_DAT
    IO_KEY_CLK = 1
    WaitUs 1
    IO_KEY_CLK = 0
    WaitUs 1      
Next i
' Return 1 Byte Result to Function
myByte = Not myByte
Return myByte
End Function

'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

                                                                        'Mathematical Function

'///////////////////////////////////////////////////////////////////////////////////////////////////



'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' Setting the Analogboard DAC Output Voltage
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function SetVoltage(fVoltage As Float) As Byte
Local Vsetm As Word                ' The Master DAC Setting Return
Local Vsets As Word                ' The SlaveDAC Setting Return
Local mbMSB As Byte
Local mbLSB As Byte       
Local sbMSB As Byte
Local sbLSB As Byte
' the VOut = Gain * (Vmaster * Rs + Vslave * Rm) / (Rm+Rs), Fullscale of the Vm = 5V and Vs = -5V, Gain = 2.5
fVtrn = fVoltage
fVtrn = fVtrn / fDACGain
fVset = fVtrn
'Get the MasteDAC Voltage Setting Value, Vm=/Rs , at Default, the Slave DAC Output = -2.5V
fVtrn = (fVtrn * (fMResistance + fSResistance) + fDACenter * fMResistance) / fSResistance
fVtrn = fVtrn * 65535 / fDACReference                                                        'The Master DAC(MAX541) is 16bit DAC, Fullscale = 2^16 = 65536
Vsetm = fVtrn
mbMSB = Msb(Vsetm)                                                                                                'Split the Setting Word to two Byte, Get the MSB Byte
mbLSB = Vsetm - mbMSB * 256                                                                                'Split the Setting Word to two Byte, Get the LSB Byte
' Get the SlaveDAC Voltage Setting Value,Vs=/Rm
fVtrn = Vsetm * fDACReference / 65535
fVtrn = 0 - ((fVset * (fMResistance + fSResistance) - fVtrn * fSResistance) / fMResistance)
fVtrn = fVtrn * 4096 / fDACReference                                                        'The Slave DAC(MAX515) is 12bit DAC, Fullscale = 2^12 = 4096
Vsets = fVtrn
sbMSB = Msb(Vsets)                                                                                                'Split the Setting Word to two Byte, Get the MSB Byte
sbLSB = Vsets - sbMSB * 256                                                                                'Split the Setting Word to two Byte, Get the LSB Byte
' Write the Setting to DAC
'Setp 1:
bSregister = bSregister And &b00001111                                                        'Hold the Analog Switch Status and Setting the DAC to Write Mode
ShiftOut mbMSB;mbLSB;sbMSB;sbLSB;bSregister                                                'Write to Serial Bus
IO_REG_STB = 1 : WaitUs 10 : IO_REG_STB = 0                                                'Update the Control Shift-Register, DAC tobe Write
'Setp 1:
bSregister = bSregister + &b10000000                                                        'Hold the Analog Switch Status and Setting the DAC to Update
ShiftOut mbMSB;mbLSB;sbMSB;sbLSB;bSregister
IO_REG_STB = 1 : WaitUs 10 : IO_REG_STB = 0                                                'Update the Control Shift-Register, DAC tobe Update
Return 0
End Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
                                                        ' ADC No-line Error Adjuest
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function Getinlerr(fVoltage As Float) As Float                       
fVtrn = fVoltage
fVset = fVtrn * fVtrn * Quadratic - fVtrn * Linear + Constant
Return fVset
End Function




'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

                                                                        'Self Test Code

'///////////////////////////////////////////////////////////////////////////////////////////////////




Interrupt Urxc(),Save All
Local uVseth As Word
Local uVsetl As Word
'Local uMSBh As Byte
'Local uLSBh As Byte
'Local uMSBl As Byte
'Local uLSBl As Byte
Local bMSB As Byte
Local bLSB As Byte
Local bRebtype As Byte
Local bSett As Byte
InputBin tTxt

tCmd = Mid(tTxt, 1, 3)
If tCmd = "STV" Then
   tm = Mid(tTxt,4,4)
   uVseth = Val(tm)
   tm = Mid(tTxt,8,4)
   uVsetl = Val(tm)
   fVtrn = uVseth
   fVtrn = fVtrn * 10000
   fVtrn = fVtrn + uVsetl
   tm = Mid(tTxt,12,1)
   bSett = Val(tm)
   If bSett = 0 Then
      fSetting = fVtrn
      bUartset = 1
   End If
   If bSett = 1 Then
      fCalsacles = fVtrn
      bUartset = 1
   End If
End If

If tCmd = "STS" Then
   tm = Mid(tTxt,4,1)
   If tm <> "x" Then bDigitaLoop = Val(tm)
   tm = Mid(tTxt,12,1)
   If tm <> "x" Then bRun = Val(tm)
   tm = Mid(tTxt,11,1)
   If tm <> "x" Then bRefsource = Val(tm)
   bUartset = 2
End If

If tCmd = "REB" Then
   tm = Mid(tTxt,4,1)
   bRebtype = Val(tm)
   Select Case bRebtype
          Case 0 ' Readback Measure Value(0-?)
          Case 8 ' Readback Cal
          Case 9 ' Readback Setting Status
   End Select
End If



Enable Interrupts
End Interrupt

$Include "k12864drv.bas"
$Include "..\font1.bas"
$Include "..\font2.bas"

lilith 发表于 2013-1-25 17:43:42

本帖最后由 lilith 于 2013-1-25 17:44 编辑

上面的 k12864drv.bas 是屏的驱动,连同字体码表在我的帖子
http://www.amobbs.com/thread-5487162-1-1.html

有,就不再帖了;原理和部分程序注释上一版帖子也有,所以也就不再重复赘述啦 {:lol:}

HYLG 发表于 2013-1-25 17:54:35

也算是电压表吧,也算是牛人吧。

HYLG 发表于 2013-1-25 17:56:32

显示屏是不是自己换的红色背光。

llssr 发表于 2013-1-25 18:11:15

仪器不错

javabean 发表于 2013-1-25 18:17:14

basic搞AVR……强大!

xinjihua 发表于 2013-1-25 18:31:27

显示屏是不是自己换的红色背光。

jeffwei 发表于 2013-1-25 18:37:35

很漂亮,精度也够高的了

PCBBOY1991 发表于 2013-1-25 18:48:44

我做了一个数控电源也是用的MAX541,但是这个是没有输出缓冲器的,直接用的误差不是很大。最近我那个电源调试了一点,因为单点接地的问题还是有点误差,恒压恒流的时候都有误差,更改了接地线以后精度终于达到了预期的效果。{:smile:}

mysunmax 发表于 2013-1-25 18:58:34

不错哈~~~~

st8051 发表于 2013-1-25 19:06:36

精密电源啊~~

gaolf_2012 发表于 2013-1-25 19:43:52

佩服!强

kpzclxtx 发表于 2013-1-25 20:23:20

大神、、膜拜。。。。

JQ_Lin 发表于 2013-1-25 21:08:32

很不错的东东。
顶!

PCBBOY1991 发表于 2013-1-25 21:09:47

楼主您能给将一下你这个PCB在布线过程中单点接地以及地的问题能给讲一下吗?我做的两版数控电源都是因为单点接地的问题会有误差。{:mad:}

kxm2008 发表于 2013-1-25 21:22:32

看那个显示的初始化过程感觉像台pc机,很骚包{:lol:}

fxw7720268 发表于 2013-1-25 21:39:55

这设备挺好的,真不错!

475627406 发表于 2013-1-25 22:13:44


这个是你以前的电路,第一次见你这个电路的时候,感觉很别扭
现在想不通这样做有啥用,你的目的的:频率补偿?降低带宽来降低噪声?
Cc的零点很低,在Cout引入的极点抵消。最后在高频处回路的相位裕度很小!!

你如果是要降低带宽来降低噪声?消除Cout引入的极点,那把Cc去掉,Rc搞个50欧就行了

kejiren123 发表于 2013-1-25 22:19:51

{:smile:}此贴必火,收藏。

475627406 发表于 2013-1-25 22:25:52

或者ad588中的这个电路

475627406 发表于 2013-1-25 22:31:13

PCBBOY1991 发表于 2013-1-25 21:09 static/image/common/back.gif
楼主您能给将一下你这个PCB在布线过程中单点接地以及地的问题能给讲一下吗?我做的两版数控电源都是因为单点 ...

电压电流采集端,画pcb时可以模拟“开尔文流量法”

说简单点就是不要让其他无关的电流在‘信号线’上流过,而让它流回地去

PCBBOY1991 发表于 2013-1-25 22:48:40

475627406 发表于 2013-1-25 22:31 static/image/common/back.gif
电压电流采集端,画pcb时可以模拟“开尔文流量法”

说简单点就是不要让其他无关的电流在‘信号线’上流 ...

今天测试的时候我还发现一个问题,本来在OPA177构成的差分放大器(对电压输出进行运算到0~2.5V)和DA出来的电压分别加在另外一个OPA177的反相端和同相端,模拟电路部分和春风的第二版几乎一样。

U11A和U11B我用的OPA177,U11B(OPA177)的输出端到U11A(OPA177)的反相端本来我接的是1。9K欧的电阻(整个电路的微调电容和春风的一样),在空载的时候电压值和设定值一样,但是一旦负载变大后,输出电压下降了大概10mV,然后我测得R21两端有压降,已经不符合工作在线性放大输入电阻为无穷大的理论了,然后我换成2.7K,5%的电阻后,无论设定多少电压,负载电流多大,输出压降就有1~2mV,我确保差分电路没有问题,可能出在U11B到U11A之间上。能给解释下吗。

475627406 发表于 2013-1-25 23:10:39

PCBBOY1991 发表于 2013-1-25 22:48 static/image/common/back.gif
今天测试的时候我还发现一个问题,本来在OPA177构成的差分放大器(对电压输出进行运算到0~2.5V)和DA出来 ...

虽然op177的Iib比084大,但在R21上应该还表现不出来

“无论设定多少电压,负载电流多大,输出压降就有1~2mV”这个够怪异
你测u11a两个输入端电压差为多少?应该很小
再测下R20上是否有电压降

marshallemon 发表于 2013-1-25 23:12:15

等待出套件,LZ什么时候出套件?

yuhang 发表于 2013-1-25 23:23:16

电压基准够奢侈的

kdtcf 发表于 2013-1-25 23:27:20

程控电压源,楼主牛B,还两台6581,好想去你家抢劫{:funk:}

kdtcf 发表于 2013-1-25 23:32:41

楼主照片啥手机拍的,爱疯四吗{:lol:}

marshallemon 发表于 2013-1-25 23:34:22

本帖最后由 marshallemon 于 2013-1-25 23:36 编辑

475627406 发表于 2013-1-25 22:13 static/image/common/back.gif
这个是你以前的电路,第一次见你这个电路的时候,感觉很别扭
现在想不通这样做有啥用,你的目的的:频率补 ...

电压跟随,也为了接容性负载稳定把

lilith 发表于 2013-1-25 23:45:01

475627406 发表于 2013-1-25 22:13 static/image/common/back.gif
这个是你以前的电路,第一次见你这个电路的时候,感觉很别扭
现在想不通这样做有啥用,你的目的的:频率补 ...

降低带宽来降低噪声?


--------------


是的,你都说了,其实是我不知道要如何才能降低电路中的噪声,所以用了这样糟糕的办法限制带宽来降低噪声 {:sweat:}至于是否有效,我刚买了一台动态分析仪准备测试这个问题,谁知道(动分)才到手第二天就挂了 {:cry:}

lilith 发表于 2013-1-25 23:47:43

marshallemon 发表于 2013-1-25 23:34 static/image/common/back.gif
电压跟随,也为了接容性负载稳定把

这个结构出现了几个地方,其中 2400 的 Vin/Ref in 是这样的缘故,因为它们都是开关电容输入(用动分或示波器以很低频率很大增益和动态范围能看到这个抖动),需要一个驱动(这个电路在 2440 手册上也有);但在两个 DAC 基准和最终电压输出 buff 上,只是为了降低噪声而已,不过是否有效还待测量,而杯具的是测量这个问题的动分给我挂掉了 {:funk:}

marshallemon 发表于 2013-1-25 23:51:28

lilith 发表于 2013-1-25 23:47 static/image/common/back.gif
这个结构出现了几个地方,其中 2400 的 Vin/Ref in 是这样的缘故,因为它们都是开关电容输入(用动分或示 ...

出套件不?我对你这个期待很久了

lilith 发表于 2013-1-25 23:53:37

PCBBOY1991 发表于 2013-1-25 21:09 static/image/common/back.gif
楼主您能给将一下你这个PCB在布线过程中单点接地以及地的问题能给讲一下吗?我做的两版数控电源都是因为单点 ...

25 楼的解释很好了,对于直流电压源类电路而言,单点接地其实就是考核每一个地线上的电流,把每一个地线视为一个电阻,看看这些电流在这个电阻上产生的压降有什么影响,比如反馈回路和电压参考回路,他们的地基准点应该是你的负载,如果你放到电源里边去,那肯定有问题;可是我们是没有办法把反馈回路和电压参考回路的地基准点丢到负载上的,因为负载通过引线和电源链接嘛,那么就要补偿这个引线上产生的电压降了。





在完善了接地布局之后,补偿导线上的压降的方法,可以参考一下 HP 662x 系列电源的手册,我找找看

lilith 发表于 2013-1-26 00:03:30

marshallemon 发表于 2013-1-25 23:51 static/image/common/back.gif
出套件不?我对你这个期待很久了

群里和好几个我经常厮混的论坛上都有很多人希望我能出套件,可是这里面有几个具体问题,

1、我没有那么多时间精力对付套件的问题,业余一点时间来嘀咕这个就很不够了,你看进度多慢 {:funk:}
2、最麻烦的就是,这个玩意如果没有校准是没有意义的,而校准它需要足够的仪器设备,因此实际上除非购买者有自己校准的能力,否则购买套件没有意义对吧。那么,也就是说我如果要发行它只能把它做成成品,调试、校准好才能出售,就好像本坛的 jj3055 那样,但这样对我的时间精力来说是做不到的。

这一次帮我绘制PCB 还在制作中提供了很多帮助的网友 TR 我曾经动员他发行套件或成品,不过他对此不是很有信心,这里面涉及到调试校准的步骤说实话比较烦人、主要是花时间,因此作为业余爱好自己嘀咕可能无所谓,否则就有点头疼了。jj3055 以前也通过阿莫兜售过他的 LTZ1000 基准,不过也是他自己焊接调试好并测试标定的,而且 LTZ1000 一般来说焊接好基本上没有太大问题需要调试,标定也只是很简单的事情;但我这个调试、校准是相对繁琐很多的事情 {:sweat:}

基本上我还是倾向于爱好者可以自制,反正源程序和电路原理图是完全公开的。当然有爱人士愿意发行套件我也是非常欢迎的事情 {:lol:}不过很显然的,发行者必须具有调试、校准它的能力对吧,也就是说至少需要可以观察(测试就算了)低频噪声的速度足够快的万用表(Agilent 3458 /Advantest 6581),以及校准线性的万用表(前面两者或其它 8 位半万用表)或相当仪器(KVD 也可以),以及校准准确度的电压基准设备(Fluke 732/734、4910 等)。

另外,网友 TR 不太乐意涉足套件的一个原因也是成本问题 {:sweat:}

lilith 发表于 2013-1-26 00:04:50

HYLG 发表于 2013-1-25 17:56 static/image/common/back.gif
显示屏是不是自己换的红色背光。

不是的唷,是买来就是这样的 {:lol:}

lilith 发表于 2013-1-26 00:07:48

kxm2008 发表于 2013-1-25 21:22 static/image/common/back.gif
看那个显示的初始化过程感觉像台pc机,很骚包

其实这个“初始化”其实是自检的过程本来没有的,我自己焊接好一块 PCB 调试的时候也很顺利,但网友 TR 焊接了几块 PCB,并把其中两块拿给我测试的时候,有一块不能正常工作,查了很久查不出原因,所以才写了这一大段用来自检的代码,发现了问题所在,又写了(今晚上)不少 Debug 代码,最终找到是一片 MAX515 有问题,其实这也是因为这些元器件全新购买非常昂贵(估计一两千、两三千软妹币可能需要),我用的几乎都是二手的拆机货,所以各种问题的缘故 {:curse:}

PCBBOY1991 发表于 2013-1-26 05:55:30

475627406 发表于 2013-1-25 23:10 虽然op177的Iib比084大,但在R21上应该还表现不出来 “无论设定多少电压,负载电流多大,输出压降就有1~ ...

除了那个R21其他的都符合运放虚短和虚短的理论,并且我把电阻改为2.7K后,两个运放输出和反向输入端也符合虚断了,然后测到的电压调整率很好了。我说的一到二毫伏是指在恒压模式下的空载与满载之间的电压降,也就是电压调整率。现在改电阻和把原来单点接地的问题用飞线解决后,精度已经很高了,这次真实积累了经验。电压采样我采用了远端补偿,这样以后电源采样点就可以在负载两端了,你可以参考下,对导线上的压降有很好的消除作用。

PCBBOY1991 发表于 2013-1-26 09:15:03

lilith 发表于 2013-1-26 00:07 其实这个“初始化”其实是自检的过程本来没有的,我自己焊接好一块 PCB 调试的时候也很顺利,但网友 TR ...

楼主你可以到美信那边去申请样片啊,我做的时候就是申请的

475627406 发表于 2013-1-26 09:28:56

PCBBOY1991 发表于 2013-1-26 05:55 static/image/common/back.gif
除了那个R21其他的都符合运放虚短和虚短的理论,并且我把电阻改为2.7K后,两个运放输出和反向输入端也符 ...

电压调整率 = 从满载到空载时主运放输出电压变化范围/主运放的开环增益
你看,“开尔文流量法”
远端补偿{:dizzy:} ,没那么深沉{:smile:}

475627406 发表于 2013-1-26 09:31:12

marshallemon 发表于 2013-1-25 23:34 static/image/common/back.gif
电压跟随,也为了接容性负载稳定把

http://www.amobbs.com/thread-5514313-1-1.html
问题是这个电路最终稳定了没有的问题{:lol:}

liu_shu 发表于 2013-1-26 09:39:09

楼主的显示屏是不是贴了一层纸啊?

475627406 发表于 2013-1-26 09:41:28

lilith 发表于 2013-1-25 23:45 static/image/common/back.gif
降低带宽来降低噪声?




在主要器件已经确定后,一个比较有效的方法就是降低带宽,同时增加的是电容,对直流性能不会有多大影响


你用的这个电路结构,带宽却没有降低

PCBBOY1991 发表于 2013-1-26 09:48:08

lilith 发表于 2013-1-25 23:53 25 楼的解释很好了,对于直流电压源类电路而言,单点接地其实就是考核每一个地线上的电流,把每一个地线 ...

单点接地的那个参考地我取的是AD,DA和电压基准的地,这些地线上的流过的电流很小,但是给运放供电,单片机和其他芯片工作电流流过的地是和这个分开的,这个我做的很好,我AD用的MX7705,带有差分输入端,很好。而电流检测的那个地(见原图)我没有接在基准,AD,DA的那个地,而是接在给运放供电的正负电源的地上,由于正负电源的到基准参考地之间导线上电流形成压降,对恒压恒流都有误差影响,当我把电流检测的地接在基准那边的参考地的时候,终于电流电压符合理论值了。

PCBBOY1991 发表于 2013-1-26 09:51:00

475627406 发表于 2013-1-26 09:28 电压调整率 = 从满载到空载时主运放输出电压变化范围/主运放的开环增益 你看,“开尔文流量法” 远端补偿 ...

在原理图上我懂,关键是PCB布线和单点接地的参考地的选择问题

475627406 发表于 2013-1-26 09:51:30

明年有时间了,我也搞个这种类型的东西耍下
打算用这种结构
http://cds.linear.com/docs/cn/design-note/dn400f%20chs.pdf

lilith 发表于 2013-1-26 11:08:43

475627406 发表于 2013-1-26 09:51 static/image/common/back.gif
明年有时间了,我也搞个这种类型的东西耍下
打算用这种结构
http://cds.linear.com/docs/cn/design-note/dn ...

是的,我用的就是这个结构呀,你这个图对带宽的抑制没我厉害 {:sweat:}

不过一个麻烦的地方是,并非这里只需要考虑直流性能,首先 LTC2400 一类 ADC 的 Vin、REF IN 是数十 KHZ 的一个开关电容输入,它对运放环路稳定性的影响需要考虑;其次,在自校准的时候,模拟开关(在本设计中)以大约 6-7HZ 速度切换,因此 ADC Vin 的跟随电路实际上的输入信号是一个幅度不确定,频率数 HZ 的信号,如果把电路带宽抑制到比数 HZ 更低,那显然也是不行的对吧 {:sweat:}   所以到底应该怎么取舍,我也在头疼。

如果电路不稳定,可以用动分观察到这个现象,杯具的是前几天它挂了 {:funk:}


Top -60dBV,Bottom -160dBV,10dBv/Div;Freq 大约 1.2HZ

475627406 发表于 2013-1-26 11:44:36

lilith 发表于 2013-1-26 11:08 static/image/common/back.gif
是的,我用的就是这个结构呀,你这个图对带宽的抑制没我厉害   

不过一个麻烦的地方是,并非这 ...

大体结构差相同,只是2449内部有模拟开关。

降低电路带宽主要是减小电路中产生的噪声吧
对于输入,用滤波来解决呀。只要让这个滤波电路不影响其他电路工作就行了

动分,好像以前的公司有,从来没摸过
测试一级电路的性能,一个古老而又简单的方法,输入级注入方波(50hz就行),示波器测输出就行了

hu_kai 发表于 2013-1-26 11:52:52

学习了,好东西。

475627406 发表于 2013-1-26 12:03:45



50hz方波(方波就表示里面有大量高次谐波)注入,输出平滑,稳定后值准确
如果前面的骨头都啃得动
那你的“一个幅度不确定,频率数 HZ 的信号”那不是小菜么{:lol:}

要果你要这样测试,最好把那些值钱的、易坏的东西拆了,你搞坏了我可不赔{:sleepy:}

PCBBOY1991 发表于 2013-1-26 12:33:26

硬件自检是什么原理呢楼主

lilith 发表于 2013-1-26 12:37:16

475627406 发表于 2013-1-26 12:03 static/image/common/back.gif
50hz方波(方波就表示里面有大量高次谐波)注入,输出平滑,稳定后值准确
如果前面的骨头都啃得动
那你的 ...

这个测过啦,我用 HP 3324A 产生的 7HZ(我的模拟开关切换频率大致是这么多)方波、正弦波、三角波、锯齿波都测试过的 {:lol:}不过动分挂了不好对比出入的畸变 {:cry:}

lilith 发表于 2013-1-26 12:40:19

475627406 发表于 2013-1-26 11:44 static/image/common/back.gif
大体结构差相同,只是2449内部有模拟开关。

降低电路带宽主要是减小电路中产生的噪声吧



降低电路带宽主要是减小电路中产生的噪声吧
对于输入,用滤波来解决呀。只要让这个滤波电路不影响其他电路工作就行了


不不不,我又不在乎速度,输入噪声就算比较大(其实 LTC2400 这颗 ADC 的本底噪声也挺大)也可以用数字滤波解决,我倒不是很在乎(相反你用滤波电路的话也要考虑响应速度的问题,因为这里的噪声频谱是 0.1HZ-10HZ,你可以想想电路的响应);关键是输出噪声,不是指 ADC 输出的 Code,这个数字滤波等着它呢,是说我这个东西本身就是要输出一个可指定的电压,而这个电压的噪声才是最糟糕的事情,因为这是很难解决的 {:cry:}

lilith 发表于 2013-1-26 13:04:44

PCBBOY1991 发表于 2013-1-26 12:33 static/image/common/back.gif
硬件自检是什么原理呢楼主

其实这个自检就是因为帮我完成这个设计的网友 TR 自己焊接的 PCB 送过来给我测试的时候发现不能工作,在排查不出问题的情况下我写了一些检测抹泥板那边一些受控器件是否正确工作的代码,具体说就是


1、启动 ADC,然后判断 ADC 读忙状态和周期,看看 ADC 有没有工作,有工作那么读忙周期就是 167ms
2、1 通过后,将模拟开关接地,判断 ADC 返回值是否为 0(有一定容差),目的是看模拟开关是否正确工作,ADC 是否正确响应输入电压
3、同 2,模拟开关接 7V 内基准,看返回值是否在一个约定的范围内
4、以上通过,开始测试 DAC,发送 0x0000,ADC 回读(此时也可以用外部万用表测试),看看 DAC 输出是否为 0V(有一定容差)
5、发送 0xff00,看是否为约定的值(有一定容差)
6、发送 0x0080 (检查副 DAC,它输出的电压是负值)看是否为约定的值(有一定容差)
7、发送 0x00ff(检查副 DAC,它输出的电压是负值)看是否为约定的值(有一定容差)

以上通过就认为没问题,如果有不通过的,进入 Debug 模式,Debug 模式循环以上步骤,且增加 0 步骤为抹泥板控制寄存器(HC4094)检查,步骤之间有几秒停顿,可以用万用表依次检查

PCBBOY1991 发表于 2013-1-26 13:29:28

lilith 发表于 2013-1-26 13:04 其实这个自检就是因为帮我完成这个设计的网友 TR 自己焊接的 PCB 送过来给我测试的时候发现不能工作,在 ...

OK,大概了解了

371278638 发表于 2013-1-26 14:59:29

学习....有机会一定要copy一下.......{:lol:}

tim 发表于 2013-1-26 15:15:08

屏很漂亮,楼主的界面布置得也很漂亮,能介绍下这屏吗?

泉过无痕 发表于 2013-1-26 16:19:56

谢谢楼主的分享。

airfex 发表于 2013-1-26 21:16:23

楼主的LCD屏也很漂亮

dreampet 发表于 2013-1-26 22:35:11

楼主能不能传个PDF版的原理图?图片版的放大后看不清了,对双DAC电压合成部分感兴趣。

wzavr 发表于 2013-1-26 22:44:19

lz有空麻烦将这次的原理图发个pdf,3楼发布的图没法看清楚.

工程师030 发表于 2013-1-26 22:52:42

楼主的LCD在哪里买的?看起来很像OLED啊!

lilith 发表于 2013-1-27 17:11:05

工程师030 发表于 2013-1-26 22:52 static/image/common/back.gif
楼主的LCD在哪里买的?看起来很像OLED啊!

楼上几位,这个屏只是一个普通的红色背光 TN LCD,可视角度也很窄的,只是在这个视角上看上去还行,稍微偏一点就看不见了,还不如这种没有背光的普通 LCD,你们要是去买了恐怕要把我骂死 {:funk:}

lilith 发表于 2013-1-27 17:12:41

wzavr 发表于 2013-1-26 22:44 static/image/common/back.gif
lz有空麻烦将这次的原理图发个pdf,3楼发布的图没法看清楚.

我用的绘制电路图软件无法导出 PDF {:sweat:}不知道为何 PNG 格式文件上传后会缩小,我打一个压缩包吧

工程师030 发表于 2013-1-27 17:18:26

lilith 发表于 2013-1-27 17:11 static/image/common/back.gif
楼上几位,这个屏只是一个普通的红色背光 TN LCD,可视角度也很窄的,只是在这个视角上看上去还行,稍微 ...

哈哈……楼主好心人啊!看出来了,还是不带背光的好!

lilith 发表于 2013-1-27 17:20:30

本帖最后由 lilith 于 2013-1-27 17:28 编辑

dreampet 发表于 2013-1-26 22:35 static/image/common/back.gif
楼主能不能传个PDF版的原理图?图片版的放大后看不清了,对双DAC电压合成部分感兴趣。 ...

不知道为何会缩小,我刚才发了一个压缩包你看看,另外我把 DAC 电压合成部分单独截上来了,其实就是把主 DAC 和副 DAC 的输出电压经过两个电阻进行叠加,这个应该很熟悉吧,运放(加法)上有说过的,Vo=V1*R2+V2*R1/(R1+R2),你可以看我的程序里 Setvoltage 函数就是根据这个公式写的。注意这个公式是根据电流导出的,也就是说输出缓冲运放的 Ib 会对 Vo 造成一定的影响,不过在这里,Vmaster 对应的合成电阻 Rmaster 很小(实际取值 249 欧),因此运放 Ib 的影响是不大的;而 Ib 受影响较大的 RSlave 对系统的贡献被弱化了 Rs/Rm = 4016 倍,所以耶可以认为没有什么影响。并且,由于本设计是数字闭环的,也就是说最终输出电压会被纠正到 ADC 上,因此整个电路 DAC 部分的误差,都不是很重要。


实际电路中由于买不到 4M 电阻,Rm 取值为 249 欧姆,Rs 为 1M,TCR=100ppm、精度为 1%。这两个电阻的具体阻值需要在程序中声明
Const fMResistance = 2.49E+02                              'DAC Voltgae Compound Resistance, the Master
Const fSResistance = 1E+06                                        'DAC Voltgae Compound Resistance, the Slave

SetVoltage 函数是根据这样的逻辑写的:
1、首先将 Vs(副 DAC 的 MAX515)预设为 -2.5V,然后求 Vm 的设定电压 Vm=/Rs
fVtrn = (fVtrn * (fMResistance + fSResistance) + fDACenter * fMResistance) / fSResistance   <---
2、得到 Vm 设置值,它只有 16bit 分辨率,所以结果肯定略高或略低于被要求的 Vo,那么将 Vm 重新带入公式,得到完整分辨率下的 Vs
fVtrn = 0 - ((fVset * (fMResistance + fSResistance) - fVtrn * fSResistance) / fMResistance)

副 DAC 输出的电压依然是正的,电路中有一个 -1 倍放大器将其转换为负压,所以程序重要予以注意。这样就在硬件和软件上完成了两个电压的合成。


bbsview 发表于 2013-1-27 18:10:11

屏幕显示够骚,哈哈

PCBBOY1991 发表于 2013-1-27 19:22:41

楼主求惠普E66系列的电源手册啊

Xplain 发表于 2013-1-27 20:57:05

不错,{:smile:}

jacktau 发表于 2013-1-27 21:07:41

楼主太牛了,膜拜一下~~~~~~~~~~~

gamalot 发表于 2013-1-27 21:34:38

你运气真好啊,这么多钽电容都没事,前些天俺的板子炸得那叫一个欢快,眼镜都给烧了几个小点点!

{:lol:}

wzavr 发表于 2013-1-27 22:39:26

lilith 发表于 2013-1-27 17:12 static/image/common/back.gif
我用的绘制电路图软件无法导出 PDF   不知道为何 PNG 格式文件上传后会缩小,我打一个压缩包吧
...

如果装一个pdf模拟打印的驱动,只要软件支持打印输出的,就可以制作成pdf文件,不需要软件中有特意的一项pdf输出功能.

gxluozhi 发表于 2013-1-28 17:01:33

前面交流为什么不加个滤波器呢?作为仪表,加了会更好!{:lol:}

fsclub 发表于 2013-1-28 21:33:50

支持出散件套装!标定自己想办法,或者找JJ3055收费成批校准。。

lilith 发表于 2013-1-28 23:48:26

gxluozhi 发表于 2013-1-28 17:01 static/image/common/back.gif
前面交流为什么不加个滤波器呢?作为仪表,加了会更好!

您看到的是没装壳、制作调试中的裸板,装壳进行完成调试的时候,就有装这个电源滤波器啦 {:lol:}



lilith 发表于 2013-1-28 23:57:52

fsclub 发表于 2013-1-28 21:33 static/image/common/back.gif
支持出散件套装!标定自己想办法,或者找JJ3055收费成批校准。。

关于这个问题我和帮我做 PCB 的网友 TR 谈过,他表示提供 PCB 倒是没啥问题,套件这个是比较花精力的,我们都倾向于交给专业为爱好者提供各种套件服务的商家来做这个,具体怎么样我和他,还有一些淘宝上的 JS 们慢慢谈吧,或者坛里也有哪些 JS 愿意掺一脚?我很乐意,并且对于能自制并调试好的我可以在一定程度*上提供免费的校准(调试的功夫我就实在是抽不出来了),因为我也有兴趣收集我这个设计的可靠性样本 {:lol:}考虑到原材料成本和调试的精力,我想自己制作出足够样本数的样机显然不如让大家来做现实 {:shy:}


lilith 发表于 2013-1-29 00:02:26

wzavr 发表于 2013-1-27 22:39 static/image/common/back.gif
如果装一个pdf模拟打印的驱动,只要软件支持打印输出的,就可以制作成pdf文件,不需要软件中有特意的一项pdf ...

这样出来的图是黑白的,看起来挺费劲呢,我还是传上来吧

lilith 发表于 2013-1-29 00:06:46

PCBBOY1991 发表于 2013-1-27 19:22 static/image/common/back.gif
楼主求惠普E66系列的电源手册啊

E66?安捷伦现在不给下载了吗,对了 E66 是啥 {:funk:}

wzavr 发表于 2013-1-29 12:30:35

lilith 发表于 2013-1-29 00:02 static/image/common/back.gif
这样出来的图是黑白的,看起来挺费劲呢,我还是传上来吧

哈哈,转换的结果有点奇怪,很多都黑白了,但是那几条粗线还是可以显示绿色的,
不过这样的pdf非常清晰,即使放大很多.
谢谢你.

dory_m 发表于 2013-1-29 14:05:29

学习,谢谢!!!

GIKE 发表于 2013-1-29 21:22:13

看着楼主的资料,热泪盈眶。。。

SNOOKER 发表于 2013-1-29 21:31:10

显示屏是亮点

maxims 发表于 2013-1-29 21:59:40

{:3_46:}必须mark学习


PS:论坛为什么没有搜索某一个人所有发言的功能呢?

PCBBOY1991 发表于 2013-1-30 12:12:24

lilith 发表于 2013-1-29 00:06 E66?安捷伦现在不给下载了吗,对了 E66 是啥

不是您在36楼说给传以下HP E66系列的手册么

bugplus 发表于 2013-1-30 13:00:03

此贴必火,楼主牛F(比牛B级别高几个数量级){:victory:}

麦可可 发表于 2013-2-1 12:01:31

看起来很漂亮 干净利落

lieklieke 发表于 2013-2-1 15:14:13

牛人啊真是牛人

sync765 发表于 2013-2-4 10:53:29

一定收藏了

dudududu 发表于 2013-6-25 10:40:24

请教一下楼主,LM399的输出电压变化范围有多大,我看datasheet上面是在6.75~7.3V之间,我看到你的基准电路里面,全部用的是固定电阻,难道说所使用到的LM399输出电压都是7.000V么??

lilith 发表于 2013-6-25 18:55:20

dudududu 发表于 2013-6-25 10:40 static/image/common/back.gif
请教一下楼主,LM399的输出电压变化范围有多大,我看datasheet上面是在6.75~7.3V之间,我看到你的基准电路 ...

我想你问的是“LM399 电压分布范围”而不是“变化范围”。根据一些朋友的数据统计和我自己的统计,年份较早的 LM399 电压分布在 6.8V 附近,年份较新的在 7V 附近分布(2011-2012 年份)。你可以看一下我目前的几台样机的观测:
http://bbs.38hot.net/forum.php?mod=viewthread&tid=41988

里面有几个 399 的电压数据,最小的大约 7.012V,最大的 7.042V。

至于为何我的设计中没有可调电阻,因为我是设计为闭壳校准的,由单片机运算介入校准,自然不需要任何可调元件。同时,可调电阻的温度系数普遍很大,稳定性也不好,使用可调电阻要实现我的预设目标也是很难的。从上个世纪八十年代开始,仪表就普遍采用没有任何可调元件,完全依靠单片机内程序进行闭壳校准的高可靠方式设计了。

dudududu 发表于 2013-6-28 08:27:47

哦,了解了,我手里40个LM399,分布电压从7.025V开始到7.088V的都有,不用可调电阻的话,也就意味着每一台电压源,在程序上设置的参数都不一样了,是么?

mruio 发表于 2013-6-28 10:09:21

楼主强啊,又是网站一大力作。

tang0571 发表于 2015-3-9 15:23:54

有营养的帖子要顶!!mark

为我所控 发表于 2015-6-13 09:57:41

来学习的,都是牛人啊,

RAMILE 发表于 2016-7-16 12:59:48

有营养的帖子要顶!!mark

qiaozejun 发表于 2017-12-13 19:08:30

lilith 发表于 2013-1-25 23:53
25 楼的解释很好了,对于直流电压源类电路而言,单点接地其实就是考核每一个地线上的电流,把每一个地线 ...

求联系方式

开始 发表于 2019-5-7 10:26:36

学习学习谢谢楼主资料
页: [1]
查看完整版本: 也算是电源吧-续:上来亮骚一下最近做的样机