|
本人,从初次接触松翰单片机到现在2个月了,从小白开始认识松翰单片机;有幸接触到了可控硅,又从小白认识可控硅电机调速;在茫茫的大海又 撞到难题,再次来这里寻求帮助。
上次发的汇编带反汇编的;看了一段时间,感觉难度好大,根本无法理解,所以自己用C写一个。
以下是本人写的C,写的不好。
问题点:
1、电机无法控速,上电直奔20000RMP,自己设定值在调不起作用?
2、本芯片支不支持本代码算法?
3、电机使用的是六级磁环,使用闭环调速,现在开环都无法做到控速?
事先在在这感谢前辈,多多拍砖,指正错误!!交流地址:QQ_ 1151174742
————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#include <SN8F27E65.h>
#define uint8 unsigned int
#define uchar8 unsigned char
#define uint16 unsigned long
struct bitDefine{
unsigned bit0:1;
unsigned bit1:1;
unsigned bit2:1;
unsigned bit3:1;
unsigned bit4:1;
unsigned bit5:1;
unsigned bit6:1;
unsigned bit7:1;
}Mode_Flag;
struct PIDValue{
uint16 liEkVal[3]; //差值保存,给定值和反馈值的差
uchar8 uEkFlag[3]; //符号,1 对应负数,0 对应正数
uchar8 uKP_Coe; //比例系数
uchar8 uKI_Coe; //积分系数
uchar8 uKD_Coe; //微分系数
uint16 iPriVal; //上一时刻的值
uint16 iSetVal; //设定值
uint16 iCurVal; //实际值
}PID;
#define Flag_AC_HI (Mode_Flag.bit0)
#define Flag_AC_LW (Mode_Flag.bit1)
#define Flag_AC_Point (Mode_Flag.bit2)
#define Flag_Motor_Point (Mode_Flag.bit3)
#define Flag_Hall_Point (Mode_Flag.bit4)
#define Flag_Time_Point (Mode_Flag.bit5)
void IO_Setting(void);
void Timer_Setting(void);
void Key_Scan(void);
void PID_Operation(void);
void Speed_Solver(void);
#define AC_Point FP04 //交流过零输入脚
#define Motor_Out FP03 //可控硅控制脚
#define Key_Select FP43 //按键输入
#define Key_Auto FP44
#define Key_Start FP46
#define LED FP45
uint8 Key_Count_Select = 0;
uint8 Key_Count_Auto = 0;
uint8 Key_Count_Start = 0;
uint8 Time_CNT = 0; //输出控制时间
uint8 Control_Speed = 0; //
uint16 Hall_Speed_Cnt = 0;
uint16 Speed_Time_ms = 0;
//uint16 Speed_Time_s = 0;
//uint8 Speed_Time[2] ;
uint16 Speed_Value;
uint16 Set_Speed_Value;
uint8 Control_Speed_1 = 0;
void main(void)
{
WDTR = 0x5A;
IO_Setting();
Timer_Setting();
Time_CNT = 0;
FGIE = 1;
PID.uKP_Coe = 0;
PID.uKI_Coe = 0;
PID.uKD_Coe = 0;
//LED = 0;
Set_Speed_Value = 40960; //设置的速度值
while(1)
{
if(!AC_Point) //低
{
if(Flag_AC_HI == 1)
{ Flag_AC_HI = 0; Flag_AC_Point = 1;}
else
{Flag_AC_HI = 0;}
}
else //高
{
if(Flag_AC_HI == 0)
{ Flag_AC_HI = 1; Flag_AC_Point = 1;}
else
{Flag_AC_HI = 1;}
}
while(Flag_AC_Point)
{
Time_CNT = 0;
Flag_AC_Point = 0 ;
Flag_Motor_Point = 1;
//Control_Speed = 150; //0~900
PID_Operation();
Speed_Solver();
}
}
}
void PID_Operation(void)
{
uint16 Temp[3] = {0}; //中间变量
uint16 PostSum = 0; //正数和
uint16 NegSum = 0; //负数和
PID.iCurVal = Speed_Value; //测出来的实时值速度
PID.iSetVal = Set_Speed_Value; //设定值速度
if(PID.iSetVal > PID.iCurVal) //设定值与实际值比较
{
Temp[0] = PID.iSetVal - PID.iCurVal ;//偏差值
PID.uEkFlag[1] = 0; //为正数
PID.liEkVal[2] = PID.liEkVal[1];
PID.liEkVal[1] = PID.liEkVal[0];
PID.liEkVal[0] = Temp[0];
if(PID.liEkVal[0] > PID.liEkVal[1] ) //E(k)>E(k-1) 这一时刻值 大于 上一时刻的值
{
Temp[0] = PID.liEkVal[0] - PID.liEkVal[1];
PID.uEkFlag[0] = 0;
}
else //E(k)<E(k-1) 这一时刻值 小于 上一时刻的值
{
Temp[0] = PID.liEkVal[1] - PID.liEkVal[0];
PID.uEkFlag[0] = 1;
}
Temp[2] = 2 * PID.liEkVal[1]; //2*E(k-1) 上一时刻的值 * 2
if((PID.liEkVal[0] + PID.liEkVal[2]) > Temp[2]) //这一时刻的值 与 上上次值 的和 大于 上一时刻的值 * 2
{
Temp[2] = (PID.liEkVal[0] + PID.liEkVal[2]) - Temp[2];
PID.uEkFlag[2] = 0;
}
else //这一时刻的值 与 上上次值 的和 小于 上一时刻的值 * 2
{
Temp[2] = Temp[2] - (PID.liEkVal[0] + PID.liEkVal[2]);
PID.uEkFlag[2] = 1;
}
Temp[0] = (uint16)PID.uKP_Coe * Temp[0]; // P 乘以 这一时刻值 和 上一时刻的值 的差值
Temp[1] = (uint16)PID.uKI_Coe * PID.liEkVal[0]; // I
Temp[2] = (uint16)PID.uKD_Coe * Temp[2]; // D
/* 正数项叠加,负数项叠加 */
if(PID.uEkFlag[0] == 0)
PostSum += Temp[0]; //正数和
else
NegSum += Temp[0]; //负数和
/* ========= 计算KI*E(k)的值 ========= */
if(PID.uEkFlag[1] == 0)
PostSum += Temp[1]; //正数和
else
/* ========= 计算KD*[E(k-2)+E(k)-2E(k-1)]的值 ========= */
if(PID.uEkFlag[2]==0)
PostSum += Temp[2]; //正数和
else
NegSum += Temp[2]; //负数和
/* ========= 计算U(k) ========= */
PostSum += (uint16)PID.iPriVal;
if(PostSum > NegSum) //是否控制量为正数
{
Temp[0] = PostSum - NegSum;
PID.iPriVal = (uint16)Temp[0];
Flag_Motor_Point = 1;
}
else //控制量输出为负数,则输出0(下限幅值输出)
{
Temp[0] = NegSum - PostSum;
PID.iPriVal = (uint16)Temp[0];
Flag_Motor_Point = 1;
}
}
else
{
Temp[0] = PID.iCurVal - PID.iSetVal ;//偏差值
PID.uEkFlag[1] = 0; //为正数
PID.liEkVal[2] = PID.liEkVal[1];
PID.liEkVal[1] = PID.liEkVal[0];
PID.liEkVal[0] = Temp[0];
if(PID.liEkVal[0] > PID.liEkVal[1] ) //E(k)>E(k-1)
{
Temp[0] = PID.liEkVal[0] - PID.liEkVal[1];
PID.uEkFlag[0] = 0;
}
else
{
Temp[0] = PID.liEkVal[1] - PID.liEkVal[0];
PID.uEkFlag[0] = 1;
}
Temp[2] = 2 * PID.liEkVal[1];
if((PID.liEkVal[0] + PID.liEkVal[2]) > Temp[2])
{
Temp[2] = (PID.liEkVal[0] + PID.liEkVal[2]) - Temp[2];
PID.uEkFlag[2] = 0;
}
else
{
Temp[2] = Temp[2] - (PID.liEkVal[0] + PID.liEkVal[2]);
PID.uEkFlag[2] = 1;
}
Temp[0] = (uint16)PID.uKP_Coe * Temp[0];
Temp[1] = (uint16)PID.uKI_Coe * PID.liEkVal[0];
Temp[2] = (uint16)PID.uKD_Coe * Temp[2];
/* 正数项叠加,负数项叠加 */
if(PID.uEkFlag[0] == 0)
PostSum += Temp[0]; //正数和
else
NegSum += Temp[0]; //负数和
/* ========= 计算KI*E(k)的值 ========= */
if(PID.uEkFlag[1] == 0)
PostSum += Temp[1]; //正数和
else
/* ========= 计算KD*[E(k-2)+E(k)-2E(k-1)]的值 ========= */
if(PID.uEkFlag[2]==0)
PostSum += Temp[2]; //正数和
else
NegSum += Temp[2]; //负数和
/* ========= 计算U(k) ========= */
PostSum += (uint16)PID.iPriVal;
if(PostSum > NegSum) //是否控制量为正数
{
Temp[0] = PostSum - NegSum;
PID.iPriVal = (uint16)Temp[0];
Flag_Motor_Point = 1;
}
else //控制量输出为负数,则输出0(下限幅值输出)
{
Temp[0] = NegSum - PostSum;
PID.iPriVal = (uint16)Temp[0];
Flag_Motor_Point = 1;
}
}
}
void Speed_Solver(void)
{
Control_Speed = (PID.iPriVal / 256);
}
void IO_Setting(void)
{
P0M = 0x6E; //P0 Input-Output value 0110 1110
P0UR = 0x01; //P0 pull up value
P0OC = 0x00; //P0 open drain value
FP00IRQ = 0;
FP00IEN = 1; //P00 interrupt flag setting
PEDGE = 0x01; //Trigger edge:P00 set Rising edge
P0 = 0X00; //P0 register value
P4M = 0xA7; //P4 Input-Output value 1010 0111
P4UR = 0x58; //P4 pull up value 0101 1000
P4CON = 0x00; //P4 Analog-Digital value
P4 = 0X00; //P4 register value
}
void Timer_Setting(void)
{
T0M = 0x60; //T0M register value, Fcpu: 4.000000MHZ//CLK source: Fcpu//
FT0IRQ = 0;
FT0IEN = 1; //T0 Interrupt enable
FT0ENB = 1; //T0 enable
TC0M = 0xB4; //TC0M register value, Fhosc: 16.000000MHZ//CLK source: Fhosc
TC0C = 0xCE; //TC0C register value, time: 50.000000us(20000.000000HZ)
TC0R = 0xCE; //TC0R register value
FTC0IRQ = 0;
FTC0IEN = 1; //TC0 Interrupt enable
FTC0ENB = 1; //TC0 enable
}
void __interrupt [0x09] ISR_INT0(void)
{
if(FP00IRQ)
{
FP00IRQ=0;
Hall_Speed_Cnt++; //脉冲计数
}
}
void __interrupt [0x0B] ISR_T0(void) // 1us
{
if(FT0IRQ)
{
FT0IRQ=0;
// Speed_Time_s ++;
if(Hall_Speed_Cnt > 1)
{
Speed_Time_ms++;
Speed_Value = (Speed_Time_ms*256)/Hall_Speed_Cnt;
Flag_Time_Point = 1;
if(Speed_Time_ms > 50)
{
Flag_Time_Point = 0;
Speed_Time_ms = 0;
Hall_Speed_Cnt = 0;
Flag_Time_Point = 0;
}
}
else
{
Speed_Value = 0;
Speed_Time_ms = 0;
Hall_Speed_Cnt = 0;
Flag_Time_Point = 0;
}
}
}
void __interrupt [0x0C] ISR_TC0(void) //10us
{
if(FTC0IRQ)
{
if(Flag_Motor_Point)
{
FTC0IRQ=0;
Time_CNT++ ;
if(Time_CNT >= Control_Speed)
{
if(Time_CNT <= (Control_Speed + 20))
{
Motor_Out = 1;
}
else
{
Motor_Out = 0;
}
}
else
{
Motor_Out = 0;
}
if(Time_CNT == 200)
{
Time_CNT = 0;
Flag_Motor_Point = 0;
}
}
else
{
Motor_Out = 0;
Time_CNT = 0;
}
}
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|