📄 c1.c
字号:
#include "hardware.h"
#include "SPCE061V004.h"
#include "unSPMACRO.h"
#include "math.h"
#define initialb 0xff0f
#define initiala 0xfffe
#define P_ADC_MUX_Ctrl (volatile unsigned int *)(0x702B)
//#define P_ADC_Ctrl (volatile unsigned int *)(0x7015)
#define P_ADC_MUX_Data (volatile unsigned int *)(0x702C)
//#define *P_ADC_MUX_Ctrl 0x702b
//#define *P_ADC_MUX_Data 0x702c
//void init();
//描述水温的各个参量
unsigned int temperature; //当前水的温度
unsigned int settemperature; //设定的水温
int integral; //稳态时一段时间的温度偏差积累
int pgain; //比例调整的比例系数
int igain; //积分系数
int dgain; //微分系数
int deadband; //决定是只进行比例调整还是PID综合调整的界限(当前水温和设定水温的差值)
int last_error;//上次调节后实际温度与设定温度的差值
int tag,tag1,tag2,tag3,tag4;
int reg;//控制波形翻转
int key1,key2,key3,key4,key5,key6,key7,key8,key9,key10,key11,key12,key13,key14,key15,key16;//各个按键的确认变量
int change;//调整占空比的变量
int err;
int delay;
int ave;
unsigned int temperature1;
int show_time,show_what;
int second,minute,hour;
int time_temp;
int slow;
void initial()//初始化IO口以及各个参量值
{
//_init();
*P_IOA_Dir=initiala; //设置A,B口的属性
*P_IOA_Attrib=0xffff;
*P_IOA_Data=0x0000;
*P_IOB_Dir=initialb;
*P_IOB_Attrib=initialb;
*P_IOB_Data=0x0000;
tag3=*P_IOB_Attrib;
key1=key2=key3=key4=key5=key6=key7=key8=key9=key10=key11=key12=key13=key14=key15=key16=0;//按键检测变量初始化
reg=0; //频率控制量初始化
*P_INT_Ctrl=0x0010;//设置中断
asm("IRQ ON");
integral=0;//PID算法的个变量初始化
pgain=13;
igain=5;
dgain=4;
last_error=0;
tag=0;
//*P_DAC_Ctrl=0x0000;
//asm("[P_ADC_MUX_Ctrl]=%0"::"r"(0x0001));
*P_ADC_MUX_Ctrl=0x0007;//设置IOA6为模拟信号输入
tag1=*P_ADC_MUX_Ctrl;
*P_ADC_Ctrl=0x0101;//关断2V电压使用参考电压为AVdd并允许AD转换同时屏蔽MICIN
tag2=*P_ADC_Ctrl;
//asm("[P_ADC_Ctrl]=%0"::"r"(0x0003));
temperature=0; //温度初值
settemperature=40;
delay=0;
ave=0;
temperature1=0;
show_time=show_what=second=minute=hour=0;
time_temp=0;
slow=0;
}
void key()//扫描键盘,检测到有效按键时,修改对应的参量值
{
unsigned int temp1;
*P_IOB_Data=0x00fe;//扫描键盘第一行
temp1=*P_IOB_Data;
temp1^=0x00fe;
if(temp1==0x0010)
key1=1;
else if(temp1==0x0020)
key2=1;
else if(temp1==0x0040)
key3=1;
else if(temp1==0x0080)
key4=1;
if(temp1==0&&key1==1)//按键一的处理程序
{
key1=0;
settemperature++;
show(settemperature,temperature);
}
else if(temp1==0&&key2==1)//按键二的处理程序
{
key2=0;
settemperature--;
show(settemperature,temperature);
}
else if(temp1==0&&key3==1)//按键三的处理程序
{
key3=0;
settemperature+=10;
show(settemperature,temperature);
}
else if(temp1==0&&key4==1)//按键四的处理程序
{
key4=0;
settemperature-=10;
show(settemperature,temperature);
}
*P_IOB_Data=0x00fd;//扫描键盘第二行
temp1=*P_IOB_Data;
temp1^=0x00fd;
if(temp1==0x0010)
key5=1;
else if(temp1==0x0020)
key6=1;
else if(temp1==0x0040)
key7=1;
else if(temp1==0x0080)
key8=1;
if(temp1==0&&key5==1)
{
key5=0;
show_time=0;
}
else if(temp1==0&&key6==1)
{
key6=0;
show_time=1;
}
else if(temp1==0&&key7==1)
{
key7=0;
show_what=0;
}
else if(temp1==0&&key8==1)
{
key8=0;
show_what=1;
}
}
void calculate()//根据水温的当前状态和设定状态计算各个参量值
{
int pterm,dterm;
err=settemperature*10-temperature;//计算当前水温和设定水温之间的差距
if(abs(err)>deadband)//如果温差大于设定值,就进行PID调节
{
pterm=err*pgain;//计算比例调节量
if(pterm>100||pterm<-100)//温差过大,不用积分调整
integral=0;
else
{
integral+=igain*err;
if(integral>100)//积分值界限
integral=100;
else if(integral<0)
integral=0;
}
dterm=(err-last_error)*dgain;//计算微分调整量
change=pterm+dterm+integral;//计算最终调节量
}
else
{
if(integral>200)
integral=0;
integral+=err;
if(integral>0)
change=integral;//温差不大,只进行积分调节
else
change=2;
}
if(abs(change)>998)change=998;
last_error=err; //更新温差
}
void ad()
{
unsigned int check;
unsigned int temp2;
check=*P_ADC_MUX_Ctrl;
check&=0xc000;//判断是否完成AD转换
if(check==0x8000)
{
temp2=*P_ADC_MUX_Data;
tag4=temp2;
if(ave==64)
{
temperature=temperature1>>6;
if(temperature>340)
temperature+=(temperature-340)/8;
//else
//temperature-=(300-temperature)/10;
if(show_what==0)
show(settemperature,temperature);
delay=0;
ave=0;
temperature1=0;
}
}
}
void InitIO_7219()
{
*P_IOB_Dir|=0x0400;
*P_IOB_Attrib|=0x0400;
*P_IOB_Data|=0x0400;
*P_IOB_Dir|=0x0200;
*P_IOB_Attrib|=0x0200;
*P_IOB_Data|=0x0200;
*P_IOB_Dir|=0x0100;
*P_IOB_Attrib|=0x0100;
*P_IOB_Data|=0x0100;
SendData_7219(0x0c,0x01); // 使其7219工作正常模式
SendData_7219(0x0b,0x07); // 配置scan limit模式,使其8个管子都工作
SendData_7219(0x0a,0x0f); // 设置亮度为最亮
SendData_7219(0x0d,0xff);
SendData_7219(0x09,0xff); // 使8个管子都用编码方式
//第七位设置为1,可以启动该位小数点
}
void time_display()
{
int data;
int b;
if(second>=60)
{
minute++;
second=0;
}
if(minute>=60)
{
hour++;
minute=0;
}
if(hour>=24)
hour=0;
data=second+100*minute;
if(show_time==1&&show_what==1)
show(hour,data);
}
int main()
{
initial();//初始化IO口,设定一些变量的初值
InitIO_7219();
while(1)
{
ad();//将前向电路采集到的电压信号转换为数字信号
key();//扫面键盘,改变对应键值
if(settemperature<=55)
deadband=70;
else if(settemperature<=70)
deadband=45;
else
deadband=10;
time_display();
calculate();//核心部分,PID计算
//display();//显示当前水温和设定水温
}
}
void IRQ4(void)__attribute__((ISR));
void IRQ4(void)
{
unsigned int temp;
*P_Watchdog_Clear=1;
delay++;
slow++;
if(slow==32)
{
ave++;
slow=0;
if(ave<65)
temperature1+=tag4/40;
}
time_temp++;
temp=*P_INT_Ctrl;
if(temp==0x0010&&err>2)
{
reg++;
if(reg>=999)
{
reg=0;
*P_IOA_Data^=0x8100;
}
else if(reg<=change)
*P_IOA_Data|=0x8100;
else
*P_IOA_Data&=0x7eff;
}
else
*P_IOA_Data&=0x7eff;
if(time_temp==1020)
{
time_temp=0;
second++;
}
*P_INT_Clear=0x0010;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -