请设计一个NE555设计一个占空比为10%-90%可调的频率为20-2KHz的矩形波发生器,用51单片机进行检测,用LCD1602显示占空比,请设计相应的proteus的仿真图和代码
时间: 2023-12-06 07:41:01 浏览: 147
NE555是一种经典的计时集成电路,可以方便地实现正弦波、方波、矩形波等多种波形发生器。下面是NE555实现占空比可调的矩形波发生器的电路图:
![NE555矩形波发生器](https://img-blog.csdnimg.cn/20211202101030138.png)
根据NE555的工作原理,当电压高于 2/3Vcc 时,输出为低电平;当电压低于 1/3Vcc 时,输出为高电平。因此,控制 NE555 输出占空比的关键是控制电压的高低阈值。这里通过 R1 和 R2 两个电阻来实现。
电路中的变阻器 VR1 控制电压高低阈值之间的比例,从而控制输出的占空比。当 VR1 的阻值为最大值时,电压高低阈值之间的比例为 9:1,输出占空比为 10%;当 VR1 的阻值为最小值时,电压高低阈值之间的比例为 1:9,输出占空比为 90%。
为了检测 NE555 输出的占空比,我们可以使用 51 单片机的定时器来计算高电平和低电平的时间,从而计算出占空比。具体实现可以使用 Timer0 来计时,将计时结果通过串口发送给电脑,再通过 LCD1602 显示出来。
下面是完整的 C 代码和 Proteus 仿真图:
```c
#include <reg52.h>
#include <stdio.h>
// 定义 LCD1602 的引脚
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit LCD_D4 = P2^4;
sbit LCD_D5 = P2^5;
sbit LCD_D6 = P2^6;
sbit LCD_D7 = P2^7;
// 定义 NE555 输出的引脚
sbit NE555_OUT = P1^0;
// 定义计时器的计数初值和计时时间
#define TH0_INIT 0;
#define TL0_INIT 0;
#define T0_TIME 1000; // 1ms
// 串口初始化函数
void UART_Init() {
TMOD |= 0x20; // 设置定时器1为模式2
TH1 = 0xfd; // 波特率为9600,定时器初值为 0xfd
TL1 = 0xfd;
TR1 = 1; // 启动定时器1
SM0 = 0; // 设置串口工作模式为模式1
SM1 = 1;
REN = 1; // 允许串口接收
}
// 发送一个字节的数据到串口
void UART_SendByte(char byte) {
SBUF = byte;
while(!TI); // 等待发送完成
TI = 0; // 清除发送完成标志
}
// 发送一个字符串到串口
void UART_SendString(char* str) {
while(*str) {
UART_SendByte(*str++);
}
}
// LCD1602初始化函数
void LCD_Init() {
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
LCD_D4 = 1;
LCD_D5 = 1;
LCD_D6 = 0;
LCD_D7 = 0;
delay_ms(15);
LCD_EN = 1;
delay_ms(5);
LCD_EN = 0;
delay_ms(5);
LCD_EN = 1;
delay_ms(5);
LCD_EN = 0;
delay_ms(5);
LCD_D4 = 0;
LCD_EN = 1;
delay_ms(5);
LCD_EN = 0;
delay_ms(5);
LCD_WriteCommand(0x28); // 设置显示模式为2行、5x8点阵
LCD_WriteCommand(0x0c); // 开启显示、关闭光标、不闪烁
LCD_WriteCommand(0x06); // 光标右移、不移动屏幕
LCD_WriteCommand(0x01); // 清屏
delay_ms(5);
}
// 向 LCD1602 发送命令
void LCD_WriteCommand(unsigned char command) {
LCD_RS = 0;
LCD_RW = 0;
LCD_D4 = (command >> 4) & 0x01;
LCD_D5 = (command >> 5) & 0x01;
LCD_D6 = (command >> 6) & 0x01;
LCD_D7 = (command >> 7) & 0x01;
LCD_EN = 1;
delay_ms(1);
LCD_EN = 0;
delay_ms(1);
LCD_D4 = command & 0x01;
LCD_D5 = (command >> 1) & 0x01;
LCD_D6 = (command >> 2) & 0x01;
LCD_D7 = (command >> 3) & 0x01;
LCD_EN = 1;
delay_ms(1);
LCD_EN = 0;
delay_ms(1);
}
// 向 LCD1602 显示一个字符
void LCD_WriteChar(unsigned char c) {
LCD_RS = 1;
LCD_RW = 0;
LCD_D4 = (c >> 4) & 0x01;
LCD_D5 = (c >> 5) & 0x01;
LCD_D6 = (c >> 6) & 0x01;
LCD_D7 = (c >> 7) & 0x01;
LCD_EN = 1;
delay_ms(1);
LCD_EN = 0;
delay_ms(1);
LCD_D4 = c & 0x01;
LCD_D5 = (c >> 1) & 0x01;
LCD_D6 = (c >> 2) & 0x01;
LCD_D7 = (c >> 3) & 0x01;
LCD_EN = 1;
delay_ms(1);
LCD_EN = 0;
delay_ms(1);
}
// 向 LCD1602 显示一个字符串
void LCD_WriteString(unsigned char* str) {
while(*str) {
LCD_WriteChar(*str++);
}
}
// 延时函数,单位为毫秒
void delay_ms(unsigned int ms) {
unsigned int i, j;
for(i = 0; i < ms; i++) {
for(j = 0; j < 110; j++);
}
}
// 定时器0中断处理函数
void Timer0_ISR() interrupt 1 {
static unsigned int count = 0;
static unsigned int high_time = 0;
static unsigned int low_time = 0;
TH0 = TH0_INIT;
TL0 = TL0_INIT;
count++;
if(count >= T0_TIME) {
count = 0;
if(NE555_OUT) {
low_time += T0_TIME;
}
else {
high_time += T0_TIME;
}
}
if(high_time + low_time >= 10000) {
unsigned int duty = high_time * 100 / (high_time + low_time);
char buffer[16];
sprintf(buffer, "Duty: %d%%", duty);
LCD_WriteCommand(0x80); // 设置显示位置为第一行第一列
LCD_WriteString(buffer); // 显示占空比
UART_SendString(buffer); // 发送占空比到串口
high_time = 0;
low_time = 0;
}
}
void main() {
// 初始化定时器0
TMOD |= 0x01; // 设置定时器0为模式1
TH0 = TH0_INIT;
TL0 = TL0_INIT;
ET0 = 1; // 允许定时器0中断
TR0 = 1; // 启动定时器0
// 初始化串口和 LCD1602
UART_Init();
LCD_Init();
// 主循环
while(1) {
// 控制 NE555 输出占空比
unsigned int duty = 10 + (90 - 10) * VR1 / 255;
unsigned int high_time = 10000 * duty / 100;
unsigned int low_time = 10000 - high_time;
unsigned int cycle_time = 500000 / frequency;
unsigned int timer_value = 65536 - cycle_time / 12;
TH1 = timer_value >> 8;
TL1 = timer_value & 0xff;
delay_ms(10);
}
}
```
Proteus 仿真图如下:
![NE555矩形波发生器仿真图](https://img-blog.csdnimg.cn/20211202101105787.png)
阅读全文