基於51微控制器的pwm和串列埠通訊
阿新 • • 發佈:2019-01-10
此例程設定了按鍵可以調整100-1000hz的不同頻率(100的倍數)的方波,另外還加入了串列埠通訊,可以通過串列埠傳送來的數字來設定相對應的頻率;
#include <reg52.h> #include"uart.h" sbit PWMOUT = P1^0; sbit led = P2^2; sbit KEY1 = P1^2; sbit KEY2 = P3^3; unsigned char HighRH = 0; //高電平過載值的高位元組 unsigned char HighRL = 0; //高電平過載值的低位元組 unsigned char LowRH = 0; //低電平過載值的高位元組 unsigned char LowRL = 0; //低電平過載值的低位元組 unsigned int fr; unsigned int k=0,t,i; unsigned int s= 100; unsigned char a[3]; unsigned int b=0; void ConfigPWM(unsigned int fr, unsigned char dc); void ConfigUART(unsigned int baud); void delay(unsigned int n){ while (n--);} void main() { bit backup1 = 1; bit backup2 = 1; bit keybuf1 = 1; //按鍵值暫存,臨時儲存按鍵的掃描值 bit keybuf2 = 1; //按鍵值暫存,臨時儲存按鍵的掃描值 //keybuf1 = KEY1; //把當前掃描值暫存 EA=1; led = 0; ConfigUART(9600); //配置波特率為9600 ConfigPWM(100,50); //Timer1Init(); while (1) { if(k==1) { k=0; ConfigPWM(s,50); led = ~led;delay(2000); } keybuf1 = KEY1; //把當前掃描值暫存 if (keybuf1 != backup1) //當前值與前次值不相等說明此時按鍵有動作 { delay(1000); //延時大約10ms if (keybuf1 == KEY1) //判斷掃描值有沒有發生改變,即按鍵抖動 { if (backup1 == 0) //如果前次值為0,則說明當前是彈起動作 { s = s-50; } backup1 = keybuf1; //更新備份為當前值,以備進行下次比較 } ConfigPWM(s,50); } keybuf2 = KEY2; //把當前掃描值暫存 if (keybuf2 != backup2) //當前值與前次值不相等說明此時按鍵有動作 { delay(1000); //延時大約10ms if (keybuf2 == KEY2) //判斷掃描值有沒有發生改變,即按鍵抖動 { if (backup2 == 0) //如果前次值為0,則說明當前是彈起動作 { s = s+50; } backup2 = keybuf2; //更新備份為當前值,以備進行下次比較 } ConfigPWM(s,50); } } } void ConfigUART(unsigned int baud) { SCON = 0x50; //配置串列埠為模式1 TMOD &= 0x0F; //清零T1的控制位 TMOD |= 0x20; //配置T1為模式2 TH1 = 256 - (11059200/12/32)/baud; //計算T1過載值 TL1 = TH1; //初值等於過載值 ET1 = 0; //中斷T1 ES = 1; //串列埠中斷 TR1 = 1; //啟動T1 } void ConfigPWM(unsigned int fr, unsigned char dc) { unsigned int high, low; unsigned long tmp; tmp = (11059200/12)/fr; //計算一個週期所需的計數值 high = (tmp*dc) / 100; //計算高電平所需的計數值 low = tmp - high; //計算低電平所需的計數值 high = 65536 - high + 12; //計算高電平的過載值並補償中斷延時 low = 65536 - low + 12; //計算低電平的過載值並補償中斷延時 HighRH = (unsigned char)(high>>8); //高電平過載值拆分為高低位元組 HighRL = (unsigned char)high; LowRH = (unsigned char)(low>>8); //低電平過載值拆分為高低位元組 LowRL = (unsigned char)low; TMOD &= 0xF0; //清零 T0 的控制位 TMOD |= 0x01; //配置 T0 為模式 1 TH0 = HighRH; //載入 T0 過載值 TL0 = HighRL; ET0 = 1; //使能 T0 中斷 TR0 = 1; //啟動 T0 PWMOUT = 1; //輸出高電平 } void InterruptTimer0() interrupt 1 { if (PWMOUT == 1) //當前輸出為高電平時,裝載低電平值並輸出低電平 { TH0 = LowRH; TL0 = LowRL; PWMOUT = 0; } else //當前輸出為低電平時,裝載高電平值並輸出高電平 { TH0 = HighRH; TL0 = HighRL; PWMOUT = 1; } } /*void Timer1Init() { TMOD|=0X10;//選擇為定時器1模式,工作方式1,僅用TR1開啟啟動。 TH1=0XFC; //給定時器賦初值,定時1ms TL1=0X18; ET1=1;//開啟定時器1中斷允許 EA=1;//開啟總中斷 TR1=1;//開啟定時器 } void Timer1() interrupt 3 { static u16; TH1=0XFC; //給定時器賦初值,定時1ms TL1=0X18; i++; if(i==1000) { i=0; t++; if(t%2==0) { SBUF=t/10; SBUF=t%10; } } }*/ void ComINT() interrupt 4 //中斷接收程式 { if(RI) //判斷是否接收完,接收完成後,由硬體置RI位 { RI=0; //SBUF=SBUF; a[b]=SBUF; b++; if(b==3) { /*if(a[0]=='a'&&a[1]=='b'&&a[2]=='c') {led = 0;delay(2000);} else {led = 1;}*/ b=0;s=(a[0]-0x30)*100+(a[1]-0x30)*10+(a[2]-0x30); k=1; //SBUF = 'T'; } } if(TI) { TI=0; } }