找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 13023|回复: 30
收起左侧

51单片机测量PWM脉冲宽度LCD1602显示当前PWM占空比频率

  [复制链接]
ID:455286 发表于 2018-12-26 12:22 | 显示全部楼层 |阅读模式
此程序通过两个定时器一个外部中断,测量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)

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:455286 发表于 2018-12-26 18:33 | 显示全部楼层
里面注释详细,不懂的欢迎提问
回复

使用道具 举报

ID:458917 发表于 2019-1-1 18:38 来自手机 | 显示全部楼层
呢能不能改成在4位的led数码管上显示脉冲宽度的,不知道代码怎么改
回复

使用道具 举报

ID:277781 发表于 2019-3-11 21:39 | 显示全部楼层
初学菜鸟,谢谢!学习了!
回复

使用道具 举报

ID:409013 发表于 2019-4-27 10:58 | 显示全部楼层
可以只用一个定时器来实现吗,大佬有空看一下我的求助
http://www.51hei.com/bbs/dpj-157890-1.html
回复

使用道具 举报

ID:539092 发表于 2019-5-27 22:36 | 显示全部楼层
如果要用定时中断测频率为100hz的方波的周期并在LCD1602上表示出来,程序应该怎么改呢
回复

使用道具 举报

ID:470926 发表于 2019-6-22 09:17 | 显示全部楼层
1179839709 发表于 2019-1-1 18:38
呢能不能改成在4位的led数码管上显示脉冲宽度的,不知道代码怎么改

可以更改 P0口接上拉电阻接数码管更改数码管对应的显示就可以
回复

使用道具 举报

ID:578183 发表于 2019-7-5 16:24 | 显示全部楼层
请问如何改变占空比,刚刚接触PWM,不是很明白
回复

使用道具 举报

ID:575294 发表于 2019-7-5 16:46 | 显示全部楼层
请问老哥,这个硬件原理图您用哪个软件做的呢?请问是 3D MAX吗?
回复

使用道具 举报

ID:480680 发表于 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);
        }
}

回复

使用道具 举报

ID:588275 发表于 2019-7-23 23:48 | 显示全部楼层
求电路原理图
回复

使用道具 举报

ID:544565 发表于 2019-8-16 12:21 来自手机 | 显示全部楼层
学习一下哈
回复

使用道具 举报

ID:633597 发表于 2019-10-31 23:43 | 显示全部楼层
我是新手看不懂
回复

使用道具 举报

ID:385637 发表于 2019-11-1 15:16 | 显示全部楼层
有点没搞明白这个占空比是怎么计算的,频率就可以计算,两个下降沿就一个完整周期,看你程序TR0与TR1都是同时开同时关的,那计时的时间不是都一样吗,怎么计算出占空比?
回复

使用道具 举报

ID:633998 发表于 2019-11-1 18:16 | 显示全部楼层
Pwm_All = (Pwm_All<<8)+TL1;这是什么意思啊?有什么作用吗?
回复

使用道具 举报

ID:143996 发表于 2019-12-17 23:46 | 显示全部楼层
有哪位编译通过的吗。交流一下。编译一直无法通过
回复

使用道具 举报

ID:24486 发表于 2020-2-12 09:24 | 显示全部楼层
学习一下,谢谢分享。
回复

使用道具 举报

ID:24486 发表于 2020-2-15 21:10 | 显示全部楼层
学习一下,谢谢分享。
回复

使用道具 举报

ID:713651 发表于 2020-4-11 16:13 | 显示全部楼层
你这个能读出来吗?
回复

使用道具 举报

ID:937848 发表于 2021-6-15 14:06 | 显示全部楼层
请问LCD1602的头文件能给出来吗 编译的时候报错了
回复

使用道具 举报

ID:937848 发表于 2021-6-15 17:13 | 显示全部楼层
头文件怎么写呀 楼主 求救!
回复

使用道具 举报

ID:962202 发表于 2021-8-27 17:29 | 显示全部楼层
看看谢分享啦,学习中如何捕获PWM然后转换PWM或者驱动MOS
回复

使用道具 举报

ID:881546 发表于 2022-7-20 15:19 | 显示全部楼层
定时器工作模式 TMOD = 0x19什么意思?
回复

使用道具 举报

ID:228452 发表于 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

评分

参与人数 1黑币 +5 收起 理由
续我心弦 + 5

查看全部评分

回复

使用道具 举报

ID:881546 发表于 2022-7-21 16:28 | 显示全部楼层
脉冲输入的口为什么是P32,我想弄个八路测脉冲宽度
回复

使用道具 举报

ID:881546 发表于 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
回复

使用道具 举报

ID:228452 发表于 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

回复

使用道具 举报

ID:228452 发表于 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...
回复

使用道具 举报

ID:228452 发表于 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
回复

使用道具 举报

ID:1078937 发表于 2023-5-22 16:07 | 显示全部楼层
shenyuqiu 发表于 2019-11-1 15:16
有点没搞明白这个占空比是怎么计算的,频率就可以计算,两个下降沿就一个完整周期,看你程序TR0与TR1都是同 ...

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

使用道具 举报

ID:1079136 发表于 2023-5-22 19:22 来自手机 | 显示全部楼层
这个有点复杂了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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