• 基于51单片机XPT2046转换电位器模拟量为数字量当作设定速度经PID控制直流电机实际转速的项目工程


    #include <reg51.h>
    #include< intrins.h>
    #define uchar unsigned char
    #define uint unsigned int
    #define ulong unsigned long
    #define GPIO_DIG P0//自定义数码管显示端 
    sbit pwm=P1^0;//位定义脉冲输入端口
    sbit IN1=P1^1;//位定义L298输入端1
    sbit IN2=P1^2;//位定义L298输入端2
    sbit LSA=P2^2;//位定义74HC138译码器A端 
    sbit LSB=P2^3;//位定义74HC138译码器B端
    sbit LSC=P2^4;//位定义74HC138译码器C端
    sbit zhongduan=P3^2;//位定义中断次数变量
    sbit DIN=P3^4;//位定义XPT2046数据输入端
    sbit CS=P3^5;//位定义XPT2046片选端
    sbit CLK=P3^6;//位定义XPT2046时钟端
    sbit DOUT=P3^7;//位定义XPT2046数据输出端
    int e=0,e1=0,e2=0;//声明当前偏差值变量、之后偏差值变量、再后偏差值变量
    int out=0;//声明PID调节后输出偏差值变量 
    uint value;//脉冲宽度时间变量
    uint temp;//设定速度
    uint num;//实际速度
    uint Inlpuse=0;//脉冲计数变量
    uint time,count,temp1;//定时器0中断次数变量、定时器1中断次数变量、电位器模拟量变量
    float uk=0,uk1=0,duk=0;//声明目前总偏差值变量、之后偏差值总变量、偏差值总变量 
    float kp=5,ki=1.5,kd=0.9;//PID控制系数P=5,I=1.5,D=0.9。
    uchar code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
    //0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
    uchar DisplayData[8];//用来存放要显示的8位数的值变量
    //  void SPI_Start() 
    //{
    //   CLK=0;
    //   CS=1;
    //   DIN=1;
    //   CLK=1;
    //   CS=0;
    //  }
      void SPI_Write(uchar dat)//写数据函数
    {
       uchar i;
       CLK=0;
       for(i=0;i<8;i++)
     {
        DIN=dat>>7; 
        dat<<=1; 
        CLK=0; 
        CLK=1;
       }
      }
      uint SPI_Read()//读数据函数
    {
       uint i, 
       dat=0;
       CLK=0;
       for(i=0;i<12;i++)//接收12位数据
     {
        dat<<=1;
        CLK=1;
        CLK=0;
        dat|=DOUT;
       }
       return dat;
      }
      uint Read_AD_Data(uchar cmd)//读XPT2046把模拟量转换为数字量函数
    {
       uchar i;
       uint AD_Value;
       CLK=0;
       CS=0;
       SPI_Write(cmd);
       for (i=6;i>0; i--);
       CLK=1;//
       _nop_();
       _nop_();
       CLK=0;
       _nop_();
       _nop_();
       AD_Value=SPI_Read();
       CS=1;
       return AD_Value;
      }
      void SetSpeed()//速度函数
    {
       temp1=Read_AD_Data(0x94);//电位器数字量变量
       temp=2*temp1>>5;//temp的变化范围在0-250之间
      }
      void PIDControl()//PID偏差计算函数
    {
       e=temp-num;
       duk=(kp*(e-e1)+ki*e+kd*(e-2e1+e2));
       uk=uk1+duk;
       out=(int)uk;
       if(out>250)
     {
        out=100;
       }
       else if(out<0)
     {
        out=0;
       }
        uk1=uk;
        e2=e1;
        e1=e;
        value=out;
       }
      void DigDisplay()//显示函数
    {
       uchar i;
       uint j;
       DisplayData[7]=DIG_CODE[num%10000/1000];
       DisplayData[6]=DIG_CODE[num%1000/100];
       DisplayData[5]=DIG_CODE[num%100/10];
       DisplayData[4]=DIG_CODE[num%10];
       DisplayData[3]=DIG_CODE[temp%10000/1000];
       DisplayData[2]=DIG_CODE[temp%1000/100];
       DisplayData[1]=DIG_CODE[temp%100/10];
       DisplayData[0]=DIG_CODE[temp%10];
       for(i=0;i<8;i++)
     {
        switch(i)//位选,选择点亮的数码管。
      {
         case(0)://显示第0位
                 LSA=0;
                 LSB=0;
                 LSC=0;
                 break;
         case(1)://显示第1位
                 LSA=1;
                 LSB=0;
                 LSC=0;
                 break;
         case(2)://显示第2位
                 LSA=0;
                 LSB=1;
                 LSC=0;
                 break;
         case(3)://显示第3位
                 LSA=1;
                 LSB=1;
                 LSC=0;
                 break;
         case(4)://显示第4位
                 LSA=0;
                 LSB=0;
                 LSC=1;
                 break;
         case(5)://显示第5位
                 LSA=1;
                 LSB=0;
                 LSC=1;
                 break;
         case(6)://显示第6位
                 LSA=0;
                 LSB=1;
                 LSC=1;
                 break;
         case(7)://显示第7位
                 LSA=1;
                 LSB=1;
                 LSC=1;
                 break;
        GPIO_DIG=DisplayData[i];//发送段码
        j=50;//扫描间隔时间设定
        while(j--);
        GPIO_DIG=0x00;//消隐
       }
      }
     }
      void SystemInit()
    {
       TMOD=0x21;//设定时器0为工作方式1,定时器1为工作方式2(自动重装初值)。
       TH0=0x3c;//设定50ms一次中断
       TL0=0xb0;
       TH1=0x9c;//设定100us一次中断
       TL1=0x9c;
       EA=1;//开总中断
       EX0=1;//开外部中断0
    IT0=1;//启动下降沿触发有效
    ET0=1;//开定时器0中断 ET1=1;//开定时器1中断 TR0=1;//启动定时器0
    TR1=1;//启动定时器1
    } void exter0() interrupt 0//外部中断0函数 { Inlpuse++;//M法测速度(外部中断0和定时器0用在M法测速上) } void timer0() interrupt 1//定时器0中断函数 { TH0=0x3c;//重装初值 TL0=0xb0; time++; if(time>=20)//1s钟读取一次转速 { EX0=0; TR0=0; num=Inlpuse;//计算转速 Inlpuse=0; PIDControl();//100ms控制一次Inlpuse=0; EX0=1; TR0=1; } } void time1() interrupt 3//定时器1中断函数 { count++; if(count>=100) count=0; if(count<value) pwm=1; else pwm=0; } void main()//主函数 { SystemInit(); while(1) { SetSpeed(); DigDisplay(); } }
  • 相关阅读:
    REHの个人主页
    多项式基础学习笔记(2)
    多项式基础学习笔记(1)
    FFT & NTT 学习笔记
    LCT学习笔记
    莫队学习笔记
    SAM 学习笔记
    网络流学习笔记
    关于魔术球贪心做法的证明
    【题解】异或粽子&加强版
  • 原文地址:https://www.cnblogs.com/AChenWeiqiangA/p/12832881.html
Copyright © 2020-2023  润新知