【Proteus仿真】51单片机+DAC0832+LCD1602制作LM317数控直流电源

【Proteus仿真】51单片机+DAC0832+LCD1602制作LM317简易数控直流电源


  • 🎬Proteus仿真
    在这里插入图片描述

✨需要注意的是:当电压调低时,实际显示的电压值和LM317输出值有1.2V的差异,不是很准确。

DAC0832简略介绍

DAC0832是8位的D/A转换集成芯片.

  • VREF:基准电压输入引脚,VREF的范围为-10V~+10V;
  • Vcc:电源输入端,Vcc的范围为:+5V~+15V;
  • IOUT1:电流输出端1,其值随DAC寄存器的内容线性变化;
  • IOUT2:电流输出端2,其值与IOUT1值之和为一常数;
  • 电压调节范围约值0~10V可调。

📝示例代码

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
#include <reg51.h>
#include<string.h>

typedef unsigned char u8; // 重命名类型u8简化代码编写
typedef unsigned int u16;

#define LCD1602\_DATA\_PORT P2 // LCD1602的8位数据端口

sbit gLcd1602_E = P3^2; // LCD1602控制总线的使能信号
sbit gLcd1602_RW = P3^1; // LCD1602控制总线的读写选择信号
sbit gLcd1602_RS = P3^0; // LCD1602控制总线的数据/命令选择信号

sbit Key1 = P3^5;
sbit Key2 = P3^7;

float Output_DA = 200;

void delay10ms(void)
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);
}

void Lcd1602WaitNoBusy(void) //忙检测函数,判断bit7是0,允许执行;1禁止
{
unsigned char sta = 0; //

LCD1602_DATA_PORT = 0xff;
gLcd1602_RS = 0;
gLcd1602_RW = 1;
do
{
gLcd1602_E = 1;
sta = LCD1602_DATA_PORT;
gLcd1602_E = 0; //使能,用完就拉低,释放总线
}while(sta & 0x80);
}

void Lcd1602WriteCmd(unsigned char cmd)
{
Lcd1602WaitNoBusy(); // 先等待LCD1602处于不忙状态

gLcd1602_E = 0; // 禁止LCD
gLcd1602_RS = 0; // 选择发送命令模式
gLcd1602_RW = 0; // 选择写入模式
LCD1602_DATA_PORT = cmd; // 将1字节命令字放入8位并行数据端口
gLcd1602_E = 1; // 使能LED
gLcd1602_E = 0; // 禁止LCD
}

void Lcd1602WriteData(unsigned char dat)
{
Lcd1602WaitNoBusy(); // 先等待LCD1602处于不忙状态

gLcd1602_E = 0; // 禁止LCD
gLcd1602_RS = 1; // 选择发送数据模式
gLcd1602_RW = 0; // 选择写入模式
LCD1602_DATA_PORT = dat; // 将1字节命令字放入8位并行数据端口
gLcd1602_E = 1; // 使能LED
gLcd1602_E = 0; // 禁止LCD
}

void Lcd1602SetCursor(unsigned char x,unsigned char y) // 坐标显示
{
unsigned char addr = 0;

switch (y)
{
case 0: // 上面一行
addr = 0x00 + x; break;
case 1: // 下面一行
addr = 0x40 + x; break;
default:
break;
}
Lcd1602WriteCmd(addr | 0x80);
}

void Lcd1602ShowStr(unsigned char x, unsigned char y, unsigned char \*pStr) //显示字符串
{
Lcd1602SetCursor(x, y); //当前字符的坐标
while (\*pStr != '\0')
{
Lcd1602WriteData(\*pStr++);
}
}

void Lcd1602Init(void)
{
Lcd1602WriteCmd(0x38); // 按照数据手册的初始化时序,先发送38H
delay10ms(); // 延时10ms
Lcd1602WriteCmd(0x38); // 按照数据手册的初始化时序,先发送38H
delay10ms(); // 延时10ms
Lcd1602WriteCmd(0x38); // 按照数据手册的初始化时序,先发送38H
delay10ms(); // 延时10ms
Lcd1602WriteCmd(0x38); // 显示模式设置
Lcd1602WriteCmd(0x08); // 关闭显示
Lcd1602WriteCmd(0x01); // 清屏(同时清数据指针)
Lcd1602WriteCmd(0x06); // 读写后指针自动加1,写1个字符后整屏显示不移动
Lcd1602WriteCmd(0x0c); // 开显示,不显示光标

Lcd1602ShowStr(2,0,"NC ADJ POWER ");
Lcd1602ShowStr(0,1,"Voltage: V");
}

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 显示函数 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void Write\_Volt(unsigned char hang,unsigned char add,unsigned int date) //用于显示
{
if(hang==1)
Lcd1602WriteCmd(0x80+add);
else
Lcd1602WriteCmd(0x80+0x40+add);
Lcd1602WriteData(0x30+date%1000/100); //显示百位
Lcd1602WriteData(0x30+date%100/10); //显示十位
Lcd1602WriteData('.'); //显示.
Lcd1602WriteData(0x30+date%10); //显示个位
Lcd1602WriteData('V'); //显示字母V
}

void Out\_Volt(unsigned char Volt)
{
P0=Volt;
}

void main()
{
Lcd1602Init();
while (1)
{
Out\_Volt(Output_DA);

if (Key1 == 0)
{
delay10ms();
if (Key1 == 0)
{
if(Output_DA < 200) Output_DA += 2;
}
while(!Key1);
}
if (Key2 == 0)
{
delay10ms();
if (Key2 == 0)
{
if(Output_DA >= 2) Output_DA -= 2;
}
while(!Key2);
}

Write\_Volt(0,8,Output_DA/2.0);
}
}

程序源码和仿真资源

1
2
3
链接:https://pan.baidu.com/s/1ByxFQLLneV9XNUqZ\_A0ioA 
提取码:exs0