我們單片機設計要求我們用51單片機控制螺旋槳到特定角度,并通過lcd102顯示出來,按鍵設置角度,電位器通過pcf8591讀取角度
包含pcb文件,程序,仿真,設計書等。做的仍有瑕疵希望見諒。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png (39.39 KB, 下載次數: 86)
下載附件
2020-12-13 16:11 上傳
單片機源程序如下:
- #include <reg52.h>
- #include "i2c.h"
- #include "delay.h"
- #include "1602.h"
- #include <stdio.h>
- #include <math.h>
- #define AddWr 0x90 //寫數據地址
- #define AddRd 0x91 //讀數據地址
- #define wait_speak 1
- #define speaked 0
- sbit PWM=P1^2;
- sbit led=P1^6;
- sbit target_up=P3^0;
- sbit target_down=P3^1;
- sbit beep=P1^5;
- float target=40.0;
- float Kp=0.05,Ki=0.4,Kd=0.15;
- unsigned int value,timer1;
- char flag=wait_speak;
- unsigned char confirtime=0;
- extern bit ack;
- unsigned char ReadADC(unsigned char Chl);
- float pid(float input);
- void control();
- void Timer1Init();
- void Timer0Init();
- void change_target();
- void beep_1s();
- void display();
- bit WriteDAC(unsigned char dat);
- void delay100us(int i) //誤差 0us
- {
- unsigned char a,b;
- while(i--)
- for(b=1;b>0;b--)
- for(a=47;a>0;a--);
- }
- /*------------------------------------------------
- 主程序
- ------------------------------------------------*/
- main()
- {
-
- LCD_Init(); //初始化液晶
- DelayMs(20); //延時有助于穩定
- LCD_Clear(); //清屏
- Timer1Init();
- value=0;
- led=0;
- while (1) //主循環
- {
- control();
- change_target();
- }
- }
- /*------------------------------------------------
- 讀AD轉值程序
- 輸入參數 Chl 表示需要轉換的通道,范圍從0-3
- 返回值范圍0-255
- ------------------------------------------------*/
- unsigned char ReadADC(unsigned char Chl)
- {
- unsigned char 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();
- NoAck_I2c(); //發送非應位
- Stop_I2c(); //結束總線
- return(Val);
- }
- float pid(float input)
- {
- static float error2,error1,error3,t,Velocity;
- error1 = target-input ;
- Velocity+=(Kp*(error1-error2))+Ki*error1+Kd*(error1-2*error2+error3);
- t=error2;
- error2= error1 ;
- error3 = t;
- return Velocity;
- }
- //電壓分辨率0.0196V
- //滿電壓3.9V所以角度分辨率0.0196/3.9*360=1.8度 所以增大角度分辨率要嘛增加滿量程電壓3.9V要嘛減小其對應的角度,其實就都是增大電壓
- void control()
- {
-
- unsigned char num=0,i;
- int sum_num=0;
- unsigned char temp[7];//定義顯示區域臨時存儲數組
- float Voltage,angle; //定義浮點變量
- float temp_value;
- for(i=0;i<5;i++)
- {
- sum_num+=ReadADC(0);
- }
- num=sum_num/5;
- sum_num=0;
- Voltage=(float)num;
- angle=(Voltage-16);//*1.41-23.91);
- //angle=-(((Voltage-4.96)/0.0136)+341.73);
- //pid計算
- temp_value=(int)pid(angle);
- if(temp_value<0)
- value=0;
- else if(temp_value>=100)
- value=100;
- else
- value=(int)temp_value;
-
- if(flag==wait_speak&&abs(angle-target)<=5)
- confirtime++;
- if(abs(angle-target)>=20) //如果角度差大于20度 將嗡鳴器設置為待激活狀態
- flag=wait_speak;
- if(confirtime==10&&(flag==wait_speak))
- {
- //beep_1s();
- sprintf(temp,"Achieve the goal:");//格式輸出電壓值,%3.2f 表示浮點輸出,共3位數,小數點后2位
- LCD_Write_String(0,1,temp);
- delay100us(10000);
- LCD_Clear(); //清屏
- flag=speaked;
- confirtime=0;
- }
-
-
-
- sprintf(temp,"DQJD:%3.2f ", angle);
- LCD_Write_String(0,0,temp);
- sprintf(temp,"SDJD:%d",(int)target);
- LCD_Write_String(0,1,temp);
- //sprintf(temp,"PWM:%d", value);
- //LCD_Write_String(10,1,temp);
- }
- //定時器1服務函數
- void Time1(void) interrupt 3
- {
- TH1 = 0x0FF;
- TL1 = 0x9C;
- timer1++;
- if(timer1>100) //PWM周期為100*100us
- {
- timer1=0;
- }
- if(timer1 <value)
- {
- PWM=1;
- }
- else
- {
- PWM=0;
- }
-
-
- }
- //定時器1初始化函數
- void Timer1Init()
- {
- TMOD|=0X10;//選擇為定時器1模式,工作方式1,僅用TR1打開啟動。
- TH1 = 0x0FF;
- TL1 = 0x9C;
- ET1=1;//打開定時器1中斷允許
- EA=1;//打開總中斷
- TR1=1;//打開定時器
- }
- void change_target()
- {
- unsigned char temp[7];//定義顯示區域臨時存儲數組
- if(target_up==0)
- {
- delay100us(100);
- if(target_up==0)
- { flag=wait_speak;
- while(target_up==0)
- {
- if(target<=80)
- target=45;
- sprintf(temp,"Target:%d",(int)target);//格式輸出電壓值,%3.2f 表示浮點輸出,共3位數,小數點后2位
- LCD_Write_String(0,1,temp);
- delay100us(1000);
-
- }
- }
- }
- if(target_down==0)
- {
- delay100us(100);
- if(target_down==0)
- { flag=wait_speak;
- while(target_down==0)
- {
- if(target>=10)
- target=0;
- sprintf(temp,"Target:%d",(int)target);//格式輸出電壓值,%3.2f 表示浮點輸出,共3位數,小數點后2位
- LCD_Write_String(0,1,temp);
- //delay10us(1000);
-
- }
- }
- }
- }
- void display()
- {
- // unsigned char temp[7];//定義顯示區域臨時存儲數組
- // sprintf(temp,"Reality: %3.2f ", angle);//格式輸出電壓值,%3.2f 表示浮點輸出,共3位數,小數點后2位
- // LCD_Write_String(0,0,temp);
- // sprintf(temp,"Target:%d",(int)target);//格式輸出電壓值,%3.2f 表示浮點輸出,共3位數,小數點后2位
- // LCD_Write_String(0,1,temp);
- // sprintf(temp,"PWM:%d", value);//格式輸出電壓值,%3.2f 表示浮點輸出,共3位數,小數點后2位
- // LCD_Write_String(9,1,temp);
- }
- void beep_1s()
- {
- unsigned char i;
- for(i=0;i<=200;i++)
- {
- delay100us(1);
- beep=~beep;
- }
- }
復制代碼
所有資料51hei提供下載:
新建 好壓 ZIP 壓縮文件.zip
(1.38 MB, 下載次數: 114)
2020-12-13 10:32 上傳
點擊文件名下載附件
源文件 下載積分: 黑幣 -5
|