⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main_pid_ok1.c

📁 一个很好的PID程序,只需稍加修加便可移植到其它系统当中
💻 C
字号:
/*==================================
微机控制与接口技术课程设计
恒温控制单片机系统C程序
==================================*/
#include <AT89X52.H>
#include <string.h>
#include <stdio.h>
#include <absacc.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
double      rOut;       //  PID Response (Output)
double      rIn;        //  PID Feedback (Input)
sbit P30=P3^0;  		// DQ=P30=P3^0,为温度总线
sbit P31=P3^1;
uchar TEMP;				// 温度值的变量;
sbit P10=P1^0;
sbit P11=P1^1;
sbit P12=P1^2;
sbit P13=P1^3;
sbit P14=P1^4;
sbit P15=P1^5;
sbit P16=P1^6;
sbit P17=P1^7;
//共阴 LED
unsigned char code led[]={0x3F,0x6,0x5B,0x4F,0x66,0x6D,0x7D,0x7,0x7F,0x6F};

typedef struct PID {
    double  SetPoint;      // 设定目标 Desired value,从拨码盘的输入值
    double  Proportion;    // 比例常数 Proportional Const
    double  Integral;      // 积分常数 Integral Const
    double  Derivative;    // 微分常数 Derivative Const
    double  LastError;     // 偏差 Error[-1]
    double  PrevError;     // 偏差 Error[-2]
    double  SumError;      // 偏差总和 Sums of Errors
} PID;
/*=================================================================
   PID计算部分
==================================================================*/

double PIDCalc( PID *pp, double NextPoint )
{
	double  dError,Error;
    Error = pp->SetPoint -  NextPoint;          // 偏差
    pp->SumError += Error;                      // 积分
    dError = pp->LastError - pp->PrevError;     // 当前微分
    pp->PrevError = pp->LastError;
    pp->LastError = Error;
    return (pp->Proportion * Error              // 比例项
        +   pp->Integral * pp->SumError         // 积分项
        +   pp->Derivative * dError             // 微分项
           );
}

/*===================================================================
   Initialize PID Structure
===================================================================*/

void PIDInit (PID *pp)
{
    memset ( pp,0,sizeof(PID));   
	//缓冲区操作函数,初始化缓冲区中指定个数的数据字节为某一指定的字符值
}

/*===================================================================
    Main Program
====================================================================*/

	//从DS18B20数字温度传感器读取的温度值。

void delay (unsigned int count)
{									
	unsigned int i;	
	while (count)	
	{
		i =200;
		while (i>0) i--;
		count--;
    }
}

void tmreset (void)				// 发送复位和初始化
{
	unsigned int i;
	P30 = 0;	
	i = 103;
	while (i>0) i--;        	// 延时
	P30 = 1;	
	i = 4;	
	while (i>0) i--;	
}

bit tmpread (void)				// 读取数据的一位
{ 
	unsigned int i;
	bit dat;
	P30 = 0; i++;	
	P30 = 1; i++; i++;			//延时	
	dat = P30;	
	i = 8; while (i>0) i--;		// 延时
	return (dat);
}	

unsigned char tmpread2 (void) 	//读一个字节
{
	unsigned char i,j,dat;	
	dat = 0;	
	for (i=1;i<=8;i++)
	{
		j = tmpread ();	
		dat = (j << 7) | (dat >> 1);	
	}
	return (dat);
}	

void tmpwrite (unsigned char dat)	//写一个字节
{   
	unsigned int i;
	unsigned char j;
	bit testb;	
	for (j=1;j<=8;j++)
	{	
		testb = dat & 0x01;
		dat = dat >> 1;	
		if (testb)
		{	
			P30 = 0; 	// 写0 
			i++; i++;  
			P30 = 1;	
			i = 8; while (i>0) i--; 
		}
		else	
		{
			P30 = 0; 	// 写0 
			i = 8; while (i>0) i--; 
			P30 = 1;
			i++; i++;  
		}
	}
}

void tmpchange(void)	// ds1820 开始转换
{  
	tmreset ();			// 复位	
	delay (1);			// 延时
	tmpwrite (0xcc);	// 跳过序列号命令
	tmpwrite (0x44); 	// 发转换命令 44H,	
}

void tmp (void)			// 读取温度
{ 
	unsigned char a;
	tmreset ();			// 复位
	delay (1);			// 延时
	tmpwrite (0xcc); 	// 跳过序列号命令
	tmpwrite (0xbe); 	// 发送读取命令
	a = tmpread2 ();	// 读取温度(ROM数字)	
	TEMP=a>>1;			// 乘分辨率0.5,转换为十进制的温度值
}

//---------------------------------------------------------
double sensor (void)    //  Dummy Sensor Function
{
    tmpchange();		// 开始温度转换
	delay(200);			// 读取延时
	tmp();				// 读取温度
	return(TEMP);		// 返回温度值
}

//============================================================
//	display 子程序

unsigned int display(viod)
{
	unsigned int NUM;
	unsigned int shi; 	//高位显示变量
	unsigned int ge;  	//低位显示变量
	shi=(!P17)*8+(!P16)*4+(!P15)*2+(!P14)*1;
	ge=(!P13)*8+(!P12)*4+(!P11)*2+(!P10)*1;
	P0=led[shi];
	P2=led[ge];
	rIn=shi*10+ge;
	return(rIn);
}

//===========================================================

void delay_1ms(int t) 	//设置周期为1mS,使用等脉宽PWM法。
{
	unsigned int i;	
	while (t)	
	{
		i =1000;
		while (i>0) i--;
		t--;
    }
}

//-----------------------------------------------------------
	//输出PWM控制程序
void PWM_actuator(double rDelta)  // PWM Actuator Function
{
	unsigned int th;
	unsigned int tl;
	unsigned char k;
	// (200/700)*1.0≈0.29
	double bili=0.29;  	//初始化功率=200W,对应bili=1时是700W。
	if  (rDelta > 0)
 	{
		th=1000*bili;
		tl=1000*(1-bili);
		bili+=0.02;
		for (k=10;k>0;k--)   	// 加热一段时间
		{
			P31=1;
			delay_1ms(th);
			P31=0;
			delay_1ms(tl);
		}
	}
	else
	{
		bili=0;	
		P31=0;    		//不加热,让其自然冷却
	}	
}
//===============================================================================

void main(void)
{
    PID         sPID;                   //  PID Control Structure
    PIDInit ( &sPID );                  //  Initialize Structure
    //P、I、D 系数的设定,以及键盘预置温度输入的读取
    sPID.Proportion = 0.1;
    sPID.Integral   = 0.1;
    sPID.Derivative = 0.1;
    sPID.SetPoint   = display();       //  键盘输入的温度设定值,同时送LED显示
    while(1) 
    {                         			//  Mock Up of PID Processing
        rIn = sensor ();                //  Read Input
        rOut = PIDCalc ( &sPID,rIn );   //  Perform PID Interation
        PWM_actuator ( rOut );          //  Effect Needed Changes
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -