| | | | | 原代码如下,初学,自己就注释的很啰嗦
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit off = P1^4; //S1 duty=0 PWM 输出
sbit full =P1^5; //S2 duty=100% PWM 输出
sbit down = P1^6; //S3 duty减小 PWM输出
sbit up = P1^7; //S4 duty增加 PWM输出
uint t,PWM_T;
void delay(uint);
void init();
/****************************************************
主程序
****************************************************/
void main()
{
init();
PWM_T=130; //开机保持duty=130/250
while(1)
{
if(!full) //检测 S2 键是否按下
{
delay(5);
PWM_T = 0xff;
}
if(!off)
{
delay(5);
PWM_T = 0x00;
}
if(!up)
{
delay(5);
if(PWM_T<250)
{
PWM_T++;
}
}
if(!down)
{
delay(5);
if(PWM_T>0)
{
PWM_T--;
}
}
}
}
|
|
|
| | | | | /****************************************************
初始化子程序
****************************************************/
void init()
{
TMOD = 0x02; //定时器0,工作模式2,8位定时模式
TH0=210; //写入预置初值(取值1-255,数越大PWM频率越高)
TL0=210; //写入预置值 (取值1-255,数越大PWM频率越高)
TR0=1; //启动定时器
ET0=1; //允许定时器0中断
EA=1; //允许总中断
P0=0xff; //初始化P0,输出端口
}
/****************************************************
延时子程序
****************************************************/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=120;y>0;y--);
}
/****************************************************
定时器0中断模拟PWM
****************************************************/
void timer0() interrupt 1
{
t++; //每次定时器中断溢出加1
if(t==255) //PWM周期 100个单位
{
t=0; //重置 t,开始新的PWM周期
P0=0x00; //输出端口置低
}
if(PWM_T==t) //按照当前占空比切换输出为高电平
{
P0=0xff; //输出端口置高
}
}
|
|
|
|
|
| | | | | | | | | | | 好像有个口是开漏(OC)输出吧,多年不搞单片机了,忘了。 |
|
|
| | | | | | | | | | | | | 增加驱动,只是加上拉电阻就OK了
似乎并不影响用它来模拟 PWM output 吧? 不懂,求解
|
|
|
| | | | | | | | | | | | | | | P0口用作输出如不加上拉电阻是没有“1”的,为高阻态。作为输入则不需上拉。 |
|
|
| | | | | | | | | | | | | | | | | 上面的电路图是 proteus 仿真图,后面是虚拟仪器示波器
P0 口类似 OC 门一样,在实际应用中是需要上拉电阻才能实现功能的 |
|
|
|
|
|