求高人给我发几个关于C51单片机PWM的编程实例

发布网友 发布时间:2022-04-23 22:51

我来回答

3个回答

热心网友 时间:2023-11-01 19:17

共两个:
/*********************************************************************************************
程序名: 触控调光台灯
编写人: 杜洋
编写时间: 2009年 7月 25日
硬件支持: STC12C2052 12MHz
接口说明: P3.7(PWM0)用PWM控制LED,P1.5~P1.7接3路触摸键
修改日志:
NO.1-20090725_0622 完成触控开关LED灯部分和PWM调光部分程序。
NO.2-20090725_0638 完成开关灯时的渐变亮度。
/*********************************************************************************************
说明:电路制作时需要将触摸键和VCC线放在一起,然后触摸时将手同时触摸按键引脚和VCC线。

/*********************************************************************************************/

#include <STC12C2052AD.H> //STC12Cx052或STC12Cx052AD系列单片机头文件

sbit ON_OFF_Key = P1 ^ 7; //ON/OFF开关键
sbit Add_Key = P1 ^ 6; //加亮度(+)
sbit Doc_Key = P1 ^ 5; //减亮度(-)
//LED与P3.7(PWM0)连接

unsigned char Bright=0x88; //全局变量,亮度值
bit POWER=0; //LED灯开/关状态标志位

/*********************************************************************************************
函数名:PWM初始化函数
调 用:PWM_init();
参 数:无
返回值:无
结 果:将PCA初始化为PWM模式,初始占空比为0
备 注:需要更多路PWM输出直接插入CCAPnH和CCAPnL即可
/**********************************************************************************************/
void PWM_init (void){
CMOD=0x02; //设置PCA定时器
CL=0x00;
CH=0x00;
CCAPM0=0x42; //PWM0设置PCA工作方式为PWM方式(0100 0010)
CCAP0L=0x00; //设置PWM0初始值与CCAP0H相同
CCAP0H=0x00; // PWM0初始时为0
CR=1; //启动PCA定时器
}
/**********************************************************************************************/

/*********************************************************************************************
函数名:PWM0占空比设置函数
调 用:PWM0_set();
参 数:0x00~0xFF(亦可用0~255)
返回值:无
结 果:设置PWM模式占空比,为0时全部高电平,为1时全部低电平
备 注:如果需要PWM1的设置函数,只要把CCAP0L和CCAP0H中的0改为1即可
/**********************************************************************************************/
void PWM0_set (unsigned char a){
CCAP0L= a; //设置值直接写入CCAP0L
CCAP0H= a; //设置值直接写入CCAP0H
}
/**********************************************************************************************/

/*********************************************************************************************
函数名:毫秒级CPU延时函数
调 用:DELAY_MS (?);
参 数:1~65535(参数不可为0)
返回值:无
结 果:占用CPU方式延时与参数数值相同的毫秒时间
备 注:应用于1T单片机时i<600,应用于12T单片机时i<125
/*********************************************************************************************/
void DELAY_MS (unsigned int a){
unsigned int i;
while( --a != 0){
for(i = 0; i < 600; i++);
}
}
/*********************************************************************************************/

/*********************************************************************************************
函数名:主函数
调 用:无
参 数:无
返回值:无
结 果:程序开始处,无限循环
备 注:
/**********************************************************************************************/
void main (void){
PWM_init(); //PWM初始化

P1M0 = 0xff; //将P1接口设置为高阻态输入
P1M1 = 0x00; //触摸按键启用

DELAY_MS (200); //延时等待I/O接口电平状态稳定

while(1){ //循环程序部分
unsigned char a; //临时变量

if(ON_OFF_Key == 1){ //开关键按下
if(POWER == 0){ //如果当前状态为关,则执行开灯程序
for(a=0;a<=Bright;a++){ //
PWM0_set(a);
DELAY_MS (20); //渐暗的时间间隔
}
PWM0_set(Bright); //达到存储的LED亮度
POWER = 1; //把状态标志位变成开
}else{ //如果当前状态为开,则执行关灯程序
for(a=Bright;a>0;a--){ //循环渐暗
PWM0_set(a);
DELAY_MS (20); //渐暗的时间间隔
}
PWM0_set(0); //关LED
POWER = 0; //把状态标志位变成关
}
while(ON_OFF_Key == 1); //等待按键放开
}

if(Add_Key == 1 && POWER == 1){ //加亮度键按下,同时在开灯状态下
Bright++; //亮度值加1
PWM0_set(Bright); //将值写入PWM控制LED亮度
if(Bright >= 0xFD){ //如果亮度值大于0xFD,则不再增加
Bright = 0xFD;
}
DELAY_MS (20); //渐变亮度的时间间隔
}

if(Doc_Key == 1 && POWER == 1){ //减亮度键按下,同时在开灯状态下
Bright--; //亮度值减1
PWM0_set(Bright); //将值写入PWM控制LED亮度
if(Bright < 0x08){ //如果亮度值小于0x08,则不再减少
Bright = 0x08;
}
DELAY_MS (20); //渐变亮度的时间间隔
}
}
}
/**********************************************************************************************/

/*************************************************************
* 杜洋工作室 DoYoung Studio
* 与电子爱好者同行 www.DoYoung.net
/*************************************************************/

/*********************************************************************************************
程序名: PWM模块调试程序(仅实验用)
编写人: 杜洋
编写时间: 2009年7月22日
硬件支持: STC12C2052 12MHz
接口说明: LED灌电流接P3.7接口(PWM0)
修改日志:
NO.1-
/*********************************************************************************************
说明:

/*********************************************************************************************/

#include<STC12C2052AD.H> //头文件

/*********************************************************************************************
函数名:PWM初始化函数
调 用:PWM_init();
参 数:无
返回值:无
结 果:将PCA初始化为PWM模式,初始占空比为0
备 注:需要更多路PWM输出直接插入CCAPnH和CCAPnL即可
/**********************************************************************************************/
void PWM_init (void){
CMOD=0x02; //设置PCA定时器
CL=0x00;
CH=0x00;
CCAPM0=0x42; //PWM0设置PCA工作方式为PWM方式(0100 0010)
CCAP0L=0x00; //设置PWM0初始值与CCAP0H相同
CCAP0H=0x00; // PWM0初始时为0

//CCAPM1=0x42; //PWM1设置PCA工作方式为PWM方式(使用时删除//)
//CCAP1L=0x00; //设置PWM1初始值与CCAP0H相同
//CCAP1H=0x00; // PWM1初始时为0

//CCAPM2=0x42; //PWM2设置PCA工作方式为PWM方式
//CCAP2L=0x00; //设置PWM2初始值与CCAP0H相同
//CCAP2H=0x00; // PWM2初始时为0

//CCAPM3=0x42; //PWM3设置PCA工作方式为PWM方式
//CCAP3L=0x00; //设置PWM3初始值与CCAP0H相同
//CCAP3H=0x00; // PWM3初始时为0

CR=1; //启动PCA定时器
}
/**********************************************************************************************/

/*********************************************************************************************
函数名:PWM0占空比设置函数
调 用:PWM0_set();
参 数:0x00~0xFF(亦可用0~255)
返回值:无
结 果:设置PWM模式占空比,为0时全部高电平,为1时全部低电平
备 注:如果需要PWM1的设置函数,只要把CCAP0L和CCAP0H中的0改为1即可
/**********************************************************************************************/
void PWM0_set (unsigned char a){
CCAP0L= a; //设置值直接写入CCAP0L
CCAP0H= a; //设置值直接写入CCAP0H
}
/**********************************************************************************************/

/*********************************************************************************************
函数名:主函数
调 用:无
参 数:无
返回值:无
结 果:程序开始处,无限循环
备 注:
/**********************************************************************************************/
void main (void){

PWM_init(); //PWM初始化
PWM0_set(0x10); //设置PWM占空比

while(1){

//无限循环程序

}
}
/**********************************************************************************************/
/*************************************************************
* 杜洋工作室 DoYoung Studio
* 与电子爱好者同行 www.DoYoung.net
/*************************************************************/

热心网友 时间:2023-11-01 19:17

我试了几次都传不上图去,我把管脚定义说一下吧。
P1.0—P1.4接5个对地键,分别作为:顺时针、逆时针、停止、加速和减速按键。
P3.0接L294的IN1,P3.1接IN2。P3.7接ENA,也就是PWM输出口。
另外你也可以用P0和P2口接LED或者LCD显示屏。
晶振就用单片机流行的12MHz就行了。
我这是用C语言写程序Keil编译。
#include<reg51.h>

sbit MA = P3^0;
sbit MB = P3^1;
sbit PWM = P3^7;

bit KeyFree;
unsigned char PWM_OUT;

void Delay(unsigned char); //声明延时函数
unsigned char KeyScan(void);
void keyProcess(unsigned char);
main()
{
TMOD = 0x01;
TH0 = - 50000 /256;
TL0 = - 50000 % 256;
IE = 0x82;
TR0 = 1;
while (1)
{
keyProcess(KeyScan());
}
}

void T0_INT () interrupt 1 //定时器函数控制PWM输出
{
TH0 = -5000 / 256;
TL0 = -5000 % 256;

PWM=1; //设置PWM输出
Delay(PWM_OUT);
PWM=0;
Delay(100-PWM_OUT);
}
void Delay(unsigned char x)
{
uchar i;
while(x--) for(i = 0;i < 200; i++);
}

unsigned char KeyScan(void)
{
P1|=0x1f;
if((P1&0x1f)!=0x1f)
{
Delay(10); //延时去抖
if((P1&0x1f)!=0x1f)
{
return P1&0x1f;
}
}
return P1&0x1f;
}

void keyProcess(uint key)
{
if(key==0x1f) /*******************/
{ /* */
KeyFree=1; /* 软件松手检测 */
} /* */
else /* */
{ /* */
if(KeyFree==1) /* */
{ /*******************/
KeyFree=0;
/*******************************************/
switch (key)
{

case 0x1e : {
MA=1;
MB=0;
break;}
case 0x1d : {
MA=0;
MB=1;
break;}
case 0x1b : {
PWM_OUT =0;
break;}
case 0x17 : {
if(PWM_OUT!=90){
PWM_OUT+=30;}
break;}
case 0x0f : {
if(PWM_OUT!=30&&PWM_OUT!=0){
PWM_OUT-=30;}
break;}
}
/*******************************************/
}
}
}

热心网友 时间:2023-11-01 19:18

其实有自带的PWM输出口的话那就很简单了。比如STC12C5201AD(PWM)系列单片机,或者干脆AVR mega系列(OCR0输出)。不过没有的话也没有关系。拿atS51为例。其实就是改变普通I/O口的电平。大致思路如下:

全局变量 unsigned int High=0;//高电平时长
全局变量 unsigned int Low=0;//低电平时长
全局变量 unsigned int zkb=0;//占空比时长
全局变量 unsigned int zhouqi=0;//周期时长

void 中断函数()
{
if(zkb>0&&zhouqi>0)
{
I/O输出高电平
zkb-=1;
zhouqi-=1;
}
else if(zkb<=0&&zhouqi>0)
{
I/O输出低电平
zhouqi-=1;
}
else if (zkb<=0&&zhouqi<=0)
{
zkb=High;
zhouqi=High+Low;
}
中断时间周期
}

void main()
{
/*初始化
**包括I/O口以及中断打开
*/

while(1)
{
//调速改变zkb 和zhouqi的值

zkb=High;
zhouqi=High+LOW;
}
}

大致的思路吧,还有很多种其他思路。

程序的已经发了,请查收,如果还有问题,百度Hi我把

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com