本版源程序如下
'///////////////////////////////////////////////////////////////////////////////////////////////////
'Voltage Generator
'By Lilith Washu
'///////////////////////////////////////////////////////////////////////////////////////////////////
$Device= m16 ' 使用的单片机名称
$Stack = 32
$Clock = 7.3728 ' 使用的单片机主频
$ShiftIn Data=PORTA.6, Clock=PORTA.7, Msb
$LeadChar="0", Format(2,6)
$Baud = 1200,n,8,1
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Constant
'///////////////////////////////////////////////////////////////////////////////////////////////////
Const fDACReference = 2.500000E+06
Const fDACGain = 5.000000E+06
Const fMResistance = 6499
Const fSResistance = 1006250
Const Reference = &b00000100 ' Analog Switch = Internal Reference(LM399) | DG412 Pin 1
Const ExternaIN = &b00000010 ' Analog Switch = Externa Voltage Input | DG412 Pin 16
Const GndOffset = &b00001000 ' Analog Switch = Auto Zero | DG412 Pin 8
Const Synthesis = &b00000001 ' Analog Switch = Synthesis Voltage Output | DG412 Pin 9
'///////////////////////////////////////////////////////////////////////////////////////////////////
' String Variables
'///////////////////////////////////////////////////////////////////////////////////////////////////
Dim Ft1 As Flash Byte ' 软字体码表
Dim Charat As String *33' 要显示的字符缓冲区
Dim tTxt As String *15
Dim tm As String *7
Dim tCmd As String *4
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Gen Variables
'///////////////////////////////////////////////////////////////////////////////////////////////////
Dim i As Byte
Dim bUartset 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 itm As Byte
Dim baCalChannel As Bit
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 bREGas(33) As Byte
Dim bREGbs(33) As Byte
Dim bREGcs(33) As Byte
Dim bREGds(33) As Byte
Dim bREGar(33) As Byte
Dim bREGbr(33) As Byte
Dim bREGcr(33) As Byte
Dim bREGdr(33) As Byte
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Float Variables
'///////////////////////////////////////////////////////////////////////////////////////////////////
Dim fTrn As Float
Dim fOut As Float
Dim fReference As Float
Dim fSynthesis As Float
Dim fCalsacles As Float
Dim fCalfSynth As Float
Dim fDacal As Float
Dim fSetting As Float
Dim fVoltage As Float
Dim fError As Float
Dim fVset As Float
Dim fVtrn 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 字符
'///////////////////////////////////////////////////////////////////////////////////////////////////
' IO Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
Declare Function WriteSReg(bDat As Byte) As Byte
Declare Function WriteDAC(bDatH As Byte, bDatL As Byte, bDAChannel As Byte) As Byte
Declare Function SetChannel(Channel As Byte) As Byte
'Declare Function GetADC() As Float
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Mathematical Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
Declare Function SetVoltage(fVoltage As Float) As Byte
Declare Function Getinlerr(fVoltage As Float) As Word
'///////////////////////////////////////////////////////////////////////////////////////////////////
' UART Interrupt
'///////////////////////////////////////////////////////////////////////////////////////////////////
Declare Interrupt Urxc()
Enable Interrupts
Enable Urxc
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Init Variables,IO,Register
'///////////////////////////////////////////////////////////////////////////////////////////////////
DDRB = &b11111111 ' Link to Analog Board
' PB0 = Reg_Dat
' PB1 = Reg_CLK
' PB2 = Reg_STB
' PB3 = MAX541 SDI
' PB4 = MAX541 SCK
' PB5 = Unused
' PB6 = Unused
' PB7 = Unused
' PA6 = 2400 SDO/Input
' PA7 = 2400 SCK
'bSregister = &b01100000 ' Init Shift Register, All Switch OPEN; ADC Chipset = 0(Work); All DAC Chipset = 1(Lock)
'WriteSReg(bSregister)
DDRA = &b10111111 ' 显示屏的控制端接在 PortA,因此设置几个端口为输出
DDRC = &b11111111 ' 显示屏的数据总线接在 PortC,设置整个 PortC 为输出
' En 接在 PA0
' RW 接在 PA1
' DI 接在 PA2
' C1 接在 PA3
' C2 接在 PA4
' RSTb to PA5
' PA6 = 2400 SDO/Input
' PA7 = 2400 SCK
PORTA = &b00000000
PORTB = &b00011011
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Init Program
'///////////////////////////////////////////////////////////////////////////////////////////////////
InitKS() ' 初始化显示屏
ClsKS(0) ' 清屏
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Intest Prg
'///////////////////////////////////////////////////////////////////////////////////////////////////
' LCD Test and Init Display Charat
Charat = "Voltgen Init..."
DrawChr(1,0)
Wait 1
ClsKS(0)
Charat = "SET:"
DrawChr(1,0)
Charat = "Red:"
DrawChr(1,1)
Charat = "Adj:"
DrawChr(1,6)
Charat = "Err:"
DrawChr(112,1)
Charat = "uV"
DrawChr(173,1)
Charat = "Run:"
DrawChr(132,6)
' Init Shift Register(HC4094)
bSregister = &b01100000
WriteSReg(bSregister)
' Init the DAC Output Default
fSetting = 9900000
fVoltage = fSetting
stt:
fDacal = 1005809 / 1000000
fVoltage = fVoltage / fDacal
SetVoltage(fVoltage)
iSmlen = 16
fReference = 0
fSynthesis = 0
fCalsacles = 7033085 'ADC Reference Setting
For i = 0 To 33
bREGas(i) = 0
bREGbs(i) = 0
bREGcs(i) = 0
bREGds(i) = 0
bREGar(i) = 0
bREGbr(i) = 0
bREGcr(i) = 0
bREGdr(i) = 0
Next i
Format(2,6)
fTrn = fSetting / 1000000
Charat = Str(fTrn)
DrawChr(25,0)
itm = 0
iSmsetp = 0
'///////////////////////////////////////////////////////////////////////////////////////////////////
' Intest End
'///////////////////////////////////////////////////////////////////////////////////////////////////
Do
iSmsetp = iSmsetp + 1
If iSmsetp > 34 Then iSmsetp = 34
iBusystp = 0
Do
iBusystp = iBusystp + 1
WaitMs 1
Loop While PINA.6 = 1
Charat = Hex(iSmsetp)
DrawChr(156,6)
Charat = "/22"
DrawChr(169,6)
baCalChannel = Not baCalChannel
If baCalChannel = 1 Then
CurrentChannel = SetChannel(Reference)
Else
CurrentChannel = SetChannel(Synthesis)
End If
WaitMs 10
iDa = ShiftIn
iDb = ShiftIn
iDc = ShiftIn
iDd = ShiftIn
iDd = iDd And &b11110000
iDd = Swap(iDd)
iTrd = iDc And &b00001111
iTrd = Swap(iTrd)
iTd = iDd + iTrd
iTrd = iDc And &b11110000
iTc = Swap(iTrd)
iTrd = iDb And &b00001111
iTrd = Swap(iTrd)
iTc = iTrd + iTc
iTrd = iDb And &b11110000
iTb = Swap(iTrd)
iTrd = iDa And &b00001111
iTrd = Swap(iTrd)
iTb = iTrd + iTb
iTrd = iDa And &b00110000
iTa = Swap(iTrd)
fTrn = 5 * (16777216 * iTa + 65536 * iTb + 256 * iTc + iTd - 33554432) / 16777216
If baCalChannel = 1 Then
For i = 1 To iSmlen
bREGds(i) = bREGds(i + 1)
bREGcs(i) = bREGcs(i + 1)
bREGbs(i) = bREGbs(i + 1)
bREGas(i) = bREGas(i + 1)
Next i
bREGds(iSmlen) = iTd
bREGcs(iSmlen) = iTc
bREGbs(iSmlen) = iTb
bREGas(iSmlen) = iTa
fTrn = 0
fOut = 0
For i = 1 To iSmlen
iTa = bREGas(i)
iTb = bREGbs(i)
iTc = bREGcs(i)
iTd = bREGds(i)
fTrn = 5 * (16777216 * iTa + 65536 * iTb + 256 * iTc + iTd - 33554432) / 16777216
fOut = fOut + fTrn
Next i
fOut = fOut / iSmlen
fSynthesis = fOut
Else
For i = 1 To iSmlen
bREGdr(i) = bREGdr(i + 1)
bREGcr(i) = bREGcr(i + 1)
bREGbr(i) = bREGbr(i + 1)
bREGar(i) = bREGar(i + 1)
Next i
bREGdr(iSmlen) = iTd
bREGcr(iSmlen) = iTc
bREGbr(iSmlen) = iTb
bREGar(iSmlen) = iTa
fTrn = 0
fOut = 0
For i = 1 To iSmlen
iTa = bREGar(i)
iTb = bREGbr(i)
iTc = bREGcr(i)
iTd = bREGdr(i)
fTrn = 5 * (16777216 * iTa + 65536 * iTb + 256 * iTc + iTd - 33554432) / 16777216
fOut = fOut + fTrn
Next i
fOut = fOut / iSmlen
fReference = fOut
End If
fCalfSynth = fSynthesis / (fReference / fCalsacles)
fError = fSetting - fCalfSynth
'bAdjerr = fError
'bAdjerr = Abs(bAdjerr)
' Display the Readback Value
Format(2,6)
fTrn = fCalfSynth / 1000000
Charat = Str(fTrn)
DrawChr(25,1)
' Display the non-Adj Error Value
Format(3,1)
Charat = Str(fError)
DrawChr(136,1)
If iSmsetp = 33 Then
' Adj the Output Voltage
fVoltage = fVoltage + fError
Format(Scientific,6)
Charat = Str(fVoltage)
DrawChr(25,6)
SetVoltage(fVoltage)
iSmsetp = 0
End If
If bUartset = 1 Then
bUartset = 0
iSmsetp = 0
fVoltage = fSetting
fVoltage = fVoltage / fDacal
SetVoltage(fVoltage)
Format(2,6)
fTrn = fSetting / 1000000
Charat = Str(fTrn)
DrawChr(25,0)
End If
Loop
'///////////////////////////////////////////////////////////////////////////////////////////////////
'Screen Drive
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function SetKS(Code As Byte, Channel As Byte) As Byte ' 写指令函数
PORTC = Code
Select Case Channel ' PA3 和 PA4 组合决定使用屏的区域,19264 有三个 64x64 区域
Case 1 : PORTA.3 = 0 : PORTA.4 = 0
Case 2 : PORTA.3 = 1 : PORTA.4 = 0
Case 3 : PORTA.3 = 0 : PORTA.4 = 1
End Select
PORTA.1 = 0 ' 设置为写状态 (0=Write,1=Read)
PORTA.2 = 0 ' 设置为指令状态 (0=指令,1=数据)
PORTA.0 = 1 : WaitUs 1 : PORTA.0 = 0 : WaitUs 1 ' 在 En 的上升沿,指令或数据进入屏幕
Return 0
End Function
Function WriteKS(Code As Byte, Channel As Byte) As Byte ' 写指令函数
PORTC = Code
Select Case Channel
Case 1 : PORTA.3 = 0 : PORTA.4 = 0
Case 2 : PORTA.3 = 1 : PORTA.4 = 0
Case 3 : PORTA.3 = 0 : PORTA.4 = 1
End Select
PORTA.1 = 0
PORTA.2 = 1 ' 设置为数据状态 (0=指令,1=数据)
PORTA.0 = 1 : WaitUs 1 : PORTA.0 = 0 : WaitUs 1
Return 0
End Function
Function InitKS() As Byte
Local iC As Byte
ResetKS()
For iC = 1 To 3
SetKS(&hc0, iC) ' 向屏幕的三个控制 IC 写入初始化和开显示的指令
SetKS(&h3f, iC)
Next iC
Return 0
End Function
Function ResetKS() As Byte ' 给屏幕完成上电脉冲,可用一个硬件电路来完成
PORTA.5 = 0
WaitMs 200
PORTA.5 = 1
End Function
Function ClsKS(GRAM As Byte) As Byte ' 清屏函数,给整个屏幕清除显示
Local iP As Byte
Local iQ As Byte
Local iC As Byte
For iC = 1 To 3
For iP = 0 To 7
For iQ = 0 To 63
SetKS(&hB8 + iP, iC) ' 设置显存开始写数据的页地址
SetKS(&h40 + iQ, iC) ' 设置显存开始写数据的行地址
WriteKS(GRAM, iC) ' 写入一个 8bit 的显存数据
Next iQ
Next iP
Next iC
Return 0
End Function
Function DrawPix(x As Byte, y As Byte) As Byte ' 在屏幕上绘制一个点
Local xAdd As Byte
Local xChip As Byte
Local yAdd As Byte
Local yCode As Byte
Local yPage As Byte
Local iStep As Byte
yCode = 1
xChip = ((x-1)/64)+1 ' 因为屏幕是3个 64pix 区域,所以需要根据横坐标决定实际上位于哪个控制 IC 的显存的行地址
xAdd = x mod 64
If xAdd = 0 Then
xAdd = 63
Else
xAdd = xAdd - 1
End If
yPage = (y-1)/8 ' KS0108 的纵坐标是 8 页每页 8 个点,据此找到页地址
yAdd = y mod 8
If yAdd = 0 Then yAdd = 8
For iStep = 1 To yAdd - 1
yCode = yCode * 2
Next iStep
If yAdd = 1 Then yCode = 1
SetKS(&hB8 + yPage, xChip) ' 设置显存开始写数据的页地址
SetKS(&h40 + xAdd, xChip) ' 设置显存开始写数据的行地址
WriteKS(yCode, xChip)
Return 0
End Function
Function DrawPage(x As Byte, Page As Byte, Code As Byte) As Byte
Local xAdd As Byte ' 显存一次写入整页的函数
Local xChip As Byte
xChip = ((x-1)/64)+1
xAdd = x mod 64
If xAdd = 0 Then
xAdd = 63
Else
xAdd = xAdd - 1
End If
SetKS(&hB8 + Page, xChip)
SetKS(&h40 + xAdd, xChip)
WriteKS(Code, xChip)
Return 0
End Function
Function DrawChr(x As Byte, Page As Byte) As Byte ' 显示一行字符,必须是码表中存在的标准 ASCII 字符
Local is As Byte
Local iLs As Byte
Local iFn As Byte
Local iChn As Byte
Local bChr As Byte
Local xAdd As Byte
xAdd = 0
iLs = Len(Charat)
For is = 1 To iLs
bChr = Asc(Mid(Charat,is,1)) - 32 ' 根据每一个字符的 ASCII 马,在码表数组中找到对应的数据,一个字符是 5x8 点的 5 个 Byte 数据
For iFn = 0 To 4
iChn = Ft1(bChr * 5 + iFn)
DrawPage(x+xAdd,Page,iChn) ' 将每一个字符对应的这 5 个 Byte 写到显存
xAdd = xAdd + 1
Next iFn
xAdd = xAdd + 1
Next is
Return 0
End Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
'Shiftreg IO
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function WriteSReg(bDat As Byte) As Byte
' PB0 = Reg_Dat
' PB1 = Reg_CLK
' PB2 = Reg_STB, INV
Local bWritedat As Byte
Local bWritebit As Byte
bWritedat = bDat
PORTB.0 = 0
PORTB.1 = 0
PORTB.2 = 0
WaitUs 1
For i = 1 To 8
bWritebit = bWritedat And &b10000000
If bWritebit = 128 Then
PORTB.0 = 1
Else
PORTB.0 = 0
End If
WaitUs 1
PORTB.1 = 1 : WaitUs 1 : PORTB.1 = 0
bWritedat = Shift(Left, 1, bWritedat)
Next i
WaitUs 1
PORTB.2 = 1 : WaitUs 1 : PORTB.2 = 0
PORTB.0 = 0
PORTB.1 = 0
Return 0
End Function
Function WriteDAC(bDatH As Byte, bDatL As Byte, bDAChannel As Byte) As Byte
' PB3 = MAX541 SDI
' PB4 = MAX541 SCK
Local bReg1 As Byte
Local bReg2 As Byte
Local bWritedat As Byte
Local bWritebit As Byte
PORTB.3 = 0
PORTB.4 = 0
' Setting DAC Chipset Pin by Shift Register(74HC4094)
Select Case bDAChannel
Case 1 'Master DAC Chipset Enable
bReg1 = bSregister And &b11011111
bReg2 = bSregister Or &b00100000
Case 2 'Slave DAC Chipset Enable
bReg1 = bSregister And &b10111111
bReg2 = bSregister Or &b01000000
End Select
' Write Serial H&L 16bit Data to DAC Register
WriteSReg(bReg1)
bWritedat = bDatH
For i = 1 To 8
bWritebit = bWritedat And &b10000000
If bWritebit = 128 Then
PORTB.3 = 1
Else
PORTB.3 = 0
End If
WaitUs 1
PORTB.4 = 1 : WaitUs 1 : PORTB.4 = 0
bWritedat = Shift(Left, 1, bWritedat)
Next i
WaitUs 1
bWritedat = bDatL
For i = 1 To 8
bWritebit = bWritedat And &b10000000
If bWritebit = 128 Then
PORTB.3 = 1
Else
PORTB.3 = 0
End If
WaitUs 1
PORTB.4 = 1 : WaitUs 1 : PORTB.4 = 0
bWritedat = Shift(Left, 1, bWritedat)
Next i
WaitUs 1
' Update the DAC
WriteSReg(bReg2)
PORTB.3 = 1
PORTB.4 = 1
Return 0
End Function
Function SetChannel(Channel As Byte) As Byte 'Setting the Analog Switch(ADC Input Channel)
Local Channelset As Byte
Channelset = bSregister And &b11110000
bSregister = Channelset + Channel
WriteSReg(bSregister)
Return bSregister
End Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
'Mathematical Function
'///////////////////////////////////////////////////////////////////////////////////////////////////
Function SetVoltage(fVoltage As Float) As Byte
Local Vsetm As Word ' The Master DAC Setting Return
Local Vsets As Word ' The Slave DAC Setting Return
Local bMSB As Byte
Local bLSB As Byte
' the addsch VOut = Gain * (Vmaster * R2 + Vslave * R1) / (R1+R2), Fullscale of the Vm and Vs all = 2.5V, R1 = 470 ohm, R2 = 1M ohm, Gain = 5
fVtrn = fVoltage
fVtrn = fVtrn / fDACGain
fVset = fVtrn
' Get the MasteDAC Voltage Setting Value, Vm=Vo*(R1+R2)/R2
fVtrn = fVtrn * (fMResistance + fSResistance) / fSResistance
fVtrn = fVtrn * 65535 * 1000000 / fDACReference
Vsetm = fVtrn
bMSB = Msb(Vsetm)
bLSB = Vsetm - bMSB * 256
WriteDAC(bMSB,bLSB,1)
' Get the SlaveDAC Voltage Setting Value,Vs=[Vo*(R1+R2)-Vm*R2]/R1
fVtrn = Vsetm * fDACReference / 65535 / 1000000
fVtrn = (fVset * (fMResistance + fSResistance) - fVtrn * fSResistance) / fMResistance
fVtrn = fVtrn * 65535 * 1000000 / fDACReference
Vsets = fVtrn
bMSB = Msb(Vsets)
bLSB = Vsets - bMSB * 256
WriteDAC(bMSB,bLSB,2)
Return 0
End Function
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
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)
fSetting = uVseth
fSetting = fSetting * 10000
fSetting = fSetting + uVsetl
bUartset = 1
End If
Enable Interrupts
End Interrupt
$Include ".\\font1.bas" |