【Proteus仿真】51单片机+lcd1602显示定时器实现PWM输出

【Proteus仿真】51单片机+lcd1602显示定时器实现PWM输出


  • 🔖基于Proteus8.12平台。
  • ✨lcd显示具体频率和占空比,通过按键调节占空比。
  • 🎬LCD显示
    在这里插入图片描述

📝主程序代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <reg52.h>
#include "LCD1602.H"
#define uchar unsigned char
#define uint unsigned int

unsigned int fr = 50; //频率 50hz
unsigned char dc = 50; //50%占空比
uchar fr_g = 0;
uchar fr_s = 0;
uchar dc_g = 0;
uchar dc_s = 0;
/\* 配置并启动 PWM,fr-频率,dc-占空比 \*/

unsigned int high, low;
unsigned long tmp;
unsigned char HighRH = 0; //高电平重载值的高字节
unsigned char HighRL = 0; //高电平重载值的低字节
unsigned char LowRH = 0; //低电平重载值的高字节
unsigned char LowRL = 0; //低电平重载值的低字节

void ConfigPWM();
void ClosePWM();

sbit key1 = P3 ^ 1; //定义按键位置 加占空比
sbit key2 = P3 ^ 0; //定义按键位置 减占空比
sbit PWMOUT = P2 ^ 1;

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
//\* 名称 : Delay\_1ms()
//\* 功能 : 延时子程序,延时时间为 1ms \* x
//\* 输入 : x (延时一毫秒的个数)
//\* 输出 : 无
//\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void Delay\_1ms(uint i)//1ms延时
{
uchar x, j;
for(j = 0; j < i; j++)
for(x = 0; x <= 148; x++);
}

void key()
{

if(!key1) //按下相应的按键,数码管显示相应的码值
{
Delay\_1ms(10);
if(!key1)
{
if(dc++ >= 100)dc = 100;

}
while(!key1);
}

if(!key2)
{
Delay\_1ms(10);
if(!key2)
{
if(dc-- <= 0)dc = 100;

}
while(!key2);
}
}

void ConfigPWM()
{
tmp = (11059200 / 12) / fr; //计算一个周期所需的计数值
high = (tmp \* dc) / 100; //计算高电平所需的计数值
low = tmp - high; //计算低电平所需的计数值
high = 65536 - high + 12; //计算高电平的重载值并补偿中断延时
low = 65536 - low + 12;//计算低电平的重载值并补偿中断延时

HighRH = (unsigned char)(high >> 8); //高电平重载值拆分为高低字节
HighRL = (unsigned char)high;
LowRH = (unsigned char)(low >> 8); //低电平重载值拆分为高低字节
LowRL = (unsigned char)low;

TMOD &= 0xF0; //清零 T0 的控制位
TMOD |= 0x01; //配置 T0 为模式 1
TH0 = HighRH; //加载 T0 重载值
TL0 = HighRL;
ET0 = 1; //使能 T0 中断
TR0 = 1; //启动 T0
PWMOUT = 1; //输出高电平
}

/\* 关闭 PWM \*/
void ClosePWM()
{
TR0 = 0; //停止定时器
ET0 = 0; //禁止中断
PWMOUT = 1; //输出高电平
}

void main()
{
uint i;
LCD1602\_Init(1, 0, 0); //lcd1602初始化
Delay\_1ms(100);

LCD1602\_DisplayChar(1, 2, ':'); //显示e
LCD1602\_DisplayChar(2, 1, 'd'); //显示p
LCD1602\_DisplayChar(2, 2, ':'); //显示:
LCD1602\_DisplayChar(1, 6, 'H'); //显示t
LCD1602\_DisplayChar(1, 7, 'Z'); //显示e
LCD1602\_DisplayChar(2, 6, '%'); //显示t
LCD1602\_DisplayChar(1, 1, 'f'); //显示t
TMOD = 0x00;
TL1 = 0xD8;
TH1 = 0xf0;
TR1 = 1; //启动定时器
ET1 = 1; //使能定时器中断
EA = 1; //开总中断
while(1)
{
key();
ConfigPWM();
for(i = 0; i < 40000; i++);
fr_g = fr % 10;
fr_s = fr / 10;
dc_g = dc % 10;
dc_s = dc / 10;
LCD1602\_DisplayChar(1, 4, fr_s + 48); //显示t
LCD1602\_DisplayChar(1, 5, fr_g + 48); //显示e
LCD1602\_DisplayChar(2, 4, dc_s + 48); //显示p
LCD1602\_DisplayChar(2, 5, dc_g + 48); //显示:

}

}


/\* T0 中断服务函数,产生 PWM 输出 \*/
void InterruptTimer0() interrupt 1
{

if(PWMOUT == 1)
{
//当前输出为高电平时,装载低电平值并输出低电平
TH0 = LowRH;
TL0 = LowRL;
PWMOUT = 0;
}
else
{
//当前输出为低电平时,装载高电平值并输出高电平
TH0 = HighRH;
TL0 = HighRL;
PWMOUT = 1;
}
}
void TM1\_Isr() interrupt 3 using 1
{
key();
}


📚LCD显示驱动程序和仿真资源

1
2
3
链接: https://pan.baidu.com/s/1OotC289Ejxadayl200DjqA
提取码: piiy