#define TDIRP3DIR //2.7-5.5V低功耗双12位,带掉电D/A转换器
#define CS_LP3OUT &=~BIT0
#define CS_HP3OUT |= BIT0
#define SCLK_H P3OUT |= BIT1
#define SCLK_L P3OUT &=~BIT1
#define DIN_H P3OUT |= BIT2
#define DIN_L P3OUT &=~BIT2
/*******TLV5618转换程序*********/
void func(uint temp,uint contr) //编程位 R1SPD PWR R0
{ //寄存器选择位R1 R0
uchar i // 0 0 写数据到DACB和BUFFER
uint aa // 0 1 写数据到BUFFER
aa=temp | contr // 1 0 写数据到DACA和用BUFFER内容更新DACB
SCLK_H
CS_L //SPD 速度控制位 SPD=1高速,SPD=0低速
//发送16位数据
for(i=0i<16i++) //喊悄简PWR 电源控制位 PWR=1掉电,PWR=0正常 *** 作
{ //上运轿电时SPD=0,PWR=0(低速模式、正常 *** 作)
if(aa &0x8000) DIN_H //contr=0x8000 选择A通道,contr=0x0000选择B通道
else DIN_L
aa=aa<<1
SCLK_L
_NOP()
SCLK_H
_NOP()
}
CS_H
return
}
func(Ampn<<1,0x8000)
我从程序直接复制过来的,参考参考吧!!!很清晰郑裤。
PID调节器主控部分包括以下几个部分:单锋斗片机部分、A/D转换部分、D/A转换部分、稳压部分、数字输入输出部分以及串口通信部分。D1:内部设定点信号灯
S1:内部设定点和外部设定点转换开关
D2:手动信号灯
S2:手动自动转换开关
D3:实际值X显示信号灯
D4:设定值W显示信号灯
S3:参数修改以及实际值和设定值显示转换开关
D5:超过限定值信并贺号灯
D6:低于限定值信号灯
S4:设定值增加按钮
S5:设定值减少按钮
S6:修改手动变量按钮
S7:修改手动变量按钮
附录[1] 主程序—MAIN.C
#include"adconver.h"
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey0.h"
#include"subkey1.h"
#include"subkey2.h"
#include"subkey3.h"
#include"subkey4.h"
#include"subkey5.h"
#include"subkey6.h"
bit insertsetframe=1//内部设定标志位
bit handframe=1//手动设定标志位
bit improvedisframe=0//实际值标志位
bit shineframe=0//判断是不是第一次开机停止4LED的闪烁
bit canshuframe=0x00//参数标志位
unsigned char circleframe=0x00//参数循环变量
unsigned char channelframe=0x00//通道标志位
unsigned char ledframe=0xfc//LED灯管状态
unsigned char times=0x00//记数位
unsigned char readkey
unsigned int setvalue=0x00//设定值
unsigned char outputvalue=0x00//输出值
unsigned int limup=0x270f//实际值上限
unsigned int limdown=0x00//实际值下限
unsigned int a1=0x270f//上限报警值
unsigned int a2=0x00//下限报警值
unsigned int cp=0x00//P参数
unsigned int ci=0x00//I参数
unsigned int cd=0x00//D参数
unsigned char led[6]//LED值公共
main()
{
unsigned int tmr
unsigned char keynumber
for (tmr=0tmr<0xfffftmr++)
write7281(0x12,0x80)
write7281(0x10,0xf0)
write7281(0x00,0xc8)
write7281(0x14,0x1b)
write7281(0x14,0x2e)
write7281(0x15,0x30)
write7281(0x15,0x40)
write7281(0x15,0x50)
write7281(0x06,0xfc)
while(1)
{
while(!key)
{
keynumber=read7281(0x13)
switch(keynumber)
{
case 0x00:
subkey0()break
case 0x01:
subkey1()break
case 0x02:
subkey2()break
case 0x03:
subkey3()break
case 0x04:
subkey4()break
case 0x05:
subkey5()break
case 0x06:
subkey6()break
default:
break
}
}
}
}
附录绝基派[2] S1模块的程序—SUBKEY0.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey0.h"
void subkey0()
{
if(insertsetframe==1)
{
insertsetframe=0
ledframe|=0x01
write7281(0x06,ledframe)
}
else
{
insertsetframe=1
ledframe&=0xfe
write7281(0x06,ledframe)
}
}//更改内部设定和外部设定的状态,并将相应的状态位进行更改,并更改状态灯
附录[3] S2模块的程序—SUBKEY1.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey1.h"
void subkey1()
{
if(handframe==1)
{
handframe=0
ledframe|=0x02
write7281(0x06,ledframe)
}
else
{
handframe=1
ledframe&=0xfd
write7281(0x06,ledframe)
}
} //更改手动自动状态,改变相应的状态位,更改相应的状态灯
附录[4] S3模块的程序—SUBKEY2.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey2.h"
#include"adconver.h"
#include"subkey0.h"
#include"subkey1.h"
#include"hdconver.h"
#include"subkey3.h"
#include"subkey4.h"
#include"pid.h"
#include"daconver.h"
void subkey2()
{
if(shineframe==0)
{
write7281(0x10,0xff)
shineframe=1
}
else
{
skey2()
}
}
void skey2(void)
{ // canshuframe=1
write7281(0x18,0x17)
switch(circleframe)
{
case 0x00: ledframe|=0x0c
write7281(0x06,ledframe)
circleframe+=1
hdconver(limup)//4LED显示上限值
dis4led()
write7281(0x14,0x41)
write7281(0x14,0x5C)//写入2LEDHI
break
case 0x01: circleframe+=1
hdconver(limdown)//4LED显示下限值
dis4led()
write7281(0x14,0x40)
write7281(0x14,0x5d)//写入2LEDLO
break
case 0x02: circleframe+=1
hdconver(a1)//4LED显示上限报警
dis4led()
write7281(0x14,0x41)
write7281(0x15,0x5a)//写入2LEDA1
break
case 0x03: circleframe+=1
hdconver(a2)//4LED显示下限报警
dis4led()
write7281(0x14,0x42)
write7281(0x15,0x5a)//写入2LEDA2
break
case 0x04: circleframe+=1
hdconver(cp)//4LED显示P参数
dis4led()
write7281(0x14,0x4e)
write7281(0x14,0x5f)//写入2LEDP
break
case 0x05: circleframe+=1
hdconver(ci)//4LED显示I参数
dis4led()
write7281(0x14,0x41)
write7281(0x14,0x5f)//写入2LEDI
break
case 0x06: circleframe+=1
hdconver(cd)//4LED显示D参数
dis4led()
write7281(0x15,0x4d)
write7281(0x14,0x5f)//写入2LEDI
break
case 0x07: improvedisframe=0
ledframe=(ledframe|0x08)&0xfb
circleframe+=1
adconver()
write7281(0x14,0x40)
write7281(0x14,channelframe)
write7281(0x06,ledframe)
break
case 0x08: improvedisframe=1
ledframe=(ledframe|0x04)&0xf7
circleframe=0
pidcf()
daconver()
hdconver(setvalue)
dis4led()
write7281(0x06,ledframe)
break
default:
break
}
}//按相应的S3改变不同的参数
附录[5] S4模块的程序—SUBKEY3.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey3.h"
#include"subkey2.h"
#include"hdconver.h"
void subkey3()
{
switch(circleframe)
{
case 0x01:limup=add1(limup)
break
case 0x02:limdown=add1(limdown)
break
case 0x03:a1=add1(a1)
break
case 0x04:a2=add1(a2)
break
case 0x05:cp=add1(cp)
break
case 0x06:ci=add1(ci)
break
case 0x07:cd=add1(cd)
break
case 0x00:setvalue=add1(setvalue)
break
default:
break
}
}
unsigned int add1(unsigned int value)
{
ledframe|=0x20//关掉下限报警
write7281(0x06,ledframe)
if(value==9999)
{
ledframe&=0xef//打开上限报警灯
write7281(0x06,ledframe)
write7281(0x06,ledframe)
}
else
{
value+=1
}
hdconver(value)
dis4led()
return(value)
}
附录[6] S5模块的程序—SUBKEY4.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey4.h"
#include"subkey2.h"
#include"hdconver.h"
void subkey4()
{
switch(circleframe)
{
case 0x01:limup=sub1(limup)
break
case 0x02:limdown=sub1(limdown)
break
case 0x03:a1=sub1(a1)
break
case 0x04:a2=sub1(a2)
break
case 0x05:cp=sub1(cp)
break
case 0x06:ci=sub1(ci)
break
case 0x07:cd=sub1(cd)
break
case 0x00:setvalue=sub1(setvalue)
break
default:
break
}
}
unsigned int sub1(unsigned int value)
{
ledframe|=0x10//关掉上限报?
write7281(0x06,ledframe)
if(value==0)
{
ledframe&=0xdf//打开上限报警灯
write7281(0x06,ledframe)
}
else
{
value-=1
}
hdconver(value)
dis4led()
return(value)
}
附录[7] S6模块的程序—SUBKEY5.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey5.h"
#include"hdconver.h"
void subkey5()
{
if(improvedisframe==0)
{
channelframe=0x00
write7281(0x15,0x40)
write7281(0x15,0x50)//若现在状态为实际值,则改变通道状态并显示现在状态为00
}
else
{
if(handframe==1)
{
ledframe|=0x10//关掉上限报警灯
write7281(0x06,ledframe)
if(outputvalue==0x00)
{
ledframe&=0xdf//打开下限报警灯
write7281(0x06,ledframe)
}
else
{
outputvalue-=1
hdconver2(outputvalue)
}
dis2led()
}
}
}
附录[7] S7模块的程序—SUBKEY6.C
#include"delay.h"
#include"dis7281.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"subkey6.h"
#include"hdconver.h"
void subkey6()
{
if(improvedisframe==0)
{
channelframe=0x01
write7281(0x15,0x41)
write7281(0x15,0x50)//若现状态为实际值,则2LED显示为01
}
else
{
if(handframe==1)
{
ledframe|=0x20//关掉下限报警灯
write7281(0x06,ledframe)
if(outputvalue==99)
{
ledframe&=0xef//打开上限报警档?
write7281(0x06,ledframe)
}
else
{
outputvalue+=1
hdconver2(outputvalue)
}
}
dis2led()
}
}
附录[8] A/D转换模块的程序—ADCONVER.C
#include"STC12C5410AD.H"
#include"adconver.H"
#include"delay.h"
#include"main.h"
#include"dis7281.h"
#include"hdconver.h"
void adconver()
{ unsigned char adchanne=0xe0//设置P1的0.1位为AD输入通道
ADC_CONTR=(0x80|ADC_CONTR)+channelframe//开启AD模拟电源
delay(1000)
P1M0=0x03
P1M1=0x03//设置通道为开漏模式
ADC_CONTR=adchanne+channelframe//设置AD转换通道
delay(22)
ADC_DATA=0x00
ADC_LOW2=0x00//清除数据口
ADC_CONTR|=0x08//开启AD端口
while(!(ADC_CONTR&0x10)){}//等待AD转换完成
ADC_CONTR&=0xe7//停止AD转换
P1M0&=0xfd
P1M1&=0xfd//设置P1口为普通IO模式
addis()
}
void addis()
{
unsigned int addata
double liangch
liangch=(limup-limdown)/100
addata=ADC_DATA+(ADC_LOW2&0x03)*1024
liangch=liangch/1023*addata
addata=(unsigned int)liangch
if(addata>a1)
{
ledframe&=0xef//打开上限报警灯
write7281(0x06,ledframe)
}
if(addata<a2)
{
ledframe&=0xdf//打开上限报警灯
write7281(0x06,ledframe)
}
hdconver(addata)
dis4led()
}
附录[8] D/A转换模块的程序—DACONVER.C
#include"delay.h"
#include"STC12C5410AD.H"
#include"main.H"
#include"daconver.h"
sbit TLV5618_SCLK=P1^7
sbit TLV5618_DIN=P1^5
sbit TLV5618_CS=P1^4
void mDelay(unsigned int a)
{unsigned int f
for(f=0f<af++)
}
void TLV5618 (unsigned int da)
{
unsigned int i
unsigned int dat
dat= da|0xc000
TLV5618_CS=0
TLV5618_SCLK=0
for(i=0i<16i++)
{
TLV5618_DIN=(bit)(dat&0x8000)
dat=dat<<1
TLV5618_SCLK=1
mDelay(50)
TLV5618_SCLK=0
mDelay(50)
}
TLV5618_CS=1
}
void daconver(void)
{ float i=100
unsigned int da
i=outputvalue/100*4096
da=(unsigned int)i
TLV5618 (da)
}
附录[9]显示及键盘模块的程序—DIS7281.C
#include"delay.H"
#include"STC12C5410AD.H"
#include"dis7281.H"
#include"main.h"
void write7281(unsigned char regadd,unsigned char writedata)
{
sendbyte(regadd)
sendbyte(writedata)
}
void sendbyte(unsigned char sendbyte)
{
unsigned char bitcounter
clk=0
clk=1
do{
clk=0
clk=1
}while(dat)
clk=0
clk=1
while(!dat)
for(bitcounter=0bitcounter<8bitcounter++)
{
if ((sendbyte&0x80)==0)
{ dat=0}
else
{dat=1}
sendbyte=sendbyte*2
clk=0
clk=1
delay(1)
}
dat=1
delay(2)
}
unsigned char receivebyte(void)
{
unsigned char bit_counter
unsigned char in_byte
clk=0
clk=1 //只发送一个单元的脉冲
while(dat)//等待BC7281响应DAT底电平
clk=0
clk=1//受到响应,再发一脉冲等待接受数据
for (bit_counter=0bit_counter<8bit_counter++ ) //接受8个BIT
{
delay(1)
in_byte=in_byte*2 //in_byte左移一位
if(dat) //如果DAT为1
{
in_byte=in_byte|0x01//bit^0=1
}
clk=0
clk=1
}
delay(2)
clk=0
clk=1
return(in_byte)
}
unsigned char read7281(unsigned char reg_add)
{
sendbyte (0x80+reg_add) //发送读指令(BIT 7=1)
return (receivebyte()) //接受数据字节并返回
}
void dis4led()
{
unsigned char i
unsigned char id=0x00
for(i=0i<4i++)
{
write7281(0x14,id+led[i])
id+=0x10
}
}
void dis2led()
{
unsigned char i
unsigned char id=0x40
for(i=4i<6i++)
{
write7281(0x14,id+led[i])
id+=0x10
}
}
附录[10]PID算法模块的程序—PID.C
#include"adconver.h"
#include"STC12C5410AD.H"
#include"math.h"
#include"pid.h"
#include"hdconver.h"
#include"dis7281.h"
xdata struct _pid
{
int pv
int sp
float integral
float pgain
float igain
float dgain
int deadband
int last_error
}
xdata struct _pid warm,*pid
xdata int process_point,set_point,dead_band
xdata float p_gain,i_gain,d_gain,integral_val,new_integ
void pid_init(struct _pid *warm,int process_point,int set_point)
{
struct _pid *pid
pid=warm
pid->pv=process_point
pid->sp=set_point
}
void pid_tune(struct _pid *pid,float p_gain,float i_gain,float d_gain,int dead_band)
{
pid->pgain=p_gain
pid->igain=i_gain
pid->dgain=d_gain
pid->deadband=dead_band
pid->integral=integral_val
pid->last_error=0
}
void pid_setinteg(struct _pid *pid,float new_integ)
{
pid->integral=new_integ
pid->last_error=0
}
void pid_bumpless(struct _pid *pid)
{
pid->last_error=(pid->sp)-(pid->pv)
}
float pid_calc(struct _pid *pid)
{
int err
float pterm,dterm,result,ferror
err=(pid->sp)-(pid->pv)
if(abs(err)>pid->deadband)
{
ferror=(float)err
pterm=pid->pgain*ferror
if(pterm>100||pterm<-100)
{
pid->integral=0.0
}
else
{
pid->integral+=pid->igain*ferror
if(pid->integral>100.0)
{
pid->integral=100.0
}
else
{
if(pid->integral<0.0)
{
pid->integral=0.0
}
}
}
dterm=((float)(err-pid->last_error))*pid->dgain
result=pterm+pid->integral+dterm
}
else
{
result=pid->integral
}
pid->last_error=err
return(result)
}
void pidcf(void)
{
int count=0
float val=100
float p_gain=cp/val
float i_gain=ci/val
float d_gain=cd/val
// unsigned int dadata
pid=&warm
dead_band=2
integral_val=(float)(0.01)
while(count<=20)
{
process_point=(unsigned int)addata/val
set_point=(unsigned int)setvalue/val
pid_init(&warm,process_point,set_point)
pid_tune(&warm,p_gain,i_gain,d_gain,dead_band)
pid_setinteg(&warm,0.0)
pid_bumpless(&warm)
count++
}
outputvalue=(unsigned char)pid_calc(&warm)
hdconver2(outputvalue)
dis4led()
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)