久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2619|回復: 4
打印 上一主題 下一主題
收起左側

想用STC90C51的P1.0輸出受PID運算結果控制

[復制鏈接]
跳轉到指定樓層
樓主
ID:193338 發表于 2017-5-10 18:26 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
想用STC90C51的P1.0輸出受PID運算結果控制,頻率為0~10KHZ可變的方波,但是被數碼管顯示占用了時間波形頻率最高才500.
有什么辦法可以解決嘛。
/*-----------------------------------------------
IIC協議 PCF8591 AD/DA轉換
P3 獨立按鍵輸入
P1 LED數碼管動態掃描輸入
------------------------------------------------*/  
#include <reg52.h>   
#include <stdio.h>
#include "i2c.h"
#include "delay.h"
#include "display.h"
#define uchar unsigned char
#define uint unsigned int
#define AddWr 0x90   //寫數據地址
#define AddRd 0x91   //讀數據地址
#define KeyPort P3                //定義按鍵輸入端口
#define Key_Add 8                        
#define Key_Dec 7
#define Key_Stop 4
#define Key_Change 3
#define Key_Add10 5
#define Key_Add100 6
#define Key_Dec10 2
#define Key_Dec100 1                //定義按鍵操作id
sbit PWMOUT =P1^0;                        //pwm輸出
sbit LED1 =P1^1;
sbit LED2 =P1^2;
sbit LED3 =P1^3;
bit StopFlag = 0;                                //暫停標志
extern bit ack;                                        //IIC應答
int KeyValue = 0;         
bit ShowType = 0;

//******************按鍵掃描**********************
//***********************************************
unsigned char KeyScan(void)//鍵盤掃描
{
unsigned char keyvalue;
if(KeyPort!=0xff)
   {
    DelayMs(10);
    if(KeyPort!=0xff)                                       
           {
            keyvalue=KeyPort;                                                        //獲取按鍵值
            while(KeyPort!=0xff);
                switch(keyvalue)
                {
                 case 0xfe:return Key_Dec100;break;                        //k1
                 case 0xfd:return Key_Dec10;break;                        //k2
                 case 0xfb:return Key_Change;break;                        //k3
                 case 0xf7:return Key_Stop;break;                                //k4
                 case 0xef:return Key_Add100;break;                        //k5        
                 case 0xdf:return Key_Add10;break;                        //k6
                 case 0xbf:return Key_Dec;break;                                //k7
                 case 0x7f:return Key_Add;break;                        // k8        返回按鍵操作id,交換返回值改變每個按鍵功能                        
                 default:return 0;break;
                }
          }
   }
   return 0;
}
//***********************************************
//***********************************************
//***********************************************
int abs(int a)
{
        if(a<0)
                a=-a;
        return a;
}               
//***********************************************
//***********************************************
//******************定義PID結構體**********************
typedef struct PID
{
    int SetPoint; //設定目標Desired Value
    double Proportion; //比例常數Proportional Const
    double Integral; //積分常數Integral Const
    double Derivative; //微分常數Derivative Const
    int LastError; //Error[-1]
    int PrevError; //Error[-2]
} PID;
//******************定義相關宏*************************
#define P_DATA 10              //比例系數p
#define I_DATA 2                //積分系數i
#define D_DATA 1                //微分系數d     都需要后期調整               
//*****************聲明PID實體*************************
static PID sPID;
static PID *sptr = &sPID;
int pwmValue = 0;
int PWM;                                                                                                
int SetVol =500;              //預設電壓值,可改變!!0-500
int value_V=0;
//*****************定時計數器定義****************************
uchar        TimerCount = 0;
int   PwmCount = 0;       //pwm定時器計數
//*********************PID參數初始化*******************
void IncPIDInit(void)
{
sptr->LastError = 0; //Error[-1]
sptr->PrevError = 0; //Error[-2]
sptr->Proportion =P_DATA; //比例常數Proportional Const
sptr->Integral =I_DATA; //積分常數Integral Const
sptr->Derivative =D_DATA; //微分常數Derivative Const
sptr->SetPoint =SetVol;  //目標為宏定義
}
//*******************增量式PID控制設計*****************
int IncPIDCalc(int NextPoint)
{
   int iError, iIncpid; //當前誤差
   sptr->SetPoint =SetVol;        //設定目標值
   iError = sptr->SetPoint - NextPoint; //增量計算
   if(abs(sptr->LastError-iError)<20)return 0 ;  //50該值需要實際調試
   iIncpid = sptr->Proportion * iError //E[k]項
             - sptr->Integral * sptr->LastError //E[k-1]項
             + sptr->Derivative * sptr->PrevError; //E[k-2]項
    sptr->PrevError = sptr->LastError;   //存儲誤差,用于下次計算
    sptr->LastError = iError;                //存儲誤差
    return iIncpid ;                         //返回增量值
}
/*------------------------------------------------
                    定時器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
        TMOD |= 0x01;          //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響                     
        TH0=(65536-45872)/256;     //定時時間高八位初值
        TL0=(65536-45872)%256;     //定時時間低八位初值
        EA=1;            //總中斷打開
        ET0=1;           //定時器中斷打開
        TR0=1;           //定時器開關打開
}

void Init_Timer1(void)
{
        TMOD |= 0x10;
  TH1 = (65536-100)/256;//
  TL1 = (65536-100)%256;
  ET1=1;                     //打開定時器中斷
  EA=1;                      //打開總中斷
  TR1=1;                     //打開定時器開關
}
/*------------------------------------------------
             讀AD轉值程序
輸入參數 Chl 表示需要轉換的通道,范圍從0-3
返回值范圍0-255
------------------------------------------------*/

unsigned int ReadADC(unsigned char Chl)
{
   unsigned int Val;
   Start_I2c();               //啟動總線
  SendByte(AddWr);             //發送器件地址
     if(ack==0)return(0);
   SendByte(0x40|Chl);            //發送器件子地址
     if(ack==0)return(0);
   Start_I2c();
   SendByte(AddWr+1);
      if(ack==0)return(0);
   Val=RcvByte();
   Val = Val*0.01953*100; //每讀取到一個1就表示5/256V(0.01953)最后保留兩位小數//
   NoAck_I2c();                 //發送非應位
   Stop_I2c();                  //結束總線
  return(Val);
}
/*------------------------------------------------
             數字分解
------------------------------------------------*/
void DisNumber()
{
  if(ShowType == 0)
  {
                TempData[0]=dofly_DuanMa[value_V/100]|0x80;        //采集值百位
                TempData[1]=dofly_DuanMa[(value_V%100)/10];   //采集值十位
                TempData[2]=dofly_DuanMa[(value_V%100)%10];   //采集值個位
    TempData[3]=0;
                TempData[4]=dofly_DuanMa[SetVol/100]|0x80;         //目標值百位
                TempData[5]=dofly_DuanMa[(SetVol%100)/10];    //目標值十位
                TempData[6]=dofly_DuanMa[(SetVol%100)%10];    //目標值個位
    }
    if(ShowType == 1)
    {
    TempData[0]=dofly_DuanMa[pwmValue/1000];        //采集值千位
                TempData[1]=dofly_DuanMa[(pwmValue%1000)/100];   //采集值百位
                TempData[2]=dofly_DuanMa[(pwmValue%100)/10];   //采集值十位
                TempData[3]=dofly_DuanMa[(pwmValue%100)%10];    //目標值個位
                TempData[4]=dofly_DuanMa[TimerCount/100];         //目標值百位
                TempData[5]=dofly_DuanMa[(TimerCount%100)/10];    //目標值十位
                TempData[6]=dofly_DuanMa[(TimerCount%100)%10];    //目標值個位
    }
}                                                                                                                                                                                                                                       


/*------------------------------------------------
              主程序
------------------------------------------------*/
main()
{
  unsigned char num=0;
  Init_Timer0();               
        Init_Timer1();                //定時器初始化
  IncPIDInit();                //pid初始化
        PWMOUT = 0;     
        LED1 =0;
        LED2 =0;
        LED3 =0;
while (1)         //主循環
  {
                 DisNumber();
          KeyValue=KeyScan();
                        switch(KeyValue)
                        {
                                case Key_Change:ShowType = ~ShowType;break;
                                case Key_Stop:StopFlag = ~StopFlag;break;
                                case Key_Dec:SetVol--;break;
                                case Key_Add:SetVol++;break;
                                case Key_Add10:SetVol+=10;break;
                                case Key_Add100:SetVol+=100;break;
                                case Key_Dec10:SetVol-=10;break;
                                case Key_Dec100:SetVol-=100;break;      //根據按鍵操作id改變目標值
                                default:break;
                        }                        
//主循環中添加其他需要一直工作的程序
  }
}

/*------------------------------------------------
                 定時器中斷子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1
{
      TH0=(65536-45872)/256;     //定時時間高八位初值
      TL0=(65536-45872)%256;     //定時時間低八位初值
      TimerCount++;        
                        if(SetVol>500)SetVol=500;                 //防止數據溢出
                        if(SetVol<0)SetVol=0;                   //防止數據溢出
      if(TimerCount == 20&&StopFlag == 0)         //TimerCount計數20時正好1s;即ad采樣間隔為1s,保證pwm穩定輸出0.5s以上;
      {
            TimerCount = 0;            //計數清零
            PWMOUT=0;              //脈沖拉低
            value_V=ReadADC(0);   //讀取ad數據
            pwmValue = pwmValue+IncPIDCalc(value_V);    //pid計算
            if(pwmValue<0) pwmValue = 100;
            if(pwmValue>5000) pwmValue = 4990;   //設置上下限      
                                                LED3 =~LED3;                                
      }
                        else
                        {
                                //等待寫入;
                        }
//                        printf("pwmValue %d value_V %d  \n",pwmValue,value_V);        
}

void  Timer1_isr(void) interrupt 3  //定時器2中斷
{
  TH1 = (65536-100)/256;
  TL1 = (65536-100)%256;
        Display(0,8) ;
        //LED3=~LED3;   
        PwmCount++;
        if(PwmCount >= (5000-pwmValue))
        {
                PWMOUT = ~PWMOUT;
                PwmCount = 0;
        }
        
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:123289 發表于 2017-5-11 00:33 | 只看該作者
你先說一說,PID與數碼管顯示是什么關系?說通了,問題就解決了。
回復

使用道具 舉報

板凳
ID:193338 發表于 2017-5-11 10:16 | 只看該作者
yzwzfyz 發表于 2017-5-11 00:33
你先說一說,PID與數碼管顯示是什么關系?說通了,問題就解決了。

PID的計算結果是控制輸出方波的頻率用的。
數碼管是用來顯示AD采集電位器電壓值得,沒什么關系。
回復

使用道具 舉報

地板
ID:199515 發表于 2017-5-11 13:15 | 只看該作者
誰能簡單說下PID
回復

使用道具 舉報

5#
ID:82765 發表于 2017-5-11 13:41 | 只看該作者
提示: 作者被禁止或刪除 內容自動屏蔽
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 福利成人 | 亚洲国产一区二区三区在线观看 | 中文字幕av一区二区三区 | 国产毛片毛片 | 免费a大片 | 伊人网综合在线 | 欧美成人免费在线 | 国产一区二区在线播放 | 欧美国产激情二区三区 | 在线观看成年人视频 | 日日夜夜天天久久 | 欧美一区二区在线播放 | 超碰地址 | 国产精品久久久 | 欧美成人第一页 | 久久精品亚洲精品国产欧美 | 岛国毛片| 色综合久久天天综合网 | 天天操 夜夜操 | 国产精品一区二区免费看 | 视频在线一区二区 | 粉嫩国产精品一区二区在线观看 | 一片毛片 | 在线2区 | 红色av社区 | 日韩综合 | 国产aa| 精品久久久久久久久久久久久 | 精品一二区 | 91精品国产乱码久久久久久 | 黑人巨大精品欧美一区二区免费 | 日本视频中文字幕 | 免费在线观看av网址 | 男女视频在线观看网站 | 日本特黄a级高清免费大片 成年人黄色小视频 | 三级成人在线 | 免费99视频 | 91久久北条麻妃一区二区三区 | 日日操夜夜干 | 亚洲日本免费 | 中文字幕在线不卡 |