找回密码
 立即注册

QQ登录

只需一步,快速开始

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

请教STC单片机输出PWM问题

[复制链接]
跳转到指定楼层
楼主
ID:761175 发表于 2023-2-19 12:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
给位老师帮我看看下面程序,我需要实现1路pwm输出,当按键按下输出电压从4.5v降到2伏,在升到4.5伏。在30秒左右完成,
#include <STC12C5410AD.H>
#define unchar unsigned char
#define unint unsigned int
#define DUTYCYCLE(x)   (256-(128*x/50))//占空比计算公式256-(80/x=50/128)=XX,  ** 占空比**


unchar  yi=1;
unchar  er=0;

sbit KEY0=P1^6;
sbit KEY1=P1^7;
unint CYCLE0,CYCLE1;
void Delay(unint x)    //延时子函数      
{
   unint y;      //定义一个Y变量
   for(;x>0;x--)    //如果X大于0,那么X就减1.
    for(y=500;y>0;y--);//给Y赋值为500,当Y大于0那么Y就减1.  *******注意前面的for的语句后面没有引号,那么会把后面的FOR语句
//也认为是他的内部语句。也就是说X执行一次那么Y就得执行500次。
}
void MainInt()        //
{      

        CMOD|=0x02;//选择SYSCLK为PWM的时钟源//控制PWM波的频率
        CCAPM0|=0x42;//允许比较器功能,开启PWM0
        CCAPM1|=0x42;//允许比较器功能,开启PWM1
        CL=0x00;//计数器清零
        CH=0x00;
        CCAP0L=0x33;//自动装入初始值,控制PWM占空比靠着两个,大于这个数输出1,反之。。
        CCAP0H=0x33; //   CCAPOL  CCAPOH  为PWM0的最高占空比和最低占空比。
        CCAP1L=0x00; //猜也猜到了这个是PWM1的低占空比。
        CCAP1H=0x00; //这个也是我猜的哈哈PWM1的高占空比。
        CCON|=0;//启动PWM
               CR = 1;                         //PCA 计时器启动运行
}
// 按键检查函数,用来调节PWM的占空比0%-100%
void KeyScan(void)
{
   if(KEY1==0)
    {
          Delay(500);
          if(KEY1==0);   
          CYCLE0+=1;
          if(CYCLE0>100)
           CYCLE0=0;
      CCAP0L=DUTYCYCLE(CYCLE0);//自动装入初始值,控制PWM占空比靠着两个,大于这个数输出1,反之。。
      CCAP0H=DUTYCYCLE(CYCLE0);//占空比计算公式256-(80/x=50/128)=XX,
      CCAP1L=DUTYCYCLE(CYCLE1);
      CCAP1H=DUTYCYCLE(CYCLE1);
        }
}
void main(void)
{
   MainInt();
    CYCLE0=100;
   while(1)
    {
//****************下面语句是不断加减CYCLE的数值来调节占空比输出的。
           if(yi==1)
     {
      Delay(30);
   CYCLE0--;
   if(CYCLE0==1)
   er=1,yi=0;
     }
     if(er==1)
     {
      Delay(50);
   CYCLE0++;
   if(CYCLE0==30)
   er=0,yi=1;
     }



   CCAP0L=DUTYCYCLE(CYCLE0);//自动装入初始值,控制PWM占空比靠着两个,大于这个数输出1,反之。。
      CCAP0H=DUTYCYCLE(CYCLE0);//占空比计算公式256-(80/x=50/128)=XX,
      CCAP1L=DUTYCYCLE(CYCLE1);
      CCAP1H=DUTYCYCLE(CYCLE1);

        }
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2023-2-19 21:12 | 只看该作者
在VCC=5V前提下,当按键按下,PWM输出电压从2伏到4.5伏范围变化,也就是占空比在40~90%范围变化。
  1. #include <STC12C5410AD.H>
  2. #define unchar unsigned char
  3. #define unint unsigned int
  4. //#define DUTYCYCLE(x)   (256-(128*x/50))//占空比计算公式256-(80/x=50/128)=XX,  ** 占空比**
  5. //unchar  yi=1;
  6. //unchar  er=0;

  7. sbit KEY0=P1^6;
  8. //sbit KEY1=P1^7;
  9. //unint CYCLE0,CYCLE1;
  10. unsigned char num;//计数变量
  11. unsigned char Z_ratio;//占空比变量
  12. bit Key_value;//键值位变量

  13. void Timer0Init(void)//60毫秒@11.0592MHz
  14. {
  15.         AUXR &= 0x7F;                //定时器时钟12T模式
  16.         TMOD &= 0xF0;                //设置定时器模式
  17.         TL0 = 0x00;                //设置定时初始值
  18.         TH0 = 0x28;                //设置定时初始值
  19.         TF0 = 0;                //清除TF0标志
  20.         TR0 = 1;                //定时器0开始计时
  21.         EA  = 1;
  22.         ET0 = 1;
  23. }

  24. void PWM_Init(void)
  25. {
  26.         CCON = 0;                                //初始化PCA控制寄存器
  27.         CL = 0;                 //复位PCA寄存器
  28.         CH = 0;                 //复位PCA寄存器
  29. //        CMOD = 0x00;                         //设置PCA时钟源,PWM频率=11.0592MHZ/12/256=3.600KHZ 278us
  30. //        CMOD = 0x02;                         //设置PCA时钟源,PWM频率=11.0592MHZ/2/256=21.600KHZ 46us
  31. //        CMOD = 0x04;                         //设置PCA时钟源,PWM频率=11.0592MHZ/1~65536/256=43.200KHZ~0.659HZ
  32. //        CMOD = 0x06;                         //设置PCA时钟源,PWM频率= 外部时钟/1/256
  33. //        CMOD = 0x08;                         //设置PCA时钟源,PWM频率=11.0592MHZ/1/256=43.200KHZ 23us
  34. //        CMOD = 0x0A;                         //设置PCA时钟源,PWM频率=11.0592MHZ/4/256=10.800KHZ 93us
  35. //        CMOD = 0x0C;                         //设置PCA时钟源,PWM频率=11.0592MHZ/6/256=7.200KHZ 139us
  36.         CMOD = 0x0E;                         //设置PCA时钟源,PWM频率=11.0592MHZ/8/256=5.400KHZ 185us
  37.         PCA_PWM0 = 0x00;        //PCA模块0工作于8位PWM
  38.         CCAP0H = CCAP0L = 0xff; //PWM0的占空比为0%
  39.         CCAPM0 = 0x42;                        //允许CCP0脚用作脉宽调节输出
  40.         CR = 1;                 //PCA定时器开始工作
  41. }

  42. void Delay_ms(unsigned int t)//1T@11.0592MHz
  43. {
  44.         unsigned int i,j;
  45.         for(i=t;i>0;i--)
  46.                 for(j=1100;j>0;j--);
  47. }

  48. void KeyScan(void)
  49. {
  50.         static unsigned char count;
  51.         static bit sign_key;

  52.         if(!KEY0)
  53.         {
  54.                 if(++count>=20 && sign_key==0)
  55.                 {
  56.                         sign_key=1;
  57.                         Key_value=~Key_value;                       
  58.                 }
  59.         }
  60.         else
  61.         {
  62.                 count=0;
  63.                 sign_key=0;
  64.         }
  65. }
  66. void main(void)
  67. {
  68.         P0M0 = 0x00;
  69.         P0M1 = 0x00;
  70.         P1M0 = 0x01;//PWM0默认端口推挽模式
  71.         P1M1 = 0x00;
  72.         P2M0 = 0x00;
  73.         P2M1 = 0x00;
  74.         P3M0 = 0x00;
  75.         P3M1 = 0x00;

  76.         PWM_Init();
  77.         Timer0Init();
  78.         Z_ratio=40;
  79.         while(1)
  80.         {
  81.                 KeyScan();
  82.                 Delay_ms(1);//控制主循环周期1ms
  83.         }
  84. }

  85. void Timer0Interrupt(void) interrupt 1
  86. {
  87. //        if(++num>=10)//600毫秒,占空比从40%~90%变化时间30秒
  88.         if(++num>=1)//测试用60ms,占空比从40%~90%变化时间3秒
  89.         {
  90.                 num=0;
  91.                 if(Key_value)
  92.                 {
  93.                         if(Z_ratio<90)
  94.                                 Z_ratio++;
  95.                 }
  96.                 else               
  97.                 {
  98.                         if(Z_ratio>40)
  99.                                 Z_ratio--;

  100.                 }
  101.                 CCAP0H=256-(Z_ratio*2.56);
  102.         }
  103. }
复制代码

回复

使用道具 举报

板凳
ID:1034262 发表于 2023-2-19 21:12 | 只看该作者
不断改变占空比就可以了。
回复

使用道具 举报

地板
ID:1063483 发表于 2023-2-19 22:37 | 只看该作者
“需要实现1路pwm输出,当按键按下输出电压从4.5v降到2伏,在升到4.5伏。在30秒左右完成。”

不知道为什么一定要在这种场合用PWM输出,如果用最便宜的ATMEL芯片控制两个I/O口输出,
一个P1.0口输出低电平时,输出电压就是4.5V;
如果另一个P1.2口输出低电平时,输出就是2V;
外面输出电压采取简单的分压电路实现就可以了。
当按键按下时由P1.0口由低电平取反,P1.2输出低电平30秒,P1.0再度取反输出低电平,
即保证输出4.5V->2V->4.5V 时间30秒。

若要PWM程序,简单一点的写一个就可以了:
/*
P1.5 脚 输出一个100 Hz的频率的PWM程序
*/

#include <STC12C5A60S2.h>

sbit PWM_PIN = P1 ^ 5;//输出Pin

//T0和T1的初始化函数
void initTimer(void)   
{
  TMOD = 0x11;              //设置工作方式
  EA = 1;
  ET0 = 1;                  //开启T0的中断
  ET1 = 1;                  //开启T1的中断
  TH1 = 0xDC;               //10毫秒
  TL1 = 0x00;               //T1的预置值
  TH0 = 0xF8;               //2毫秒
  TL0 = 0xCD;               //T0的预置值
  TR0 = 1;
  TR1 = 1;                                                                //启动两个定时器
}
//TL0中断服务子函数,使用通用工作寄存器组1
void Timer0(void) interrupt 1 using 1
{
        PWM_PIN = 0;             //P1_0引脚为低电平
        TR0 = 0;                                                        //停止定时器TL0
    TH0 = 0xF8;               //2毫秒
    TL0 = 0xCD;               //T0的预置值
}
//TH0中断服务子函数,占用定时计数器1的中断向量,使用通用工作寄存器组2
void Timer1(void) interrupt 3 using 2
{
        PWM_PIN = 1;             //P1_0引脚为高电平
        TR0 = 1;                                                        //启动定时器TL0
          TH1 = 0xDC;               //10毫秒
          TL1 = 0x00;               //T0的预置值                                       
}
int main(void)
{
  PWM_PIN = 0;               //初始化为低电平
  initTimer();            //初始化T0和T1
  while(1)
  {
  }
}

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

5#
ID:761175 发表于 2023-2-19 23:40 | 只看该作者
wulin 发表于 2023-2-19 21:12
在VCC=5V前提下,当按键按下,PWM输出电压从2伏到4.5伏范围变化,也就是占空比在40~90%范围变化。

老师你好,十分感谢指导,怎么我用Proteus 8 仿真没波形输出呢,是我那里没搞对,在帮我看看。谢了
回复

使用道具 举报

6#
ID:761175 发表于 2023-2-19 23:53 | 只看该作者
wulin 发表于 2023-2-19 21:12
在VCC=5V前提下,当按键按下,PWM输出电压从2伏到4.5伏范围变化,也就是占空比在40~90%范围变化。

我的按键是接到P1.6,输出是P1.3.用的是Proteus 8 中的89C52。看看是那里我没搞对。谢了
回复

使用道具 举报

7#
ID:1063483 发表于 2023-2-20 09:35 | 只看该作者
以下2点说明来自百度:

1.   51系列单片机引脚电平与TTL电平兼容,也就是输入高电位大于2.0V,低电位小于0.8V,输出高电位大于2.4V,低电位小于0.4V。一般情况下,若电源电压为5V,输出高电位电压也是5V左右,低电位电压接近0V.
2.   0.3VCC----0V为低电平,0.7VCC---VCC为高电平,一般来讲,对于5V电源的单片机来说,低电平在1.3V以下,高电平在3.7V以上,数字信号尽量不要使用1.3---3.7V这个区间,这有可能会造成单片机无法识别或识别错误。

你检查一下芯片输出脚的电压,输出是不是5V和(0点几)V,不用理会波形.  
占空比40%~90%,不等于输出2V到4.5V电压,还是要加分压器的,取得你要的电压。希望对你有帮助。
回复

使用道具 举报

8#
ID:1063483 发表于 2023-2-21 09:06 | 只看该作者
“如果用最便宜的ATMEL芯片控制两个I/O口输出”
楼主问是ATMEL什么型号,昨天查了。好像是  MICROCHIP的  PIC16F819 之类芯片,以前是几毛钱,现在好像长到了4块左右了。microchip和 atemel 现在都在一起了,还是怎么了,你再研究研究。
回复

使用道具 举报

9#
ID:761175 发表于 2023-2-21 09:08 来自手机 | 只看该作者
watsonbu 发表于 2023-2-19 22:37
“需要实现1路pwm输出,当按键按下输出电压从4.5v降到2伏,在升到4.5伏。在30秒左右完成。”

不知道为什 ...

十分感谢,你说的芯片是什么型号的呢
回复

使用道具 举报

10#
ID:1063483 发表于 2023-2-21 09:17 | 只看该作者
型号:PIC16F819 这系列的芯片,好像是 MICROCHIP,但上面有ATMEL字样,以前是几毛钱,现在要4块了
回复

使用道具 举报

11#
ID:213173 发表于 2023-2-21 10:12 | 只看该作者
稻草人008 发表于 2023-2-19 23:40
老师你好,十分感谢指导,怎么我用Proteus 8 仿真没波形输出呢,是我那里没搞对,在帮我看看。谢了

给你的示例是基于你的程序头文件#include <STC12C5410AD.H>修改,亦可用于STC15系列。用IAP15W4K58S4芯片实物运行完全正常。仿真软件对于增强型51芯片的新增功能基本没有实际意义。本示例使用了STC自带的PWM功能模块,默认PWM0输出端口P1.1。AT89C52根本不具备此模块。
回复

使用道具 举报

12#
ID:761175 发表于 2023-2-21 10:17 来自手机 | 只看该作者
watsonbu 发表于 2023-2-21 09:17
型号:PIC16F819 这系列的芯片,好像是 MICROCHIP,但上面有ATMEL字样,以前是几毛钱,现在要4块了

十分感谢,我去学习一下,有什么不懂还要请教你的
回复

使用道具 举报

13#
ID:761175 发表于 2023-2-22 17:31 来自手机 | 只看该作者
wulin 发表于 2023-2-21 10:12
给你的示例是基于你的程序头文件#include 修改,亦可用于STC15系列。用IAP15W4K58S4芯片实物运行完全正常 ...

十分感谢,我在试试
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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