垂直起降懸臂控制,代碼可以實現指定角度懸停,采用PWM輸出,PCF8591讀取角度,八位數碼管顯示設定角度與實時角度。
單片機源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #define DataPort P0
- #define CYCLE 10
- typedef unsigned char uint8;
- typedef unsigned int uint16;
- typedef unsigned long uint32;
- void Display(unsigned char FirstBit,unsigned char Num);
- void PWMOUT();
- void wucha();
- void scan();
- void xianshi();
- void DelayUs2x(unsigned char t);//us級延時函數聲明
- void DelayMs(unsigned char t); //ms級延時
- void Init_Timer0(void);
- bit flag_300ms = 0;
- sbit LATCH1=P2^2;
- sbit LATCH2=P2^3;
- sbit K1 = P3^0;
- sbit K2 = P3^1;
- sbit PWM = P1^3;
- sbit I2C_SDA = P2^1;
- sbit I2C_SCL = P2^0;//I2C通信的兩個引腳
- uint8 AD_value = 0;//AD值
- key=0;
- TempData[8];
- angle=0;
- sangle=0;
- Proportion=1.5;
- Integral=0;
- Derivative=0;
- Error;
- LastError;
- PrevError;
- out=20;
- count=0;
- uint8 get_ADC_vaule(uint8 chn);
- code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 顯示段碼值0~9
- code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分別對應相應的數碼管點亮,即位碼
- void main()
- {
- Init_Timer0();
- while(1)
- {
- xianshi();
- scan();
- wucha();
- xianshi();
- }
- }
- void DelayUs2x(unsigned char t)
- {
- while(--t);
- }
- void DelayMs(unsigned char t)
- {
- while(t--)
- {
- //大致延時1mS
- DelayUs2x(245);
- DelayUs2x(245);
- }
- }
- void scan()
- {
- P3 = 0xff;
-
- if (P3==0xfe) key=1;
- if (P3==0xfd) key=2;
- if (P3==0xfb) key=3;
- if (P3==0xf7) key=4;
- if (P3==0xef) key=5;
- if (P3==0xdf) key=6;
- if (P3==0xbf) key=7;
- if (P3==0x7f) key=8;
- switch (key)
- {
- case 1:
- {
- sangle=0;
- Proportion=3;
- Integral=0;
- Derivative=0;
- }
- break;
- case 2:
- {
- sangle=35;
- Proportion=1.7;
- Integral=0.1;
- Derivative=0.1;
- }
- break;
- case 3:
- {
- sangle=45;
- Proportion=1.85;
- Integral=0;
- Derivative=0;}
- break;
- case 4:
- {
- sangle=45;
- Proportion=1.85;
- Integral=0.2;
- Derivative=0;
- }
- break;
- case 5:
- {
- sangle=45;
- Proportion=1.85;
- Integral=0.3;
- Derivative=0.1;}
- break;
- case 6:
- {
- sangle=50;
- Proportion=1.5;
- Integral=0;
- Derivative=0;
- }
- break;
- case 7:
- {
- sangle=55;
- Proportion=1.8;
- Integral=0.01;
- Derivative=0;}
- break;
- case 8:
- {
- sangle=60;
- Proportion=1.5;
- Integral=0;
- Derivative=0;
- }
- }
- }
- void xianshi()
- {DelayMs(1);
- AD_value = get_ADC_vaule(0);//讀取通道0的AD值
-
- angle=(float)AD_value*1.41-21;
- TempData[3]=dofly_DuanMa[angle%10];
- TempData[2]=dofly_DuanMa[angle/10%10];
- TempData[1]=dofly_DuanMa[angle/100];
- TempData[7]=dofly_DuanMa[sangle%10];
- TempData[6]=dofly_DuanMa[sangle/10%10];
- TempData[5]=dofly_DuanMa[sangle/100];
- }
- void wucha()
- {
- angle=(float)AD_value*1.41-21;
- Error=sangle-angle;
- PrevError+=Error;
- out=out+Proportion*Error+Integral*PrevError+Derivative*(LastError-Error);
- //out=out+Proportion*(Error-LastError)+Integral*Error+Derivative*(Error+PrevError-2*LastError);
- LastError=Error;
- //out=50;
- //out=out+Proportion*Error+Integral*Error*0.02+Derivative*Error/0.02;
- if(out<0)
- out=0;
- if(out>100)
- out=100;
- }
- void I2C_delay()//I2C延時函數
- {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- void I2C_start()//I2C起始信號
- {
- I2C_SDA = 1;
- I2C_SCL = 1;
- I2C_delay();
- I2C_SDA = 0;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- }
- void I2C_stop()//I2C停止信號
- {
- I2C_SDA = 0;
- I2C_SCL = 0;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SDA = 1;
- I2C_delay();
- }
- bit I2C_write(uint8 dat)//I2C寫一個字節(jié)
- {
- bit ack = 0;
- uint8 mask = 0;
- for(mask=0x80;mask!=0;mask>>=1)
- {
- if((mask&dat) == 0)
- I2C_SDA = 0;
- else
- I2C_SDA = 1;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- }
- I2C_SDA = 1;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- ack = I2C_SDA;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
-
- return (~ack);
- }
- uint8 I2C_read_ACK()//I2C讀一個字節(jié),并發(fā)送應答位
- {
- uint8 dat = 0;
- uint8 mask = 0;
- I2C_SDA = 1;
- for(mask=0x80;mask!=0;mask>>=1)
- {
- if(I2C_SDA == 0)
- dat = dat & (~mask);
- else
- dat = dat | mask;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- }
- I2C_SDA = 0;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- return dat;
- }
- uint8 I2C_read_NACK()//I2C讀一個字節(jié),并發(fā)送非應答位
- {
- uint8 dat = 0;
- uint8 mask = 0;
- I2C_SDA = 1;
- for(mask=0x80;mask!=0;mask>>=1)
- {
- if(I2C_SDA == 0)
- dat = dat & (~mask);
- else
- dat = dat | mask;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- }
- I2C_SDA = 1;
- I2C_delay();
- I2C_SCL = 1;
- I2C_delay();
- I2C_SCL = 0;
- I2C_delay();
- return dat;
- }
- uint8 get_ADC_vaule(uint8 chn)//獲取AD值
- {
- uint8 value;
- I2C_start();//I2C起始信號
- if(!I2C_write(0X90))//寫入PCF8591地址及讀寫選擇位為寫
- {
- I2C_stop();
- return 0;
- }
- I2C_write(0X40 | chn);//寫入PCF8591通道0
- I2C_write(0x00 | chn);//寫入PCF8591通道0
- I2C_start();//I2C起始信號
- I2C_write(0x48<<1 | 0x01);
- I2C_read_ACK();//提供轉換所需的時鐘信號
- value = I2C_read_NACK();//讀取上一次轉換的結果
- I2C_stop();//I2C結束信號
- return value;
- }
- void Init_Timer0(void)
- {
- TMOD |= 0x01; //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響
- TH0=0x00; //給定初值
- TL0=0x00;
- EA=1; //總中斷打開
- ET0=1; //定時器中斷打開
- TR0=1; //定時器開關打開
- }
- void Timer0_isr(void) interrupt 1
- {
- static unsigned char count;
- TH0=(65536-10)/256; //重新賦值 2ms
- TL0=(65536-10)%256;
- Display(0,8); // 調用數碼管掃描
- count++;
- if (count<out)
- PWM= 1;
- else
- PWM=0;
- if(count==100)
- count= 0;
- }
- void Display(unsigned char FirstBit,unsigned char Num)
- {
- static unsigned char i=0;
-
- DataPort=0; //清空數據,防止有交替重影
- LATCH1=1; //段鎖存
- LATCH1=0;
- DataPort=dofly_WeiMa[i+FirstBit]; //取位碼
- LATCH2=1; //位鎖存
- LATCH2=0;
- DataPort=TempData[i]; //取顯示數據,段碼
- LATCH1=1; //段鎖存
- LATCH1=0;
- i++;
- if(i==Num)
- i=0;
- }
復制代碼
全部程序51hei下載地址:
第四次.rar
(40.58 KB, 下載次數: 16)
2020-12-13 09:06 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|