找回密码
 立即注册

QQ登录

只需一步,快速开始

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

想知道怎么用51单片机接收PWM信号

[复制链接]
跳转到指定楼层
楼主
我的二氧化碳传感器MH-Z19输出的是PWM信号,我要用51单片机的I/O口接收这个信号,怎么获得PWM的占空比呢?我听说用一个外部中断和定时器可以实现,我在网上看到了一个接收的方式,用了外部中断0和计数器0,但是他用的STC15F100W-STC15F104W芯片,这个芯片的外部中断0检测到上升沿和下降沿都会进入外部中断,检测到上升沿就开启计数器从零开始计数,检测到下降沿就获取计数值(得到了高电平持续的时间),再将计数器置零等待下一个上升沿。我的芯片是STC89C516RD+,外部中断只能检测到下降沿,所以用不了上述方法。
求问还有什么方式可以检测到PWM的占空比?
(其实二氧化碳传感器MH-Z19也能用串口传输数据,但是我的芯片只有一个串口,而且串口要与上位机通信,所以只能选择PWM的形式了)
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:624769 发表于 2022-4-19 21:22 来自手机 | 只看该作者
不在乎性能的话,在外部中断中处理完下降沿的工作后while(p32==0);  等到上升沿后处理完上升沿的活,再退出中断。 在乎性能的话,int0直接接pwm输入,int1通过反向器接pwm,分别处理上升沿和下降沿,当然也可以用npn代替反向器。
回复

使用道具 举报

板凳
ID:732794 发表于 2022-4-19 21:31 | 只看该作者
PWM转换成电压信号给单片机,单片机ADC取值后除以基准,得到占空比。
此方案有微小的误差(~1%),看你的取决了。
回复

使用道具 举报

地板
ID:57657 发表于 2022-4-20 06:27 | 只看该作者
51FAN2020 发表于 2022-4-19 21:31
PWM转换成电压信号给单片机,单片机ADC取值后除以基准,得到占空比。
此方案有微小的误差(~1%),看你的 ...

此型号不支持ADC,建议使用STC8系列,其次STC15
回复

使用道具 举报

5#
ID:213173 发表于 2022-4-20 09:15 | 只看该作者
MH-Z19有两种输出:UART和PWM。
1.采用沙发建议。
2.加74157,串口分时复用。
3.换增强型芯片。
回复

使用道具 举报

6#
ID:1001922 发表于 2022-4-20 22:44 | 只看该作者
188610329 发表于 2022-4-19 21:22
不在乎性能的话,在外部中断中处理完下降沿的工作后while(p32==0);  等到上升沿后处理完上升沿的活,再退 ...

感谢 我的问题已经解决
回复

使用道具 举报

7#
ID:1001922 发表于 2022-4-20 22:44 | 只看该作者
wulin 发表于 2022-4-20 09:15
MH-Z19有两种输出:UART和PWM。
1.采用沙发建议。
2.加74157,串口分时复用。

感谢 我的问题已经解决
回复

使用道具 举报

8#
ID:1001922 发表于 2022-4-20 22:45 | 只看该作者
51FAN2020 发表于 2022-4-19 21:31
PWM转换成电压信号给单片机,单片机ADC取值后除以基准,得到占空比。
此方案有微小的误差(~1%),看你的 ...

感谢 我的问题已经解决
回复

使用道具 举报

9#
ID:1001922 发表于 2022-4-20 22:45 | 只看该作者
npn 发表于 2022-4-20 06:27
此型号不支持ADC,建议使用STC8系列,其次STC15

感谢 我的问题已经解决
回复

使用道具 举报

10#
ID:1001922 发表于 2022-4-20 23:36 | 只看该作者
我今天突然顿悟,只用STC89C516RD+单片机的定时器1实现了PWM信号的检测。大概是这样的:利用定时器,1ms进入一次中断,在中断函数中,利用if检测上升沿和下降沿,遇到上升沿就用一个变量保存高电平持续时间;遇到下降沿,就继续记录PWM持续时间,直到遇到下一个上升沿,将记录的PWM持续时间存起来。就得到了高电平持续时间和整个PWM持续时间,进而得到占空比。实测可行。
但是每1ms就进入一次中断,可能有点不好,但我说不出来哪不好。
回复

使用道具 举报

11#
ID:624769 发表于 2022-4-21 00:21 | 只看该作者
Ruuci 发表于 2022-4-20 23:36
我今天突然顿悟,只用STC89C516RD+单片机的定时器1实现了PWM信号的检测。大概是这样的:利用定时器,1ms进 ...

你的思路是对的,
1ms的确不妥, 1ms 的间隔有点太长了误差可能会大。如果只是要得到频占比的话,定时器最好是 8位自动重载模式,定时20us左右, 采样次数尽可能的多一点,10000以上吧,结果会比较精确。程序大致如下(供参考):

#define Duty_Value 50000  //设置量程 (0~65535) 这里定义5万次,20us间隔,大约1秒 计算一次频占比,
bit PWM_Done;            //标志
unsigned short Duty_H,Duty_L,PWM_H,PWM_L,Duty_ount;   //用到的变量
sbit PWM_IO = P3^2;   //定义 PWM输入引脚  (任意引脚)

void PWM_Get_Inti() //初始化
{
Duty_H = 0;
Duty_L = 0;
Duty_count = Duty_Value;
PWM_Done = 0;
//此处定义定时器
}

void T0_Int() interrupt 1     //中断
{
if(PWM_IO)
{
  Duty_H++; //测量高电平比
}
else
{
  Duty_L++; //测量低电平比
}
if(--Duty_count==0)
{
  PWM_H = Duty_H; //保存高电平比
  PWM_L = Duty_L; //保存低电平比
  Duty_H = 0; //复位
  Duty_L = 0;
  Duty_count = Duty_Value;
  PWM_Done = 1;
}
}

//主程序内:
if(PWM_Done)
{
PWM_Done = 0;  //清标志
//计算 频占比  如:    PWM_H * 100/ Duty_Value  得出 x% 高电平比,根据需要拟定
}


回复

使用道具 举报

12#
ID:887371 发表于 2022-4-21 08:43 | 只看该作者
楼主这办法,pwm频率越低,精度越高。
假如要达到100的分辨率,要远低于10Hz才行。

芯片是STC89C516RD+,外部中断只能检测到下降沿,

1.通过加反相器(例如一个npn管)来检测上升沿。
2.串口不够,可以考虑用io模拟串口。

我更倾向于用io模拟串口。
回复

使用道具 举报

13#
ID:1001922 发表于 2022-4-21 22:32 | 只看该作者
188610329 发表于 2022-4-21 00:21
你的思路是对的,
1ms的确不妥, 1ms 的间隔有点太长了误差可能会大。如果只是要得到频占比的话,定时器 ...

其实我1ms进入一次中断,是怕太频繁了,导致其他器件不能正常运行。我的DIY小玩意是检测温度,湿度,和CO2。温度湿度都好说,就是这个CO2的检测麻烦。接受PWM信号用了定时器中断,1ms中断一次,我把检测CO2和温湿度代码合在一起,然后我的我的LCD1602显示就出问题了。
回复

使用道具 举报

14#
ID:624769 发表于 2022-4-21 22:58 | 只看该作者
Ruuci 发表于 2022-4-21 22:32
其实我1ms进入一次中断,是怕太频繁了,导致其他器件不能正常运行。我的DIY小玩意是检测温度,湿度,和CO ...

你定时器中断 1ms 进入一次,只是读个高低电平,然后  ++ , -- 的话,绝对不会影响 其他程序运行的,所以,你不需要担心 1ms 太短,影响性能, 只需要担心 1ms 太长,准确度太低的问题就可以了。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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