简述
这个简易系统由51单片机为主控芯片,制作一个根据光照强度展现不同亮度的照明LED,并在LCD1602上显示目前的光照强度是强或弱。光照强度用三个小灯来表示。亮度为1000则一个灯亮起,1001-2000则两个灯亮起,2001-3500则三个灯亮起。
Keil编写程序,编译出HEX导入到Proteus搭建的电路当中实现功能后,焊接实物电路。
问题
刚开始做的时候可能会遇见的问题
1.关于Proteus中仿真电路图的制作
~元器件代码不了解
~不会用辅助工具
~各个元器件之间应该如何进行连接
~如何在仿真电路中导入Keil中编译好的HEX文件
2.Keil编写程序
~TLC2543+LCD1602驱动程序的使用
~如何让LCD1602显示出TLC2543测量得到的值
~端口设置
~编写头文件
3.实物焊接
~虚焊:可能表面上连接到了,但是实际上并没有连接
~短路:可能是不同元器件之间的短路,也可能是相同元器件之间的短路
功能
1:以51单片机为主控芯片,LCD1602的数据接口D0~D7使用P0口
2:模数转换芯片使用TLC2543
3:LCD1602的显示内容有TLC2543上收到的值、LED亮度变化的阈值
4:LCD1602显示的亮度变化的阈值要可以通过按键改变
(ps:亮度的初始化阈值1000,2000这两个个数值(min=0,max=3500)。这里我用了三个按键,k1控制k2和k3加还是减,k2控制第一个阈值,k3控制第二个阈值。每一次加减为500。我设置的第一个阈值在0-1500,第二个阈值在2000-3500;若加减阈值小于或者超出临界值,则当前按键按下无效)
具体操作
仿真电路的搭建
一.软件的下载
二.工程的建立
在这里可以找到如何创建工程,同时还有一些其他可以借鉴的搭建电路的方法
三.连接
芯片与单片机连接并不是任意的,需要阅读相关的中文资料,找到对应的功能管脚,与单片机相应的管脚相连
四.元器件
刚开始我使用Proteus是比较困难的,这里可以把要用到的元器件列出来
要连接两个端口,可以点击一个端口,就会跳出一根线,然后将线拉至想要连接的另一个端口,再点击一下就完成了。
(元器件可以设置大小,刚开始找到的可能不太合适,可以双击元件进行设置进行设置)
1.CAP 33pF电容 2.CAP-ELEC 4.7uF电容 3.BUTTON 按 4.POT-HG 滑动变阻器
5.RES 电阻 可设置阻值 6.LDR 光敏电阻 7.CRYSTAL 12MHZ 晶振 8.LED-BIBY 普通的LED
9.TLC2543 模数转换芯片 10.LM016L LCD1602显示芯片 11.80C51 主控芯片
4.构建好51单片机最小系统
最小系统包括主控芯片、复位电路以及晶振电路
主控芯片:单片机P0端口连接上拉电阻
复位电路:9脚利用BUTTON(按键),CAP-ELEC(电容),RES(电阻)搭建复位电路
起振电路:18,19脚用一个晶振,两个电容
(ps:刚开始使用Proteus时,可以用接线端子整理电路,如图P0端口与上拉电阻的连接就是使用的接线端子)
终端模式中的DEFAULT中可以找到
2.将TLC2543+LM016L(LCD1602)连接到51单片机上。同时连接上按键,使得LCD1602显示的亮度变化的阈值(即)可以通过按键改变
TLC2543的连接:AIN0(1脚)连接在光敏电阻和电阻之间(这里可以选择1-12任意一个管脚,具体看怎么让编程和焊接时更加简洁方便),接收变化,并将接收到的值转化为数字。SDO\SDI\_CS\CLK这四个管脚在这可以选择单片机上没有被来连接的管脚,我这里选择的是6、7、8、16四个管脚,编写时要注意定义好端口。通过SDO将数据发送给单片机。
LCD1602的连接:D0~D7管脚连接在单片机P0端口(即32-39管脚),在上拉电阻之前。L RW/RS/E三个管脚连接在26-28三个管脚上。VDD接电源,VSS接地,VEE连接滑动变阻器,滑动变阻器接地(通过改变滑动变阻器的阻值,控制LCD1602的亮度)。
3.仿真
仿真电路搭载好之后,可以将Keil编译好的HEX文件导入到单片机中,如图所示
1.双击单片机编辑元件
2.导入编译好的HEX文件
3.开始进行仿真(左下角的三角形。正方形是停止)
注意:
1.每个芯片都要连接电源接地,在同一个项目之中还要共地;
2.在Proteus中,TLC2543&LCD1602电源管脚和接地管脚都没有显示出来,所以在焊接实物的之后要注意连接
实物焊接
如图,实物焊接一定要小心,不要短路,防止发生意外!
此外:在之前也提到芯片要通电才能正常使用,Proteus中有些芯片可能没有显示出来,在实物焊接的时候要注意连接;不然像LCD1602屏幕会很暗;同时,要注意它的哪个管脚接高,哪个管脚接低,接反可能会导致显示屏第二排无法显示出来。管脚的连接可以看之前的数据手册。
代码
1.分为三个文件
main.c+all.c+all.h
- 芯片端口的定义可以放在main.c中,也可以放在头文件里面
- 函数可以放在main.c中,也可以放在all.c中,不过这样就要在头文件中进行声明
- # 表示预编译
- 头文件一般以 #ifndef 开头,#endif结尾
2.具体代码
main.c
#include "all.h"
/*****全局变量*******/
u16 value; //TLC2543获取的值
u16 key=1000; //第一个阈值
u16 change=2000; //第二个阈值
int i,j;
long volt;
bit keep;
///******TLC2543**********/
//sbit SDO=P1^5;
//sbit SDI=P1^6;
//sbit _CS=P1^7;
//sbit CLK=P3^6;
/*********灯***********/
sbit LED1 = P2^0;
sbit LED2 = P2^1;
sbit LED3 = P2^2;
//定义按键端口
sbit k1 = P1^1;
sbit k2 = P1^2;
sbit k3 = P1^3;
///******LCD1602**********/
//sbit RS = P2^6;
//sbit RW = P2^5;
//sbit EN = P2^7;
//sbit LCD1602_E=P2^7;
//sbit LCD1602_RW=P2^5;
//sbit LCD1602_RS=P2^6;
/*延时函数*/
void delay1(u16 i) {
while(i--);
}
void delay(uchar n) {
uchar i;
for(i=0; i<n; i++) {
_nop_();
}
}
/*2543启动函数*/
uint read2543(uchar port) {
uint ad=0,i;
CLK=0;
_CS=0;
port<<=4;
for(i=0; i<12; i++) {
if(SDO) ad|=0x01;
SDI=(bit)(port&0x80);
CLK=1;
delay(3);
CLK=0;
delay(3);
port<<=1;
ad<<=1;
}
_CS=1;
ad>>=1;
volt=ad*1.221;
return(volt);
}
/*按键函数*/
void keypros() {
if(k1 == 0) {
keep = 1;//模式加
} else if(k1 == 1) {
keep = 0;//模式减
}
if((k2 == 0)&&(keep == 0)) {
key+=500;
} else if((k2 == 0)&&(keep == 1)) {
key-=500;
}
if((k3 == 0)&&(keep == 0)) {
change+=500;
} else if((k3 == 0)&&(keep == 1)) {
change-=500;
}
}
void LED() {
if(value>change) {
LED1 = 1;
LED2 = 1;
LED3 = 1;
} else if(key<=value && value<=change) {
LED1 = 1;
LED2 = 1;
LED3 = 0;
} else if(0<value && value<key){
LED1 = 1;
LED2 = 0;
LED3 = 0;
} else{
LED1 = 0;
LED2 = 0;
LED3 = 0;
}
}
/*阈值范围检测*/
void test() {
if(change>key)
{
if((key>=0)&&(key<=1500))
{
key=key;
}else if(key>=1500){
key=1500;
}else{
key=0;
}
if(change<3500){
change=change;
}else{
change=3500;
}
}
else
{
key=1000;
change=2000;
}
}
//void LED(){
// if(value>2000)
// {
// LED1 = 1;
// LED2 = 1;
// LED3 = 1;
// }else if(1000<=value && value<=2000) {
// LED1 = 1;
// LED2 = 1;
// LED3 = 0;
// } else{
// LED1 = 0;
// LED2 = 0;
// LED3 = 0;
// }
//}
/*LCD1602显示函数*/
void LCD_Display_AD(void) {
LcdWriteCom(0x80);
LcdWriteData('A');
LcdWriteData('D');
LcdWriteData(':');
LcdWriteData((value%10000000/1000000) +'0');//百万
LcdWriteData((value%1000000/100000) +'0');//十万
LcdWriteData((value%100000/10000) +'0');//万
LcdWriteData((value%10000/1000) +'0');//千
LcdWriteData((value%1000/100) +'0');//百
LcdWriteData((value%100/10) +'0');//十
LcdWriteData((value%10) +'0');//个
LcdWriteCom(0x80+0x40);
LcdWriteData((key%10000/1000) +'0');//千
LcdWriteData((key%1000/100) +'0');//百
LcdWriteData((key%100/10) +'0');//十
LcdWriteData((key%10) +'0');//个
LcdWriteData(' ');
LcdWriteData(' ');
LcdWriteData((change%10000/1000) +'0');//千
LcdWriteData((change%1000/100) +'0');//百
LcdWriteData((change%100/10) +'0');//十
LcdWriteData((change%10) +'0');//个
}
void main() {
LcdInit(); //LCD初始化
while(1) {
value = read2543(0000);
keypros();
test();
LED();
LCD_Display_AD();//调用显示程序
}
}
all.c
#include "all.h"
void Lcd1602_Delay1ms(uint c) { //误差 0us
uchar a,b,j;
for(j=c;j>0; j--)
{
for(b=199; b>0; b--)
{
for(a=1; a>0; a--);
}
}
}
void LcdWriteCom(uchar com) { //写入命令
LCD1602_E = 0; //使能
LCD1602_RS = 0; //选择发送命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待数据稳定
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
void LcdWriteData(uchar dat) { //写入数据
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择输入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //写入数据
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
void LcdInit(void) { //初始化子程序
LcdWriteCom(0x38); //开显示
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加一
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
all.h
#ifndef __ALL_H_
#define __ALL_H_
#include<reg52.h>
#include<intrins.h>
#define LCD1602_DATAPINS P0
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned int u16;
typedef unsigned char u8;
/******TLC2543**********/
sbit _CS=P1^4;
sbit SDO=P1^5;
sbit SDI=P1^6;
sbit CLK=P1^7;
/******LCD1602**********/
sbit RS = P2^6;
sbit RW = P2^5;
sbit EN = P2^7;
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
void LcdWriteCom(uchar com);
void LcdWriteData(uchar dat);
void Lcd1602_Delay1ms(uint c);
void LcdInit(void);
#endif