单片机
返回首页

#C51中断定时(PWM输出+外部中断频率检测)

2022-09-15 来源:csdn

前言

C51单片机自身无PWM输出,可以借用T1定时中断输出一定频率的脉冲信号,且占空比可调,便于继续开发


提示:以下是本篇文章正文内容,下面案例可供参考


一、场景

样例1:P3引脚输出固定频率PWM信号,占空比人为调整

样例2:PWM+外部中断检测频率验证

步步进阶

二、PWM简介

PWM(Pulse Width Modulation)脉冲宽度调制,是一种对模拟信号电平进行数字编码的方法。

占空比:高电平占周期的比例,如f=1Hz,T=1s,T1=0.5s,占空比即为50%


在这里插入图片描述

为什么这么说呢?

1.pwm本身就是一个方波信号,1和0对应数字电路中高电平、低电平。

2.思考下:负载两端(如LED、直流电机等)直流供电,高电平时ON,低电平时OFF。

3.若是将PWM信号输出至负载两端(如1Hz/5V,占空比50%)~~==~~理论上0.5s全部导通,0.5s全部关闭。此时,负载两端的等效电压约2.5V(5V*50%)工作时状态。电路中电流发生变化,器件工作状态受到影响。

简言之,在合适的频率信号下,通过调整PWM占空比,可以改变输出电压的有效值


三、编程实现

样例1:PWM+占空比软件调整

1.设计思路:

设计f = 10Hz的PWM信号,T = 100ms。

将T分割成100份,每份1ms


2.代码设计

1.T1定时初始化


void Timer1Init(void) //1ms @11.0592MHz 

{

TMOD &= 0x0F; //设置定时模式 GATE C/T^ M1 M0  // 0 0 0 1

TMOD |= 0x10; //设置定时模式 T1 方式1 16位定时器

TH1 = (65536 - 1000) / 256; //初值

TL1 = (65536 - 1000) % 256;

TF1 = 0; //清除TF1标志

ET1 = 1;//打开定时器T1

TR1 = 1; //定时器1开始计时

}


2.T1中断服务函数


//2.PWM输出处理

TR1  = 0;

vPWMCnt++;

if(vPWMCnt <= PWM_DUTY)

{

PWM = 1;

}

else if(vPWMCnt <= 100)

{

PWM = 0;

}

else 

{

vPWMCnt = 0;

}

TH1 = (65536 - 1000) % 256; //重装初值

TL1 = (65536 - 1000) / 256;

TR1 = 1;


3.调试验证

P3.0输出PWM,周期比时钟源输出的要大一点

在这里插入图片描述

改变占空比,波形改变


#define PWM_DUTY 20 //占空比

在这里插入图片描述

样例2:PWM+外部中断检测频率

1.设计思路:

P3.0输出PWM信号

外部中断INT0+T0结合检测频率

数码管显示频率数值


2.代码设计

1.外部中断INT0初始化


void EX0Init(void)

{

IT0 = 1; //外部中断0触发方式 0:电平触发(低电平有效)1:边沿触发(高->低负跳变)

EX0 = 1; //允许外部中断0中断

}


2.外部中断INT0中断服务函数


void Ex0_ISR() interrupt 0

{

//2.外部中断计数方案

EX0 = 0;

vFreqCnt_Ex0++;

EX0 = 1;

}


3.T0定时中断服务函数(1ms)


void Timer0_ISR() interrupt 1

{

UI vFreqCnt;

vFreqCnt++;

if(vFreqCnt > 1000)

{

vFreqCnt = 0;

EX0 = 0;

gFreqCnt = vFreqCnt_Ex0;

vFreqCnt_Ex0 = 0;

EX0 = 1;

}

}


4.频率显示处理


NumDisSpare(gFreqCnt);


void NumDisSpare(unsigned int vDisNum)

{

if(vDisNum >= 1000)

{

SEG_DisBuf[0]  = vDisNum / 1000;

}

else

{

SEG_DisBuf[0] = 23;

}

if(vDisNum >= 100)

{

SEG_DisBuf[1]  = vDisNum / 100 % 10;

}

else 

{

SEG_DisBuf[1] = 23;

}

if(vDisNum >= 10)

{

SEG_DisBuf[2]  = vDisNum / 10 % 10;

}

else

{

SEG_DisBuf[2] = 23;

}

SEG_DisBuf[3]  = vDisNum % 10;

}


3.调试验证

1.利用上篇简单频率测试方式,进行检测并显示

在这里插入图片描述

总结

1.原计划一篇讲完再利用PWM实现LED呼吸灯功能,篇幅过长,下篇继续。

2.仿真环境下与实际的的确有偏差,proteus下输出PWM方波,周期偏差3ms左右。实际电路板示波器观测没有这么大偏差。晶振已经排查,具体原因再研究研究。

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 基于IC555的可变PWM振荡器电路

  • 优化电路板布局的简单方法

  • 如何使用LED驱动器LM3915制作振动计

  • 分享一个电网倾角计电路

  • 电谐波图形均衡器示意图

  • 一种构建12V和230V双直流电源的简单方法

    相关电子头条文章