标题:
单片机小白求教问题—数码管不显示
[打印本页]
作者:
rsdwm
时间:
2022-3-6 21:15
标题:
单片机小白求教问题—数码管不显示
问题:数码管不显示问题
情况:加上Fuzzy模块的函数后,数码管不显示
单片机源程序如下:
void display_service();
unsigned char ad_result = 0,ControlOut=0; // 0-255
int ad_show = 0;
void main()
{
while(1)
{
ad_result = ADC_Conv();
ad_show = ad_result; //5v - 500 255-份
display_service();
Display();
ControlOut = Control_Fuzzy(ad_result); //如果注释掉这行代码,不调用这个函数就会正常
DAC0832_Conv(ControlOut);
}
}
void display_service()
{
LEDBUF[0]=ad_show/1000%100;
LEDBUF[1]=ad_show/100%10;
LEDBUF[2]=ad_show/10%10;
LEDBUF[3]=ad_show%10;
}
复制代码
fuzzy模块代码
const float code WaterLevel_FuzzyControl_table[7][7]=
// NL NM NS ZO PS PM PL
{
3, 3, 3, 3, 2, 1, 0, //NL
3, 3, 3, 2, 1, 0, 0, //NM
3, 3, 2, 0, 0, 0, 0, //NS
0, 0, 0, 0, 0, 0, 0, //ZO
0, 0, 0, 0,-2,-3,-3, //PS
0, 0,-1,-2,-3,-3,-3, //PM
0,-1,-2,-3,-3,-3,-3 //PL
};
/*
函数名称:隶属度计算函数
参数:x为清晰值对应的模糊值,x0,x1,x2为端点中点值
a,b,c为过程隶属度,u为最终隶属度
*/
float Membership( char x0, char x1, char x2, float x)
{
float a,b,c,u;//r,
//r = x1-x0; //相似三角形算法
//if(r == 0)
// r = 0.001; //保证分母不为零
a = (x-x0)/(x1-x0);//r;
//r = x2-x1;
//if(r == 0)
// r = 0.001;
b = (x2-x)/(x2-x1);//r;
/* tanx算法 tanx=1
a = x-x0;
b = x2-x;
*/
if(a <= b) //比较取小
c = a;
else
c = b;
if(c < 0) //若隶属度小于零,则强制为零
u = 0; //隶属度为什么等于零
else
u = c;
return u; //返回隶属度
}
/*
函数名称:控制函数
参数:入口参数WL;WLE水位偏差;WLEC偏差变化;
WLFlag水位控制标志;WL0上一次的水位值;
WLE0为上一次的水位偏差;WLOut为累计的水位控制输出;
K为水位控制输出比例因子。
*/
unsigned int Control_Fuzzy(unsigned char WL)
{
/*float ControlOut;
ControlOut = WL;*/
static unsigned char WL0 = 0, WLE0 = 0 ;//WLOut = 127 ,;
float ControlOut,WLE,WLEC;//,CG = 0
float code K = 2.67;
char i,j;//,k = 0
static char WLFlag = 0;
float MembershipE[7],MembershipEE[7];// //定义隶属度值缓冲区
if(WLFlag == 1) goto FC; //满足条件,进入模糊控子程序
//*************水位异常报警**************
if(WL <= 106) //水位超低
{
if(WL0 == 0) //第一次进入程序不进行控制
{
ControlOut = 0;
WL0 = WL;
}
else //否则报警
{
ControlOut = 0xff;
//Alarm();
}
}
else if (WL >= 150) //水位超高
{
if(WL0 == 0) //第一次进入程序不进行控制
{
ControlOut = 0;
WL0 = WL;
}
else //否则报警
{
ControlOut = 0;
//Alarm();
}
}
//爆管与虚假水位报警
WLE = WL - WL0; //计算水位偏差及其变化
WLEC = WLE - WLE0;
WL0 = WL;
if(WLEC*10 <= -1) //爆管
{
ControlOut = 0xff;
//Alarm();
}
else if(WLEC*10 >= 3)
{
ControlOut = 0; //虚假水位
//Alarm();
}
else
FC:
{
if(WLFlag == 0) //第一次进入程序不进行控制
{
WLFlag = 1;
//K = 2.67;
WLE = (WL - 127)*0.035; //论域转换
WL0 = WL;
WLE = WLE0;
ControlOut = 0;
}
else
{
WLFlag = 1;
WLE = (WL - 127)*0.035; //论域转换
WL0 = WL;
WLEC = (WLE0 - WLE)*0.024;
WLEC = WLE;
}
//**************计算WLE的隶属度************
MembershipE[1] = Membership(-4,-3,-2,WLE);
MembershipE[2] = Membership(-3,-2,-1,WLE);
MembershipE[3] = Membership(-2,-1,-0,WLE);
MembershipE[4] = Membership(-1,-0,1,WLE);
MembershipE[5] = Membership(0,1,2,WLE);
MembershipE[6] = Membership(1,2,3,WLE);
MembershipE[7] = Membership(2,3,4,WLE);
//**************计算WLEC的隶属度************
MembershipEE[1] = Membership(-4,-3,-2,WLEC);
MembershipEE[2] = Membership(-3,-2,-1,WLEC);
MembershipEE[3] = Membership(-2,-1,-0,WLEC);
MembershipEE[4] = Membership(-1,-0,1,WLEC);
MembershipEE[5] = Membership(0,1,2,WLEC);
MembershipEE[6] = Membership(1,2,3,WLEC);
MembershipEE[7] = Membership(2,3,4,WLEC);
//**************求输出************
for(i=1;i<8;i++)
{
if(MembershipE[i]>0)
{
i=i;
}
}
for(j=1;j<8;j++)
{
if(MembershipEE[i]>0)
{
j=j;
}
}
ControlOut = WaterLevel_FuzzyControl_table[i][j]*K*16+127; //计算结果并且转化论域
}
return ControlOut;
}
复制代码
代码仿真.zip
2022-3-6 21:14 上传
点击文件名下载附件
149 KB, 下载次数: 5
作者:
wojiaoguogai
时间:
2022-3-7 08:52
要么死循环,要么崩了
作者:
rsdwm
时间:
2022-3-7 15:31
wojiaoguogai 发表于 2022-3-7 08:52
要么死循环,要么崩了
谢谢解答,我模拟跑了一遍,发现每次经过fuzzy模块出来后,再display后有又从第一个switch语句开始。死循环了,不知道是什么原因,现在我用定时中断刷新display后可以显示了。
作者:
lkc8210
时间:
2022-3-7 17:37
fuzzy.c :
行64:float MembershipE[7],MembershipEE[7];// //定义隶属度值缓冲区
行128~144:
//**************计算WLE的隶属度************
MembershipE[1] = Membership(-4,-3,-2,WLE);
MembershipE[2] = Membership(-3,-2,-1,WLE);
MembershipE[3] = Membership(-2,-1,-0,WLE);
MembershipE[4] = Membership(-1,-0,1,WLE);
MembershipE[5] = Membership(0,1,2,WLE);
MembershipE[6] = Membership(1,2,3,WLE);
MembershipE[7] = Membership(2,3,4,WLE);
//**************计算WLEC的隶属度************
MembershipEE[1] = Membership(-4,-3,-2,WLEC);
MembershipEE[2] = Membership(-3,-2,-1,WLEC);
MembershipEE[3] = Membership(-2,-1,-0,WLEC);
MembershipEE[4] = Membership(-1,-0,1,WLEC);
MembershipEE[5] = Membership(0,1,2,WLEC);
MembershipEE[6] = Membership(1,2,3,WLEC);
MembershipEE[7] = Membership(2,3,4,WLEC);
[]内只能是0~6,MembershipEE[7] 指向了不知明地址
当中可能包含了display内的i
而当你把display放进定时中断内
display内的i的地址改变了
于是显示就正常了
但依然存某地址不断被MembershipEE[7] = Membership(2,3,4,WLEC);覆写的危险
而且display内的i应定义为静态变数
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1