基于51单片机的pwm和串口通信
扫描二维码
随时随地手机看文章
此例程设置了按键可以调整100-1000hz的不同频率(100的倍数)的方波,另外还加入了串口通信,可以通过串口发送来的数字来设置相对应的频率;
#include
#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;
}
}