網友投稿 703 2022-05-29
編程實驗分別仿真和實驗臺操作兩種方式。
實驗1 AD轉換--輸入
AD轉換是所有嵌入式系統或機器人獲取外部信息的一種重要方式,將溫度、角度和位置等轉換為對應的數字量,供處理器處理。
原理圖:
程序:
/*************** ex1 ******************/
#include
#define uint unsigned int
#define uchar unsigned char
uchar code LEDData[]=
{
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
};
sbit OE = P1^0;
sbit EOC = P1^1;
sbit ST = P1^2;
sbit CLK = P1^3;
void DelayMS(uint ms)
uchar i;
while(ms--)
for(i=0;i<120;i++);
}
void Display_Result(uchar d)
P2 = 0xf7;
P0 = LEDData[d%10];
DelayMS(5);
P2 = 0xfb;
P0 = LEDData[d%100/10];
P2 = 0xfd;
P0 = LEDData[d/100];
void main()
TMOD = 0x02;
TH0 = 0x14;
TL0 = 0x00;
IE = 0x82;
TR0 = 1;
P1 = 0x3f;
while(1)
ST = 0;
ST = 1;
while(EOC == 0);
OE = 1;
Display_Result(P3);
OE = 0;
void Timer0_INT() interrupt 1
CLK = !CLK;
實驗臺,測量電壓值并顯示:
代碼:
//模數實驗
#include "reg52.h"
#define ulong unsigned long
sbit LE1=P3^3;
//定義數值顯示
uchar code xianshi[11]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xbE,0xE0,0xFE,0xF6,0x00};
sbit ST=P3^0; //起始
sbit OE=P3^1; //使能
sbit EOC=P3^2; //轉換完成標志位
sbit ADD_A=P3^5; //輸入端口選擇A
sbit ADD_B=P3^6; //輸入端口選擇B
sbit ADD_C=P3^7; //輸入端口選擇C
uint getdata,average,n,volt,sum; //變量
void delay1_ms(uint time) //延時
uint i,j;
for(i=0;ifor(j=0;j<123;j++);}void display_num1(uint dat,uchar num1) //顯示數值{// P2=0x00;// P0=0x00;P0=xianshi[dat];switch(num1){case 1: P2=0x01;break;case 2: P2=0x02;break;case 3: P2=0x04;break;case 4: P2=0x08;break;case 5: P2=0x10;break;case 6: P2=0x20;break;case 7: P2=0x40;break;case 8: P2=0x80;break;default: break;}delay1_ms(1);//P0=0x00;}//數碼管4位顯示函數void display_num4(uint num){uint wan;uint qian;uint bai;uint shi;uint ge;P2=0x00;wan=(num/10000)%10;if(wan==0) wan=10;display_num1(wan,5);qian=(num/1000)%10;if(wan==10&&qian==0) qian=10;display_num1(qian,4);bai=(num/100)%10;if(wan==10&&qian==10&&bai==0) bai=10;display_num1(bai,3);shi=(num/10)%10;if(wan==10&&qian==10&&bai==10&&shi==0) shi=10;display_num1(shi,2);ge=num%10;display_num1(ge,1);}void delay(uint N){while(N--);}uint adconvert_date(){ST=0;ST=1;delay(2);ST=0;while(!EOC);OE=1;delay(2);getdata=P1;delay(2);OE=0;return getdata;}void main(){uint i;uint n;uint volt;ulong sum=0;uint average;P2=0x00;ADD_A=0;ADD_B=0;ADD_C=0;delay(1000);while(1){ADD_A=0;ADD_B=0;ADD_C=0;ST=0;P2=0x00;for(n=0;n<10;n++){volt=adconvert_date(); //測量可變電阻電壓sum += volt; //累加次數50}average=sum/10; //取平均值average=average*19.4; //換算成電壓值 19.4=OKsum=0; //和清零for(i=0;i<400;i++)display_num4(average); //顯示平均值}}DA轉換將控制器結果轉為模擬量控制外部設備。最常用的實驗是波形仿真。數字調壓:代碼:#include #define uint unsigned int#define uchar unsigned charsbit K1 = P3^0;sbit K2 = P3^1;sbit K3 = P3^2;sbit K4 = P3^3;sbit K5 = P3^4;sbit K6 = P3^5;sbit K7 = P3^6;sbit K8 = P3^7;void DelayMS(uint ms){uchar i;while(ms--){for(i=0;i<120;i++);}}void main(){P2 = 0x00;while(1){if(K1 == 0) P2 = 0;if(K2 == 0) P2 = 35;if(K3 == 0) P2 = 70;if(K4 == 0) P2 = 105;if(K5 == 0) P2 = 140;if(K6 == 0) P2 = 175;if(K7 == 0) P2 = 210;if(K8 == 0) P2 = 255;DelayMS(2);}}代碼:#include #include #define uint unsigned int#define uchar unsigned char#define DAC0832 XBYTE[0xfffe]char code sin_data[256]={0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf4,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe3,0xe1,0xde,0xdc,0xda,0xd8,0xd6,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x92,0x8f,0x8c,0x89,0x86,0x83,0x80,0x7d,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x64,0x61,0x5e,0x5b,0x58,0x55,0x52,0x4f,0x4c,0x49,0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x14,0x12,0x10,0xf,0xd,0xc,0xb,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x3,0x2,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x2,0x3,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xc,0xd,0xe,0x10,0x12,0x13,0x15,0x17,0x18,0x1a,0x1c,0x1e,0x20,0x23,0x25,0x27,0x29,0x2c,0x2e,0x30,0x33,0x35,0x38,0x3b,0x3d,0x40,0x43,0x46,0x48,0x4b,0x4e,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c,0x6f,0x73,0x76,0x79,0x7c};//正弦碼表,可通過SIN()函數獲得void DelayMS(uint ms){uchar i;while(ms--){for(i=0;i<120;i++);}}void delay_nus(unsigned int i){unsigned int j;while(i--){for(j=0;j<127;j++);}}/**********************************************/void delay(unsigned char i){unsigned char t;for(t=0;t}/**********************************************輸出數據到端口(注意考慮延時)**********************************************/void conversion(unsigned char out_data){DAC0832 =out_data; //輸出數據delay(1);//delay_nus(10); //延時等待轉換}/************************************************產生正弦波函數************************************************/void sine(void){unsigned char i;for(i=0;i<255;i++){conversion(sin_data[i]);}}/***********************************************產生鋸齒波(下降型)***********************************************/void saw(void){unsigned char j;for(j=0;j<255;j++)conversion(j);}/***********************************************產生方波(脈沖)***********************************************/void pulse(void){conversion(0xff);delay_nus(1000);conversion(0x00);delay_nus(1000);}/***********************************************產生三角波***********************************************/void triangle(void){unsigned char k;for(k=0;k<255;k++)conversion(k);for(;k>0;k--)conversion(k);}void main(){while(1){// pulse();// saw();// sine();triangle();}}代碼:#include"reg52.h"char code sin_data[256]={0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf4,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe3,0xe1,0xde,0xdc,0xda,0xd8,0xd6,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x92,0x8f,0x8c,0x89,0x86,0x83,0x80,0x7d,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x64,0x61,0x5e,0x5b,0x58,0x55,0x52,0x4f,0x4c,0x49,0x46,0x43,0x41,0x3e,0x3b,0x39,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x14,0x12,0x10,0xf,0xd,0xc,0xb,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x3,0x2,0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x2,0x3,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xc,0xd,0xe,0x10,0x12,0x13,0x15,0x17,0x18,0x1a,0x1c,0x1e,0x20,0x23,0x25,0x27,0x29,0x2c,0x2e,0x30,0x33,0x35,0x38,0x3b,0x3d,0x40,0x43,0x46,0x48,0x4b,0x4e,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c,0x6f,0x73,0x76,0x79,0x7c};//正弦碼表,可通過SIN()函數獲得void delay_nus(unsigned int i){unsigned int j;while(i--){for(j=0;j<127;j++);}}/**********************************************/void delay(unsigned char i){unsigned char t;for(t=0;t}/**********************************************輸出數據到端口(注意考慮延時)**********************************************/void conversion(unsigned char out_data){P0=out_data; //輸出數據delay(5);//delay_nus(10); //延時等待轉換}/************************************************產生正弦波函數************************************************/void sine(void){unsigned char i;for(i=0;i<255;i++){conversion(sin_data[i]);}}/***********************************************產生鋸齒波(下降型)***********************************************/void saw(void){unsigned char j;for(j=0;j<255;j++)conversion(j);}/***********************************************產生方波(脈沖)***********************************************/void pulse(void){conversion(0xff);delay_nus(1000);conversion(0x00);delay_nus(1000);}/***********************************************產生三角波***********************************************/void triangle(void){unsigned char k;for(k=0;k<255;k++)conversion(k);for(;k>0;k--)conversion(k);}void main(){while(1){pulse();//saw();//sine();//triangle();}}實驗臺:代碼:#include"reg52.h"#include "math.h"#define uchar unsigned char#define uint unsigned intuchar code xianshi[12]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xbE,0xE0,0xFE,0xF6,0x9c,0x00};sbit PWM=P1^7;sbit key1=P1^0;sbit key2=P1^1;sbit key3=P1^2;uint wide=100;//脈寬計數uint t1=0; //低電平脈寬uint t2=0; //一個周期uint time_low=0;uint time_high=100;bit high_flag=0;bit low_flag=0;bit state_flag=0;uint set_count=100;//設定轉速值uint run_count=0;//實際頻率的讀取uint stop_count=0; //電機轉速存儲變量uint time=0;int en=0,en_1=0,en_2=0; //定義 三個時刻的誤差存儲變量float a0=1.7,a1=0.30,a2 =0.002,un=0; //定義PID計算參公式的參數void delay1_ms(uint time);void delay(uint time);void display_num1(uint dat,uchar num1);void display_num4(uint num);void time01_initiat(void);void key_precess(void);void pid(void);void main(){time01_initiat(); //初始化定時器0和定時器1while(1){key_precess(); //鍵盤掃描函數}}//1ms延時函數void delay1_ms(uint time){uint i,j;for(i=0;ifor(j=0;j<123;j++);}//指定的位上顯示 指定的一位數據void display_num1(uint dat,uchar num1){P0=xianshi[dat]; //段顯switch(num1){case 1: P2=0x01;break;case 2: P2=0x02;break;case 3: P2=0x04;break;case 4: P2=0x08;break;default: break;}delay1_ms(2);}//四位數據顯示函數void display_num4(uint num){uint qian;uint bai;uint shi;uint ge;qian=num/1000;if(qian==0)// qian=11;display_num1(11,4);bai=num%1000;bai=bai/100;if(qian==10&&bai==0) bai=10;display_num1(bai,3);shi=num%100;shi=shi/10;if(qian==10&&bai==10&&shi==0) shi=10;display_num1(shi,2);ge=num%10;display_num1(ge,1);}//四位數據顯示函數void display_num4_1(uint num){uint qian;uint bai;uint shi;uint ge;display_num1(10,4);bai=num%1000;bai=bai/100;if(qian==10&&bai==0) bai=10;display_num1(bai,3);shi=num%100;shi=shi/10;if(qian==10&&bai==10&&shi==0) shi=10;display_num1(shi,2);ge=num%10;display_num1(ge,1);}void delay(uint time){uint i;for(i=0;idisplay_num4_1(stop_count);}void delay1(uint num){uint i;for(i=0;idisplay_num4(set_count);}void time01_initiat(){TMOD=0X11; //計數器0和定時器1TL0=0X33;TH0=0XFE;//計數器0賦初值 0.5msTH1=0X4C;TL1=0X00;//定時器1賦初值 50msEA=1;PT0=1;ET0=1;ET1=1;TR0=0;TR1=0;IT0=1;EX0=0;}void key_precess(){if(key1==0&&key2==1&&key3==1) //判斷系統的運行模式,如果KEY1鍵 按下//且state_flag為1則系統處于運行模式,如果state__flag為0則為設置模式{while(key1==0);state_flag=~state_flag;if(state_flag==1){EX0=1;TR1=1;TR0=1;en =0;en_1 =0;en_2 =0;un =0;wide=150;//wide = set_count;}}if(key1==1&&key2==0&&key3==1&&state_flag==0) //KEY2為按鍵加{//while(key2==0);delay1(20);set_count+=1;if(set_count>300) set_count=100;}if(key1==1&&key2==1&&key3==0&&state_flag==0) //KEY3為按鍵減{// while(key3==0);delay1(20);if(set_count>100) set_count-=1;if(set_count==100) set_count=300;}if(state_flag==0) //如果系統處于設置模式,則關閉定時器中斷和外部中斷,同時初始化部分變量{PWM = 0;EX0=0;TR0=0;TR1=0;run_count=0;stop_count=0;time=0;t1=0;t2=0;display_num4(set_count);}if(state_flag==1) //如果系統處于運行模式則顯示電機的實際轉速值{display_num4_1(stop_count);}}void pid(void) //PID 計算輸出量{en=set_count-stop_count;un=1.7*en-0.03*en_1+0.002*en_2;//計算輸出量if(un > 400)un = 400;if(un <-400)un = -400;en_2=en_1; //更新誤差en_1=en;wide = wide + un/4; //計算wide,用于調節PWM的占空比,計算周期為100msif(wide>900)wide=900; //防止超限,確保計算餓wide值有效if(wide<10)wide=10;}//外部中斷0用于電機轉速測量void int0() interrupt 0{EX0=0;run_count++;EX0=1;}//定時器0用于產生PWM ,占空比通過PID計算獲得void time0() interrupt 1{TL0=0X9c;TH0=0XFF;//計數器0賦初值 100usTR0=0;if(low_flag==0)t1++;//低電平時間計時t2++;if(t2==1000) //用于確定PWM的周期 ,t2乘以定時器的中斷周期即為PWM的周期{PWM=1;t2=0;low_flag=0;}if(t1==wide)//wide的值即為低電平的時間{PWM=0;t1=0;low_flag=1;}TR0=1;}void time1() interrupt 3{TH1=0X3C;TL1=0XBD; //50ms定時TR1=0;time++;if(time==40) //定時2s到,讀取到的值run_count即為電機每秒的轉速值{stop_count=run_count/2;time=0;run_count=0;pid(); //調用PID算法}TR1=1;} 版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
for(j=0;j<123;j++);
void display_num1(uint dat,uchar num1) //顯示數值
// P2=0x00;
// P0=0x00;
P0=xianshi[dat];
switch(num1)
case 1: P2=0x01;break;
case 2: P2=0x02;break;
case 3: P2=0x04;break;
case 4: P2=0x08;break;
case 5: P2=0x10;break;
case 6: P2=0x20;break;
case 7: P2=0x40;break;
case 8: P2=0x80;break;
default: break;
delay1_ms(1);
//P0=0x00;
//數碼管4位顯示函數
void display_num4(uint num)
uint wan;
uint qian;
uint bai;
uint shi;
uint ge;
P2=0x00;
wan=(num/10000)%10;
if(wan==0) wan=10;
display_num1(wan,5);
qian=(num/1000)%10;
if(wan==10&&qian==0) qian=10;
display_num1(qian,4);
bai=(num/100)%10;
if(wan==10&&qian==10&&bai==0) bai=10;
display_num1(bai,3);
shi=(num/10)%10;
if(wan==10&&qian==10&&bai==10&&shi==0) shi=10;
display_num1(shi,2);
ge=num%10;
display_num1(ge,1);
void delay(uint N)
while(N--);
uint adconvert_date()
ST=0;
ST=1;
delay(2);
while(!EOC);
OE=1;
getdata=P1;
OE=0;
return getdata;
uint i;
uint n;
uint volt;
ulong sum=0;
uint average;
ADD_A=0;
ADD_B=0;
ADD_C=0;
delay(1000);
for(n=0;n<10;n++)
volt=adconvert_date(); //測量可變電阻電壓
sum += volt; //累加次數50
average=sum/10; //取平均值
average=average*19.4; //換算成電壓值 19.4=OK
sum=0; //和清零
for(i=0;i<400;i++)
display_num4(average); //顯示平均值
DA轉換將控制器結果轉為模擬量控制外部設備。最常用的實驗是波形仿真。
數字調壓:
sbit K1 = P3^0;
sbit K2 = P3^1;
sbit K3 = P3^2;
sbit K4 = P3^3;
sbit K5 = P3^4;
sbit K6 = P3^5;
sbit K7 = P3^6;
sbit K8 = P3^7;
P2 = 0x00;
if(K1 == 0) P2 = 0;
if(K2 == 0) P2 = 35;
if(K3 == 0) P2 = 70;
if(K4 == 0) P2 = 105;
if(K5 == 0) P2 = 140;
if(K6 == 0) P2 = 175;
if(K7 == 0) P2 = 210;
if(K8 == 0) P2 = 255;
DelayMS(2);
#define DAC0832 XBYTE[0xfffe]
char code sin_data[256]={0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,
0xab,0xae,0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,
0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf4,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,
0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe3,0xe1,0xde,0xdc,0xda,0xd8,0xd6,
0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb4,0xb1,0xae,0xab,0xa8,
0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x92,0x8f,0x8c,0x89,0x86,0x83,0x80,0x7d,0x79,0x76,0x73,
0x70,0x6d,0x6a,0x67,0x64,0x61,0x5e,0x5b,0x58,0x55,0x52,0x4f,0x4c,0x49,0x46,0x43,0x41,
0x3e,0x3b,0x39,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,
0x17,0x15,0x14,0x12,0x10,0xf,0xd,0xc,0xb,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x3,0x2,0x1,0x1,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x2,0x3,0x3,0x4,0x5,0x6,0x7,0x8,
0x9,0xa,0xc,0xd,0xe,0x10,0x12,0x13,0x15,0x17,0x18,0x1a,0x1c,0x1e,0x20,0x23,0x25,0x27,
0x29,0x2c,0x2e,0x30,0x33,0x35,0x38,0x3b,0x3d,0x40,0x43,0x46,0x48,0x4b,0x4e,0x51,0x54,
0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c,0x6f,0x73,0x76,0x79,0x7c};//正弦碼表,可通過SIN()函數獲得
void delay_nus(unsigned int i)
unsigned int j;
while(i--)
for(j=0;j<127;j++);
/**********************************************/
void delay(unsigned char i)
unsigned char t;
for(t=0;t
/**********************************************
輸出數據到端口(注意考慮延時)
**********************************************/
void conversion(unsigned char out_data)
DAC0832 =out_data; //輸出數據
delay(1);
//delay_nus(10); //延時等待轉換
/************************************************
產生正弦波函數
************************************************/
void sine(void)
unsigned char i;
for(i=0;i<255;i++)
conversion(sin_data[i]);
/***********************************************
產生鋸齒波(下降型)
***********************************************/
void saw(void)
unsigned char j;
for(j=0;j<255;j++)
conversion(j);
產生方波(脈沖)
void pulse(void)
conversion(0xff);
delay_nus(1000);
conversion(0x00);
產生三角波
void triangle(void)
unsigned char k;
for(k=0;k<255;k++)
conversion(k);
for(;k>0;k--)
// pulse();
// saw();
// sine();
triangle();
#include"reg52.h"
P0=out_data; //輸出數據
delay(5);
pulse();
//saw();
//sine();
//triangle();
實驗臺:
#include "math.h"
uchar code xianshi[12]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xbE,0xE0,0xFE,0xF6,0x9c,0x00};
sbit PWM=P1^7;
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;
uint wide=100;//脈寬計數
uint t1=0; //低電平脈寬
uint t2=0; //一個周期
uint time_low=0;
uint time_high=100;
bit high_flag=0;
bit low_flag=0;
bit state_flag=0;
uint set_count=100;//設定轉速值
uint run_count=0;//實際頻率的讀取
uint stop_count=0; //電機轉速存儲變量
uint time=0;
int en=0,en_1=0,en_2=0; //定義 三個時刻的誤差存儲變量
float a0=1.7,a1=0.30,a2 =0.002,un=0; //定義PID計算參公式的參數
void delay1_ms(uint time);
void delay(uint time);
void display_num1(uint dat,uchar num1);
void display_num4(uint num);
void time01_initiat(void);
void key_precess(void);
void pid(void);
time01_initiat(); //初始化定時器0和定時器1
key_precess(); //鍵盤掃描函數
//1ms延時函數
void delay1_ms(uint time)
for(i=0;ifor(j=0;j<123;j++);}//指定的位上顯示 指定的一位數據void display_num1(uint dat,uchar num1){P0=xianshi[dat]; //段顯switch(num1){case 1: P2=0x01;break;case 2: P2=0x02;break;case 3: P2=0x04;break;case 4: P2=0x08;break;default: break;}delay1_ms(2);}//四位數據顯示函數void display_num4(uint num){uint qian;uint bai;uint shi;uint ge;qian=num/1000;if(qian==0)// qian=11;display_num1(11,4);bai=num%1000;bai=bai/100;if(qian==10&&bai==0) bai=10;display_num1(bai,3);shi=num%100;shi=shi/10;if(qian==10&&bai==10&&shi==0) shi=10;display_num1(shi,2);ge=num%10;display_num1(ge,1);}//四位數據顯示函數void display_num4_1(uint num){uint qian;uint bai;uint shi;uint ge;display_num1(10,4);bai=num%1000;bai=bai/100;if(qian==10&&bai==0) bai=10;display_num1(bai,3);shi=num%100;shi=shi/10;if(qian==10&&bai==10&&shi==0) shi=10;display_num1(shi,2);ge=num%10;display_num1(ge,1);}void delay(uint time){uint i;for(i=0;idisplay_num4_1(stop_count);}void delay1(uint num){uint i;for(i=0;idisplay_num4(set_count);}void time01_initiat(){TMOD=0X11; //計數器0和定時器1TL0=0X33;TH0=0XFE;//計數器0賦初值 0.5msTH1=0X4C;TL1=0X00;//定時器1賦初值 50msEA=1;PT0=1;ET0=1;ET1=1;TR0=0;TR1=0;IT0=1;EX0=0;}void key_precess(){if(key1==0&&key2==1&&key3==1) //判斷系統的運行模式,如果KEY1鍵 按下//且state_flag為1則系統處于運行模式,如果state__flag為0則為設置模式{while(key1==0);state_flag=~state_flag;if(state_flag==1){EX0=1;TR1=1;TR0=1;en =0;en_1 =0;en_2 =0;un =0;wide=150;//wide = set_count;}}if(key1==1&&key2==0&&key3==1&&state_flag==0) //KEY2為按鍵加{//while(key2==0);delay1(20);set_count+=1;if(set_count>300) set_count=100;}if(key1==1&&key2==1&&key3==0&&state_flag==0) //KEY3為按鍵減{// while(key3==0);delay1(20);if(set_count>100) set_count-=1;if(set_count==100) set_count=300;}if(state_flag==0) //如果系統處于設置模式,則關閉定時器中斷和外部中斷,同時初始化部分變量{PWM = 0;EX0=0;TR0=0;TR1=0;run_count=0;stop_count=0;time=0;t1=0;t2=0;display_num4(set_count);}if(state_flag==1) //如果系統處于運行模式則顯示電機的實際轉速值{display_num4_1(stop_count);}}void pid(void) //PID 計算輸出量{en=set_count-stop_count;un=1.7*en-0.03*en_1+0.002*en_2;//計算輸出量if(un > 400)un = 400;if(un <-400)un = -400;en_2=en_1; //更新誤差en_1=en;wide = wide + un/4; //計算wide,用于調節PWM的占空比,計算周期為100msif(wide>900)wide=900; //防止超限,確保計算餓wide值有效if(wide<10)wide=10;}//外部中斷0用于電機轉速測量void int0() interrupt 0{EX0=0;run_count++;EX0=1;}//定時器0用于產生PWM ,占空比通過PID計算獲得void time0() interrupt 1{TL0=0X9c;TH0=0XFF;//計數器0賦初值 100usTR0=0;if(low_flag==0)t1++;//低電平時間計時t2++;if(t2==1000) //用于確定PWM的周期 ,t2乘以定時器的中斷周期即為PWM的周期{PWM=1;t2=0;low_flag=0;}if(t1==wide)//wide的值即為低電平的時間{PWM=0;t1=0;low_flag=1;}TR0=1;}void time1() interrupt 3{TH1=0X3C;TL1=0XBD; //50ms定時TR1=0;time++;if(time==40) //定時2s到,讀取到的值run_count即為電機每秒的轉速值{stop_count=run_count/2;time=0;run_count=0;pid(); //調用PID算法}TR1=1;} 版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
//指定的位上顯示 指定的一位數據
void display_num1(uint dat,uchar num1)
P0=xianshi[dat]; //段顯
delay1_ms(2);
//四位數據顯示函數
qian=num/1000;
if(qian==0)// qian=11;
display_num1(11,4);
bai=num%1000;
bai=bai/100;
if(qian==10&&bai==0) bai=10;
shi=num%100;
shi=shi/10;
if(qian==10&&bai==10&&shi==0) shi=10;
void display_num4_1(uint num)
display_num1(10,4);
void delay(uint time)
for(i=0;idisplay_num4_1(stop_count);}void delay1(uint num){uint i;for(i=0;idisplay_num4(set_count);}void time01_initiat(){TMOD=0X11; //計數器0和定時器1TL0=0X33;TH0=0XFE;//計數器0賦初值 0.5msTH1=0X4C;TL1=0X00;//定時器1賦初值 50msEA=1;PT0=1;ET0=1;ET1=1;TR0=0;TR1=0;IT0=1;EX0=0;}void key_precess(){if(key1==0&&key2==1&&key3==1) //判斷系統的運行模式,如果KEY1鍵 按下//且state_flag為1則系統處于運行模式,如果state__flag為0則為設置模式{while(key1==0);state_flag=~state_flag;if(state_flag==1){EX0=1;TR1=1;TR0=1;en =0;en_1 =0;en_2 =0;un =0;wide=150;//wide = set_count;}}if(key1==1&&key2==0&&key3==1&&state_flag==0) //KEY2為按鍵加{//while(key2==0);delay1(20);set_count+=1;if(set_count>300) set_count=100;}if(key1==1&&key2==1&&key3==0&&state_flag==0) //KEY3為按鍵減{// while(key3==0);delay1(20);if(set_count>100) set_count-=1;if(set_count==100) set_count=300;}if(state_flag==0) //如果系統處于設置模式,則關閉定時器中斷和外部中斷,同時初始化部分變量{PWM = 0;EX0=0;TR0=0;TR1=0;run_count=0;stop_count=0;time=0;t1=0;t2=0;display_num4(set_count);}if(state_flag==1) //如果系統處于運行模式則顯示電機的實際轉速值{display_num4_1(stop_count);}}void pid(void) //PID 計算輸出量{en=set_count-stop_count;un=1.7*en-0.03*en_1+0.002*en_2;//計算輸出量if(un > 400)un = 400;if(un <-400)un = -400;en_2=en_1; //更新誤差en_1=en;wide = wide + un/4; //計算wide,用于調節PWM的占空比,計算周期為100msif(wide>900)wide=900; //防止超限,確保計算餓wide值有效if(wide<10)wide=10;}//外部中斷0用于電機轉速測量void int0() interrupt 0{EX0=0;run_count++;EX0=1;}//定時器0用于產生PWM ,占空比通過PID計算獲得void time0() interrupt 1{TL0=0X9c;TH0=0XFF;//計數器0賦初值 100usTR0=0;if(low_flag==0)t1++;//低電平時間計時t2++;if(t2==1000) //用于確定PWM的周期 ,t2乘以定時器的中斷周期即為PWM的周期{PWM=1;t2=0;low_flag=0;}if(t1==wide)//wide的值即為低電平的時間{PWM=0;t1=0;low_flag=1;}TR0=1;}void time1() interrupt 3{TH1=0X3C;TL1=0XBD; //50ms定時TR1=0;time++;if(time==40) //定時2s到,讀取到的值run_count即為電機每秒的轉速值{stop_count=run_count/2;time=0;run_count=0;pid(); //調用PID算法}TR1=1;} 版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
display_num4_1(stop_count);
void delay1(uint num)
for(i=0;idisplay_num4(set_count);}void time01_initiat(){TMOD=0X11; //計數器0和定時器1TL0=0X33;TH0=0XFE;//計數器0賦初值 0.5msTH1=0X4C;TL1=0X00;//定時器1賦初值 50msEA=1;PT0=1;ET0=1;ET1=1;TR0=0;TR1=0;IT0=1;EX0=0;}void key_precess(){if(key1==0&&key2==1&&key3==1) //判斷系統的運行模式,如果KEY1鍵 按下//且state_flag為1則系統處于運行模式,如果state__flag為0則為設置模式{while(key1==0);state_flag=~state_flag;if(state_flag==1){EX0=1;TR1=1;TR0=1;en =0;en_1 =0;en_2 =0;un =0;wide=150;//wide = set_count;}}if(key1==1&&key2==0&&key3==1&&state_flag==0) //KEY2為按鍵加{//while(key2==0);delay1(20);set_count+=1;if(set_count>300) set_count=100;}if(key1==1&&key2==1&&key3==0&&state_flag==0) //KEY3為按鍵減{// while(key3==0);delay1(20);if(set_count>100) set_count-=1;if(set_count==100) set_count=300;}if(state_flag==0) //如果系統處于設置模式,則關閉定時器中斷和外部中斷,同時初始化部分變量{PWM = 0;EX0=0;TR0=0;TR1=0;run_count=0;stop_count=0;time=0;t1=0;t2=0;display_num4(set_count);}if(state_flag==1) //如果系統處于運行模式則顯示電機的實際轉速值{display_num4_1(stop_count);}}void pid(void) //PID 計算輸出量{en=set_count-stop_count;un=1.7*en-0.03*en_1+0.002*en_2;//計算輸出量if(un > 400)un = 400;if(un <-400)un = -400;en_2=en_1; //更新誤差en_1=en;wide = wide + un/4; //計算wide,用于調節PWM的占空比,計算周期為100msif(wide>900)wide=900; //防止超限,確保計算餓wide值有效if(wide<10)wide=10;}//外部中斷0用于電機轉速測量void int0() interrupt 0{EX0=0;run_count++;EX0=1;}//定時器0用于產生PWM ,占空比通過PID計算獲得void time0() interrupt 1{TL0=0X9c;TH0=0XFF;//計數器0賦初值 100usTR0=0;if(low_flag==0)t1++;//低電平時間計時t2++;if(t2==1000) //用于確定PWM的周期 ,t2乘以定時器的中斷周期即為PWM的周期{PWM=1;t2=0;low_flag=0;}if(t1==wide)//wide的值即為低電平的時間{PWM=0;t1=0;low_flag=1;}TR0=1;}void time1() interrupt 3{TH1=0X3C;TL1=0XBD; //50ms定時TR1=0;time++;if(time==40) //定時2s到,讀取到的值run_count即為電機每秒的轉速值{stop_count=run_count/2;time=0;run_count=0;pid(); //調用PID算法}TR1=1;} 版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
display_num4(set_count);
void time01_initiat()
TMOD=0X11; //計數器0和定時器1
TL0=0X33;
TH0=0XFE;//計數器0賦初值 0.5ms
TH1=0X4C;
TL1=0X00;//定時器1賦初值 50ms
EA=1;
PT0=1;
ET0=1;
ET1=1;
TR0=0;
TR1=0;
IT0=1;
EX0=0;
void key_precess()
if(key1==0&&key2==1&&key3==1) //判斷系統的運行模式,如果KEY1鍵 按下
//且state_flag為1則系統處于運行模式,如果state__flag為0則為設置模式
while(key1==0);
state_flag=~state_flag;
if(state_flag==1)
EX0=1;
TR1=1;
TR0=1;
en =0;
en_1 =0;
en_2 =0;
un =0;
wide=150;
//wide = set_count;
if(key1==1&&key2==0&&key3==1&&state_flag==0) //KEY2為按鍵加
//while(key2==0);
delay1(20);
set_count+=1;
if(set_count>300) set_count=100;
if(key1==1&&key2==1&&key3==0&&state_flag==0) //KEY3為按鍵減
// while(key3==0);
if(set_count>100) set_count-=1;
if(set_count==100) set_count=300;
if(state_flag==0) //如果系統處于設置模式,則關閉定時器中斷和外部中斷,同時初始化部分變量
PWM = 0;
run_count=0;
stop_count=0;
time=0;
t1=0;
t2=0;
if(state_flag==1) //如果系統處于運行模式則顯示電機的實際轉速值
void pid(void) //PID 計算輸出量
en=set_count-stop_count;
un=1.7*en-0.03*en_1+0.002*en_2;//計算輸出量
if(un > 400)un = 400;
if(un <-400)un = -400;
en_2=en_1; //更新誤差
en_1=en;
wide = wide + un/4; //計算wide,用于調節PWM的占空比,計算周期為100ms
if(wide>900)wide=900; //防止超限,確保計算餓wide值有效
if(wide<10)wide=10;
//外部中斷0用于電機轉速測量
void int0() interrupt 0
run_count++;
//定時器0用于產生PWM ,占空比通過PID計算獲得
void time0() interrupt 1
TL0=0X9c;
TH0=0XFF;//計數器0賦初值 100us
if(low_flag==0)t1++;//低電平時間計時
t2++;
if(t2==1000) //用于確定PWM的周期 ,t2乘以定時器的中斷周期即為PWM的周期
PWM=1;
low_flag=0;
if(t1==wide)//wide的值即為低電平的時間
PWM=0;
low_flag=1;
void time1() interrupt 3
TH1=0X3C;
TL1=0XBD; //50ms定時
time++;
if(time==40) //定時2s到,讀取到的值run_count即為電機每秒的轉速值
stop_count=run_count/2;
pid(); //調用PID算法
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。