基于51單片機(jī)的pwm和串口通信
此例程設(shè)置了按鍵可以調(diào)整100-1000hz的不同頻率(100的倍數(shù))的方波,另外還加入了串口通信,可以通過(guò)串口發(fā)送來(lái)的數(shù)字來(lái)設(shè)置相對(duì)應(yīng)的頻率;
#include
#include"uart.h"
sbit PWMOUT = P1^0;
sbit led = P2^2;
sbit KEY1 = P1^2;
sbit KEY2 = P3^3;
unsigned char HighRH = 0; //高電平重載值的高字節(jié)
unsigned char HighRL = 0; //高電平重載值的低字節(jié)
unsigned char LowRH = 0; //低電平重載值的高字節(jié)
unsigned char LowRL = 0; //低電平重載值的低字節(jié)
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; //按鍵值暫存,臨時(shí)保存按鍵的掃描值
bit keybuf2 = 1; //按鍵值暫存,臨時(shí)保存按鍵的掃描值
//keybuf1 = KEY1; //把當(dāng)前掃描值暫存
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; //把當(dāng)前掃描值暫存
if (keybuf1 != backup1) //當(dāng)前值與前次值不相等說(shuō)明此時(shí)按鍵有動(dòng)作
{
delay(1000); //延時(shí)大約10ms
if (keybuf1 == KEY1) //判斷掃描值有沒(méi)有發(fā)生改變,即按鍵抖動(dòng)
{
if (backup1 == 0) //如果前次值為0,則說(shuō)明當(dāng)前是彈起動(dòng)作
{
s = s-50;
}
backup1 = keybuf1; //更新備份為當(dāng)前值,以備進(jìn)行下次比較
}
ConfigPWM(s,50);
}
keybuf2 = KEY2; //把當(dāng)前掃描值暫存
if (keybuf2 != backup2) //當(dāng)前值與前次值不相等說(shuō)明此時(shí)按鍵有動(dòng)作
{
delay(1000); //延時(shí)大約10ms
if (keybuf2 == KEY2) //判斷掃描值有沒(méi)有發(fā)生改變,即按鍵抖動(dòng)
{
if (backup2 == 0) //如果前次值為0,則說(shuō)明當(dāng)前是彈起動(dòng)作
{
s = s+50;
}
backup2 = keybuf2; //更新備份為當(dāng)前值,以備進(jìn)行下次比較
}
ConfigPWM(s,50);
}
}
}
void ConfigUART(unsigned int baud)
{
SCON = 0x50; //配置串口為模式1
TMOD &= 0x0F; //清零T1的控制位
TMOD |= 0x20; //配置T1為模式2
TH1 = 256 - (11059200/12/32)/baud; //計(jì)算T1重載值
TL1 = TH1; //初值等于重載值
ET1 = 0; //中斷T1
ES = 1; //串口中斷
TR1 = 1; //啟動(dòng)T1
}
void ConfigPWM(unsigned int fr, unsigned char dc)
{
unsigned int high, low;
unsigned long tmp;
tmp = (11059200/12)/fr; //計(jì)算一個(gè)周期所需的計(jì)數(shù)值
high = (tmp*dc) / 100; //計(jì)算高電平所需的計(jì)數(shù)值
low = tmp - high; //計(jì)算低電平所需的計(jì)數(shù)值
high = 65536 - high + 12; //計(jì)算高電平的重載值并補(bǔ)償中斷延時(shí)
low = 65536 - low + 12; //計(jì)算低電平的重載值并補(bǔ)償中斷延時(shí)
HighRH = (unsigned char)(high>>8); //高電平重載值拆分為高低字節(jié)
HighRL = (unsigned char)high;
LowRH = (unsigned char)(low>>8); //低電平重載值拆分為高低字節(jié)
LowRL = (unsigned char)low;
TMOD &= 0xF0; //清零 T0 的控制位
TMOD |= 0x01; //配置 T0 為模式 1
TH0 = HighRH; //加載 T0 重載值
TL0 = HighRL;
ET0 = 1; //使能 T0 中斷
TR0 = 1; //啟動(dòng) T0
PWMOUT = 1; //輸出高電平
}
void InterruptTimer0() interrupt 1
{
if (PWMOUT == 1) //當(dāng)前輸出為高電平時(shí),裝載低電平值并輸出低電平
{
TH0 = LowRH;
TL0 = LowRL;
PWMOUT = 0;
}
else //當(dāng)前輸出為低電平時(shí),裝載高電平值并輸出高電平
{
TH0 = HighRH;
TL0 = HighRL;
PWMOUT = 1;
}
}
/*void Timer1Init()
{
TMOD|=0X10;//選擇為定時(shí)器1模式,工作方式1,僅用TR1打開(kāi)啟動(dòng)。
TH1=0XFC; //給定時(shí)器賦初值,定時(shí)1ms
TL1=0X18;
ET1=1;//打開(kāi)定時(shí)器1中斷允許
EA=1;//打開(kāi)總中斷
TR1=1;//打開(kāi)定時(shí)器
}
void Timer1() interrupt 3
{
static u16;
TH1=0XFC; //給定時(shí)器賦初值,定時(shí)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;
}
}