找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7714|回复: 18
打印 上一主题 下一主题
收起左侧

用PWM做呼吸灯

  [复制链接]
跳转到指定楼层
楼主
ID:55063 发表于 2013-10-13 10:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我要用pwm做呼吸灯,可我对pwm是怎么编写的,原理什么的不知道,忘前辈们指教。最好能给我一个教pwm控制单片机的视频教程,我学一下,谢谢!
由于是新手,表述可能不准确请见谅。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2013-10-13 13:38 | 只看该作者
这里有 呼吸灯的详细资料http://www.51hei.com/mcu/1160.html
回复

使用道具 举报

板凳
ID:55946 发表于 2013-10-15 00:10 | 只看该作者
12系列的PWM输出
STC12C5A60S2内部集成了两路可编程计数器阵列(PCA)可以用做脉宽调制(PWM)输出。脉宽调制是将模拟信号转换为脉冲波的一种技术。一般转换后脉波的周期固定,但占空比会随模拟信号的大小而改变。讲多了,下面直接讲重点,如何用C语言实现PWM输出。
STC12C5A60S2单片机通过程序设定工作在八位PAM模式,其占空比与PCA_PWMn(n=0,1下同)寄存器的EPCnL和CCAPn L的值有关。当CL的值小于[EPCnL,CCAPn L]时PWM输出低电平,大于时输出高电平。八位计数器CL不断的从00加一,直到FF再循环,这样就形成了一定占空比的方波,当CL从FF溢出到00时,[EPCnH,CCAPn H]的值自动装载到[EPCnL,CCAPn L]中,我们只要改变[EPCnH,CCAPn H],在下一个周期就会形成新的占空比。要想使用PWM功能,要将CCAPMn寄存器的ECOMn和PWMn位置位。CL和CH的初值都为0(八位(256-256)%256和(256-256)/256)。CCAPn H的值等于=255-255*占空比/100。
主要文件
/********************************************************************
* 文件名  :  12系列PWM输出
* 描述    :  利用12系列自带的PWM输出可调占空比的脉宽 
* 创建人  : 严兵,2013年7月21日
***********************************************************************/
#include "fun.h"   
/********************************************************************
* 名称 : 外部中断0服务函数
* 功能 : 外部产生中断时,将占空比值减一
* 输入 : 无
* 输出 : 无
***********************************************************************/                          
void  INT0_interrupt() interrupt 0
{
        if ( duty_level > 0 )
        {
                duty_level --;
                CCAP0H =  255 - 255 * duty[duty_level] / 100;
        }
        else
        {
                duty_level = 10;        //PWM调到最大,发光二极管熄灭
                CCAP0H =  255 - 255 * duty[duty_level] / 100;
        }
}

main()
{
        ms_delay(20);
        init_port();
        init_int();       
        init_pca();

        EA = 1;//开总中断

        while(1);
}
FUN.H头文件
#include <intrins.h>
#include <reg51.h>        //包含头文件  

//定义端口寄存器         
sfr P0M0 = 0X93;
sfr P0M1 = 0X94;
sfr P1M0 = 0X91;
sfr P1M1 = 0X92;
sfr P2M0 = 0X95;
sfr P2M1 = 0X96;  
sfr P3M0 = 0Xb1;
sfr P3M1 = 0Xb2;

//与PCA0有关的寄存器
sfr CCON = 0xd8; //PCA控制寄存器
        sbit CCF0 = CCON^0; //PCA0中断标志位
        sbit CR = CCON^6;        //运行控制位
        sbit CF = CCON^7;        //溢出标志
sfr CMOD = 0xd9; //PCA工作模式寄存器
sfr CL = 0xe9;
sfr CH = 0xf9;
sfr CCAPM0 = 0xda;//PCA0寄存器  
sfr CCAP0L = 0xea;
sfr CCAP0H = 0xfa;
sfr PCAPWM0 = 0xf2;

#define fosc 11059200L       
sbit s1 = P3^2;

unsigned char duty[11] = {0,10,20,30,40,50,60,70,80,90,100};
unsigned char duty_level;        //占空比值
/********************************************************************
* 名称 : 外部中断0初始化函数
* 功能 : 初始化外部中断0
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init_int()
{
        IT0 = 1;//设置INT0为下降沿触发
        EX0 = 1;//允许INT0中断  
}
/********************************************************************
* 名称1: I/O初始化函数
* 功能 : 初始化P1I/O
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init_port()
{
        P1M1 = 0x00;  //P1.3强推挽输出
        P1M0 = 0x04;
}
/********************************************************************
* 名称 : PCA初始化函数
* 功能 : 设置PCA模块0的PWM
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init_pca()
{
        CCON = 0;         //
        CL = 0;             //(256-256)/256  PCA计数器初值设定,八位PWM模式  
        CH = 0;             //(256-256)%256
        CMOD = 0x08; //0000 1000 时钟源为系统时钟,得到PWM的频率(最快) = fosc / 256 = 43.2k,PWM时PCA计数器不需要产生中断,只要一直计数
        duty_level = 0;        //占空比0%
        CCAP0H =  255 - 255 * duty[duty_level] / 100;//根据PWM占空比算捕获计数值
        CCAP0L =  CCAP0H;        //将高位值(CCAP0H)给低位(CCAP0L),这样就可以通过改变高位值来控制低位值,而占空比是根据CL和[EECPOL,CCAP0L]比较得来的
        CCAPM0 = 0x42; //0010 0010 上升沿捕获,PWM使能
        CR = 1;        //        启动PWM
}
/********************************************************************
* 名称 : 延时函数
* 功能 : 延时T*MS
* 输入 : T
* 输出 : 无
***********************************************************************/
void ms_delay(unsigned int t)
{
        unsigned  int  i;
        for (t; t > 0; t--)        //外层循环t次         
                for (i = 1320;i > 0; i--)        //内层循环110*12次        ,12系列比51快12倍          
                ;
}
回复

使用道具 举报

地板
ID:55063 发表于 2013-10-16 13:37 | 只看该作者
太感谢了
回复

使用道具 举报

5#
ID:63752 发表于 2014-8-19 12:52 | 只看该作者
太感谢了,学习学习~~
回复

使用道具 举报

6#
ID:2318 发表于 2014-8-19 13:10 来自手机 | 只看该作者
呼吸灯其实挺简单的,,就是慢慢的改变pwm脉冲宽度,达到让灯慢慢亮又慢慢暗的效果
回复

使用道具 举报

7#
ID:63752 发表于 2014-8-22 11:39 | 只看该作者
hkccd 发表于 2014-8-19 13:10
呼吸灯其实挺简单的,,就是慢慢的改变pwm脉冲宽度,达到让灯慢慢亮又慢慢暗的效果

我用PCA模块做PWM输出,定时器中断,使500MS改变占空比,我要如果设置?请求助。
回复

使用道具 举报

8#
ID:123712 发表于 2016-7-16 14:12 | 只看该作者
感谢感谢,学习中
回复

使用道具 举报

9#
ID:122633 发表于 2016-7-22 21:53 | 只看该作者
PWM 脉冲宽度调制
回复

使用道具 举报

10#
ID:122633 发表于 2016-7-22 21:58 | 只看该作者
利用处理器的数字输出来控制脉冲宽度
回复

使用道具 举报

11#
ID:111634 发表于 2016-7-23 12:36 | 只看该作者
呼吸灯的定义是什么?
回复

使用道具 举报

12#
ID:134736 发表于 2016-7-23 17:24 | 只看该作者
分享一个Arduino上用与驱动舵机的PWM输出:用延时做的效果可以:

void servopulse(int servopin,int myangle)//定义一个脉冲函数
{
pulsewidth=(myangle*11)+500;//将角度转化为500-2480 的脉宽值
digitalWrite(servopin,HIGH);//将舵机接口电平至高
delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
digitalWrite(servopin,LOW);//将舵机接口电平至低
delay(20-pulsewidth/1000);
}
回复

使用道具 举报

13#
ID:134884 发表于 2016-7-25 09:03 | 只看该作者
之前做过一个 死循环里面通过变量大小分配亮和灭的比值  再用定时器控制比值的变化 就有呼吸灯效果了
回复

使用道具 举报

14#
ID:134903 发表于 2016-7-25 10:16 | 只看该作者
定时器
回复

使用道具 举报

15#
ID:134907 发表于 2016-7-25 11:55 | 只看该作者
Delay(20);
回复

使用道具 举报

16#
ID:134919 发表于 2016-7-25 12:06 | 只看该作者
PWM 脉冲宽度调制
回复

使用道具 举报

17#
ID:134697 发表于 2016-7-25 14:31 | 只看该作者
我也是来学习的,回头做下实验。
回复

使用道具 举报

18#
ID:76600 发表于 2016-7-27 12:09 | 只看该作者
学习
回复

使用道具 举报

19#
ID:1114752 发表于 2024-3-30 10:33 | 只看该作者
哈喽,大佬,现在是2024年,你还在吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表