标题: 51单片机测量PWM脉冲宽度LCD1602显示当前PWM占空比频率 [打印本页]

作者: MR_CHEN12    时间: 2018-12-26 12:22
标题: 51单片机测量PWM脉冲宽度LCD1602显示当前PWM占空比频率
此程序通过两个定时器一个外部中断,测量PWM高电平时间以及周期,计算并在1602显示出占空比 周期 高电平时间,只需让脉冲在P3^2口输入即能测得数据。。

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <LCD1602.h>

  3. typedef unsigned char uint8;
  4. typedef unsigned int  uint16;//数据类型重定义

  5. uint8 count = 0; //计进入外部中断次数
  6. bit flag = 1;  //捕获结束标志位
  7. long Pwm_All; //PWM的周期
  8. long Pwm_High; //PWM的高电平时间                   占空比=Pwm_High/Pwm_All
  9. void delay(long i)
  10. {
  11.         while(i--);
  12. }

  13. void Interrupt_Init()
  14. {
  15.         /*定时器1为工作模式1 16位计数器 由TR1直接启动
  16.                 定时器0为工作模式1 16位计数器 由GATE和TR0共同启动*/
  17.         TMOD = 0x19;
  18.         
  19.         TH1 = 0;
  20.         TL1 = 0;
  21.         TH0 = 0;
  22.         TL0 = 0;
  23.         
  24.         IT0 = 1;//下降沿触发
  25.         IT1 = 1;
  26.         //TR0 = 1; //GATE高电平启动
  27.         
  28.         EX0 = 1;
  29.         EA = 1;        
  30. }

  31. void main()
  32. {
  33.         uint16 Pwm_percentage; //PWM占空比
  34.         Interrupt_Init();
  35.         LCD1602_Initialize( );
  36.         LCD1602_PrintString(1,1,"ALL:");
  37.         LCD1602_PrintString(1,10,"us");
  38.         LCD1602_PrintString(2,1,"HIGH:");
  39.         LCD1602_PrintString(2,11,"us");
  40.         while(1)
  41.         {
  42.                
  43.                 if(flag)
  44.                 {
  45.                         Pwm_percentage = Pwm_High*1000 / Pwm_All;
  46.                         LCD1602_PrintChar(1,12,0x30+Pwm_percentage/100);
  47.                         LCD1602_PrintChar(1,13,0x30+Pwm_percentage%100/10);
  48.                         LCD1602_PrintChar(1,14,'.');
  49.                         LCD1602_PrintChar(1,15,0x30+Pwm_percentage%10);
  50.                         LCD1602_PrintChar(1,16,'%');
  51.                         
  52.                         LCD1602_PrintChar(1,5,0x30+Pwm_All/10000);
  53.                         LCD1602_PrintChar(1,6,0x30+Pwm_All%10000/1000);
  54.                         LCD1602_PrintChar(1,7,0x30+Pwm_All%1000/100);
  55.                         LCD1602_PrintChar(1,8,0x30+Pwm_All%100/10);
  56.                         LCD1602_PrintChar(1,9,0x30+Pwm_All%10);
  57.                         LCD1602_PrintChar(2,6,0x30+Pwm_High/10000);
  58.                         LCD1602_PrintChar(2,7,0x30+Pwm_High%10000/1000);
  59.                         LCD1602_PrintChar(2,8,0x30+Pwm_High%1000/100);
  60.                         LCD1602_PrintChar(2,9,0x30+Pwm_High%100/10);
  61.                         LCD1602_PrintChar(2,10,0x30+Pwm_High%10);
  62.                         flag = 0; //计算完一次清零
  63.                 }
  64.                 delay(70000);
  65.         }
  66.         
  67. }

  68. void EXTI0 () interrupt 0
  69. {
  70.                 count++;
  71.         if(count == 1) //第一次下降沿,启动定时器1
  72.         {
  73.                 TR1 = 1;
  74.                 TR0 = 1;
  75.         }
  76.         if(count == 2) //第二次下降沿,一整个周期完毕
  77.         {
  78.                 EX0 = 0; //关闭外部中断,防止被其他打断计算
  79.                 TR1 = 0;        //周期停止计数
  80.                 TR0 = 0;        //高电平时间停止计数
  81.                 Pwm_All = TH1; //获取数据
  82.                 Pwm_All = (Pwm_All<<8)+TL1;
  83.                 Pwm_High = TH0;
  84.                 Pwm_High = (Pwm_High<<8)+TL0;
  85.                 TH1 = 0; //清零为下一次做准备
  86.                 TL1 = 0;
  87.                 TH0 = 0;
  88.                 TL0 = 0;
  89.                 count = 0;
  90.                 flag = 1;        
  91.                 EX0 = 1; //开启下一次计算
  92.                 TR1 = 0;
  93.                 TR0 = 0;
  94.         }
  95.         
  96. }
复制代码

所有资料51hei提供下载:
PWM捕获占空比.zip (45 KB, 下载次数: 406)




作者: MR_CHEN12    时间: 2018-12-26 18:33
里面注释详细,不懂的欢迎提问
作者: 1179839709    时间: 2019-1-1 18:38
呢能不能改成在4位的led数码管上显示脉冲宽度的,不知道代码怎么改
作者: zycable    时间: 2019-3-11 21:39
初学菜鸟,谢谢!学习了!
作者: Lucky_Dog    时间: 2019-4-27 10:58
可以只用一个定时器来实现吗,大佬有空看一下我的求助
http://www.51hei.com/bbs/dpj-157890-1.html
作者: 1975966580    时间: 2019-5-27 22:36
如果要用定时中断测频率为100hz的方波的周期并在LCD1602上表示出来,程序应该怎么改呢
作者: zhanyouyuyuni    时间: 2019-6-22 09:17
1179839709 发表于 2019-1-1 18:38
呢能不能改成在4位的led数码管上显示脉冲宽度的,不知道代码怎么改

可以更改 P0口接上拉电阻接数码管更改数码管对应的显示就可以
作者: 懒惰的家伙    时间: 2019-7-5 16:24
请问如何改变占空比,刚刚接触PWM,不是很明白
作者: leiluo    时间: 2019-7-5 16:46
请问老哥,这个硬件原理图您用哪个软件做的呢?请问是 3D MAX吗?
作者: 周涛1331    时间: 2019-7-21 21:45
懒惰的家伙 发表于 2019-7-5 16:24
请问如何改变占空比,刚刚接触PWM,不是很明白

#include <AT89X52.h>

#define MAX 0x50   //定时上限定义       占空比上限         下面通过定时器改变占空比
#define MIN 0x00   //定时下限定义       占空比下限
#define TIMELINE 11         //时间分频常数
#define TRUE  1
#define FALSE 0             //标志位常数

unsigned int TimeCounter;
bit ArrowFlg = 0;         //方向标志位
unsigned char upCounter,downCounter;    //增加计数器和减少计数器

sbit LED=P0^0;

//T0的中断服务子函数
void T0Deal() interrupt 1 using 0
{
        TH0=0xf1;
        TL0=0xf1;
        TR0=1;
        TimeCounter++;  //定时计数器增加
        if(TimeCounter == TIMELINE)
        {
                if((upCounter == MAX)&&(downCounter == MIN))  //计数方向标志位切换
    {
      ArrowFlg = FALSE;
    }
                if((upCounter == MIN)&&(downCounter == MAX))
    {
      ArrowFlg= TRUE;
    }
                if(ArrowFlg == 1)   //如果是增加计数
    {
      upCounter++;
      downCounter--;
    }
                else               //如果是减少计数
    {
      upCounter--;
      downCounter++;
    }
                TimeCounter=0;
        }
}
//延时函数
void Delay(unsigned int i)
{
        unsigned int j;
        while(i--)
        {
                for(j=0;j<32;j++);     //延时
        }
}

void main()
{
        upCounter = MIN;
        downCounter = MAX;     //计数器初始化
        TMOD = 0x01;          //设置定时器工作方式
        TH0 = 0xF0;
        TL0 = 0xF0 ;          //T0初始化值
        EA = 1;
        ET0 = 1;              //开中断
        TR0 = 1;              //启动T0
        while(1)
        {
                LED=0;            //输出变化的PWM波形
                Delay(downCounter);   
                LED=1;
                Delay(upCounter);
        }
}


作者: six666666666666    时间: 2019-7-23 23:48
求电路原理图
作者: odiwuano    时间: 2019-8-16 12:21
学习一下哈
作者: zhang21    时间: 2019-10-31 23:43
我是新手看不懂
作者: shenyuqiu    时间: 2019-11-1 15:16
有点没搞明白这个占空比是怎么计算的,频率就可以计算,两个下降沿就一个完整周期,看你程序TR0与TR1都是同时开同时关的,那计时的时间不是都一样吗,怎么计算出占空比?
作者: 刘十一    时间: 2019-11-1 18:16
Pwm_All = (Pwm_All<<8)+TL1;这是什么意思啊?有什么作用吗?
作者: sunlei058378    时间: 2019-12-17 23:46
有哪位编译通过的吗。交流一下。编译一直无法通过
作者: kevintang    时间: 2020-2-12 09:24
学习一下,谢谢分享。
作者: kevintang    时间: 2020-2-15 21:10
学习一下,谢谢分享。
作者: wzjhuohua    时间: 2020-4-11 16:13
你这个能读出来吗?
作者: 星辰大海aa    时间: 2021-6-15 14:06
请问LCD1602的头文件能给出来吗 编译的时候报错了
作者: 星辰大海aa    时间: 2021-6-15 17:13
头文件怎么写呀 楼主 求救!
作者: sd3114336    时间: 2021-8-27 17:29
看看谢分享啦,学习中如何捕获PWM然后转换PWM或者驱动MOS
作者: 续我心弦    时间: 2022-7-20 15:19
定时器工作模式 TMOD = 0x19什么意思?
作者: mick32    时间: 2022-7-20 20:48
TMOD(Timer Mode) is an SFR. The address of this register is 89H. This is not bit-addressable.

TMOD.jpg (191.21 KB, 下载次数: 102)

TMOD.jpg

作者: 续我心弦    时间: 2022-7-21 16:28
脉冲输入的口为什么是P32,我想弄个八路测脉冲宽度
作者: 续我心弦    时间: 2022-7-21 16:36
mick32 发表于 2022-7-20 20:48
TMOD(Timer Mode) is an SFR. The address of this register is 89H. This is not bit-addressable.

I'm going to have another question on the next floor and if you could help me, I will sincerely appreciate you
作者: mick32    时间: 2022-7-21 22:52
本帖最后由 mick32 于 2022-7-21 23:20 编辑

"This is not bit-addressable"
If you want to change lets say only 89.0 bit you can change that bit and rest of bits in byte keep the same
Then you can send new byte to 89H register
information is byte wide xxxxxxxx (8 bits)
hope this is of help...
TMOD EQU 089H ; TMOD register

bit addressable

CLR IE.7 or SETB 20H.2

byte addressable

MOV TMOD,#00100010B ;22H


作者: mick32    时间: 2022-7-21 23:10

"Why is the pulse input port P32, I want to get an eight-way test pulse width"
P3.2 (INT0) and P3.3 (INT1) are hardware specific inputs...
8051 can't follow eight inputs with hardware
You try with software pooling but with big chance to loose real data...
作者: mick32    时间: 2022-7-21 23:30
"This is not bit-addressable"

TMOD EQU 089H ; TMOD register

bit addressable example

CLR IE.7 or
SETB 20H.2

byte addressable example

MOV TMOD,#00100010B ;22H
作者: 1940178371    时间: 2023-5-22 16:07
shenyuqiu 发表于 2019-11-1 15:16
有点没搞明白这个占空比是怎么计算的,频率就可以计算,两个下降沿就一个完整周期,看你程序TR0与TR1都是同 ...

因为定时器0博主设置的带门控位GATE,当INT0高电平时,定时器0才启动;中断第一次下降沿开启TR0=1不会立刻启动定时器1,上升沿之后才启动

作者: 18355449194    时间: 2023-5-22 19:22
这个有点复杂了




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1