基于proteus的51单片机开发实例38-TLC2543

基于proteus的51单片机开发实例38-TLC25431 基于 proteus 的 51 单片机开发实例 38 TLC25431 1 实验目的我们已经学习了 ADC0809 和 ADC0832 两种模数转换芯片的基础知识 电路设计 程序控制 大家可能会发现 这两种芯片都是 8 位的 A D 转换

欢迎大家来到IT世界,在知识的湖畔探索吧!

基于proteus的51单片机开发实例38-TLC2543



欢迎大家来到IT世界,在知识的湖畔探索吧!

1. 基于proteus的51单片机开发实例38-TLC2543

1.1. 实验目的

我们已经学习了ADC0809和ADC0832两种模数转换芯片的基础知识、电路设计、程序控制,大家可能会发现,这两种芯片都是8位的A/D转换。而对于现在的很多应用来说,8位A/D转换已经显得不够精确了,本实例继续来学习模数转换芯片TLC2543,这是一款12位的A/D转换芯片,已经能够满足多数需求了。

1.2. 设计思路

图1是本实例的电路图,本实例通过TLC2543采集电位器滑动端的电压值,将采集到的电压值以SPI串行通信方式发送到单片机,单片机将接收到的数值转换为实际的电压值,然后将该电压值通过LCD1602液晶显示出来。

基于proteus的51单片机开发实例38-TLC2543

图1 TLC2543电路

1.3. 基础知识

TLC2543是一种12位串行A/D转换芯片。串行通信方式是SPI。有11路模拟输入通道,也就是说TLC2543可以同时采集11路模拟电压。

1.3.1. TIL2543引脚说明

下图所示是TLC2543的引脚图。

基于proteus的51单片机开发实例38-TLC2543

图2 TLC2543引脚图

AIN0~AIN10:11路模拟电压输入;11路输入信号由内部多路器选择。对于4.1MHz的I/O CLOCK,驱动源阻抗必须小于等于50Ω,而且用60pF的电容来限制模拟输入电压的斜率。

VCC、GND:电源、地;

CS:片选端,低电平有效;在CS由高到低的变化时,内部计数器复位,由低到高变化时,在设定时间内禁止DATA INPUT和I/O CLOCK。

I/O CLOCK:时钟端,提供通信时钟;该端口接收串行输入信号并完成以下四个功能:1)在I/O CLOCK的前8个上升沿,8位输入数据存入输入数据寄存器;2)在I/O CLOCK的第四个下降沿,被选通的模拟输入电压开始向电容器充电,直到I/O CLOCK的最后一个下降沿为止。3)将前一次转换数据的其余11位输出到DATA OUTPUT端,在I/O CLOCK的下降沿时数据开始变化;4)I/O CLOCK的最后一个下降沿,将转换的控制信号传送到内部状态控制位。

DATA INPUT:SPI通信数据输入端;由4位的串行地址输入来选择模拟量输入通道。

DATA OUTPUT:SPI通信数据输出端;CS为高时,高端口处于高阻状态,CS为低时处于激活状态。

EOC:转换结束端;在最后的I/O CLOCK下降沿之后,EOC从高电平变为低电平并保持到转换完成和数据准备传输为止。

REF+、REF-:正、负基准电压端,这两端接基准直流电压,作为输入模拟电压的电压标准对比端,所以这个电压非常重要,要确保该电压的稳定性和准确性。

1.3.2. TLC2543操作流程

使用TLC2543时,首先要通过DATA INPUT端口向芯片写入控制字,控制字为1个字节(8位),这个控制字决定了TLC2543要转换的模拟通道的通道号,转换后的数据长度及输出数据的格式。

1、工作方式选择

控制字的高4位决定了A/D采集的通道号,例如,高四位数据为0010,代表选择的通道是第2通道。当高4位为1110时,TLC2543进入休眠状态。

2)转换结果输出格式选择

控制字的低4位选择输出数据的格式和长度。如下图所示

基于proteus的51单片机开发实例38-TLC2543

图3 TLC2543转换结果输出格式

1.3.3. TLC2543的通信时序

TLC2543上电后,片选端口CS必须有一个从高到低的变化,然后才能开始一次工作周期。此时EOC需要保持高电平,表示当前输出寄存器的内容是上一次采集的数据。在I/O CLOCK的时钟控制下,依次向DATA INPUT引脚写入控制字,控制字的每一位在时钟信号的上升沿被送入TLC2543(先传送高位)。同时,data output也在每个时钟信号的下降沿开始按位输出数据。

TLC2543收到第四个时钟信号后,模拟通道选择数据已送完,TLC2543随即开始对该次选定通道的模拟量进行采样,并保持到第12个时钟的下降沿。在第12个时钟下降沿到来时,EOC变为低电平,开始对本次采样的模拟量进行A/D转换,转换时间约为10uS,转换完成后EOC变为低电平,转换的数据保存在输出数据寄存器中,等待下一个时钟周期时通过DATA OUTPUT 输出。

当VREF+接+5V,VREF-接地时,模拟电压与输出结果的关系为:模拟电压=输出结果/819。

基于proteus的51单片机开发实例38-TLC2543

图4 时钟传送时序图,使用CS,MSB在前

基于proteus的51单片机开发实例38-TLC2543

图5 时钟传送时序图 不使用CS MSB在前

1.4. 电路设计

本实例电路图如图1所示。

对于TLC2543的电路连接:外电压输入通道选择TLC2543的AIN4端口,该端口连接一个可调电阻,通过调整可调电阻的滑动端,使TLC2543的模拟输入端获得不同的电压值。TLC2543的参考电压端接+5V的稳定参考电压。单片机的P3.0~P3.4分别连接TLC2543的SDO、SDI、CS、CLK、EOC这几个管脚。

单片机的P0口连接LCD1602液晶的8位数据端D0~D7。同时P0口的8个引脚要连接上拉电阻,本电路中通过一个排阻连接到电源正极,作为8个引脚的上拉电阻。

单片机的P2.0、P2.1、P2.2这三个端口分别控制LCD1602液晶的RS、RW、E这三个控制端。

基于proteus的51单片机开发实例38-TLC2543

1.5. 程序设计

本实例的程序代码如下。

由于本程序涉及到LCD1602液晶的控制,TLC2543的控制以及一些延时函数,包含的功能模块比较多,所以我们采用模块化的程序设计方法,将这几个功能模块分别编写.c和.h文件。其中.h文件包含宏定义、管脚定义、函数声明等,.c文件包含全局变量的声明,函数的定义等内容。

主程序代码

#include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #include"LCD1602.h" #include"TLC2543.h" #include"Delay.h" unsigned char code digit[10]={"0"}; //定义字符数组显示数字 unsigned char code Str[]={"Volt="}; //说明显示的是电压 / 模块名:main.c 模块功能:控制主程序工作流程,实现程序功能 */ /* 函数功能:显示转换结果 入口参数:ad_val,储存A/D转换结果 */ void Display_N(unsigned int ad_val) { unsigned char i,j,k,l; i=ad_val/1000; //取千位数字 j=(ad_val%1000)/100; //取百位数字 k=(ad_val%100)/10; //取十位数字 l=ad_val%10; //取个位数字 WriteAddress(0x01); //写显示地址,将在第1行第1列开始显示 WriteData('N'); // 显示“N=” WriteData('='); WriteData(digit[i]); //显示千位数字 WriteData(digit[j]); //显示百位数字 WriteData(digit[k]); //显示十位数字 WriteData(digit[l]); //显示个位数字 } /* 函数功能:显示采集电压 入口参数:ad_val,储存A/D转换结果 */ void Display_Voltage(unsigned int ad_val) { unsigned char i,j,k; unsigned char INT; //储存电压整数部分数字 unsigned int DEC; //储存电压小数部分的前三位数字 float u; u=ad_val/819.0; INT=(unsigned char)u; DEC=(unsigned int)(u*1000-INT*1000); i=DEC/100; //取电压的小数点第一位 j=(DEC%100)/10; //取电压的小数点第二位 k=DEC%10; //取电压的小数点第三位 WriteAddress(0x41); //写显示地址,将在第2行第1列开始显示 WriteData('U'); // 显示“U=” WriteData('='); WriteData(digit[INT]); //显示电压整数值 WriteData('.'); //显示小数点 WriteData(digit[i]); //显示小数点第一位 WriteData(digit[j]); //显示小数点第二位 WriteData(digit[k]); //显示小数点第三位 WriteData('V'); //显示电压的单位“V” } /* 函数功能:主函数 */ main(void) { unsigned int AD_Result; LcdInitiate(); //将液晶初始化 while(1) { AD_Result= A_D(4); //选中通道4进行A/D转换 Display_N(AD_Result); //显示转换结果 Display_Voltage(AD_Result); //将转换结果显示为输入的检测电压 } }

欢迎大家来到IT世界,在知识的湖畔探索吧!

液晶显示代码

欢迎大家来到IT世界,在知识的湖畔探索吧!/* 以下是对液晶模块的操作程序 */ sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚 sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚 sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚 sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚 /* 函数功能:判断液晶模块的忙碌状态 返回值:result。result=1,忙碌;result=0,不忙 */ bit BusyTest(void); /* 函数功能:将模式设置指令或显示地址写入液晶模块 入口参数:dictate */ void WriteInstruction (unsigned char dictate); /* 函数功能:指定字符显示的实际地址 入口参数:x */ void WriteAddress(unsigned char x); /* 函数功能:将数据(字符的标准ASCII码)写入液晶模块 入口参数:y(为字符常量) */ void WriteData(unsigned char y); /* 函数功能:对LCD的显示模式进行初始化设置 */ void LcdInitiate(void); 
#include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #include"LCD1602.h" #include"TLC2543.h" #include"Delay.h" extern unsigned char code digit[10]; //定义字符数组显示数字 extern unsigned char code Str[]; //说明显示的是电压 / 模块名:1602.c 模块功能:1602LCD显示驱动 */ ////////////////////////////////////////////////////////////////// /* 以下是对液晶模块的操作程序 */ /* 函数功能:判断液晶模块的忙碌状态 返回值:result。result=1,忙碌;result=0,不忙 */ bit BusyTest(void) { bit result; RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态 RW=1; E=1; //E=1,才允许读写 _nop_(); //空操作 _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 result=BF; //将忙碌标志电平赋给result E=0; //将E恢复低电平 return result; } /* 函数功能:将模式设置指令或显示地址写入液晶模块 入口参数:dictate */ void WriteInstruction (unsigned char dictate) { while(BusyTest()==1); //如果忙就等待 RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲, // 就是让E从0到1发生正跳变,所以应先置"0" _nop_(); _nop_(); //空操作两个机器周期,给硬件反应时间 P0=dictate; //将数据送入P0口,即写入指令或地址 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 } /* 函数功能:指定字符显示的实际地址 入口参数:x */ void WriteAddress(unsigned char x) { WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x" } /* 函数功能:将数据(字符的标准ASCII码)写入液晶模块 入口参数:y(为字符常量) */ void WriteData(unsigned char y) { while(BusyTest()==1); RS=1; //RS为高电平,RW为低电平时,可以写入数据 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲, // 就是让E从0到1发生正跳变,所以应先置"0" P0=y; //将数据送入P0口,即将数据写入液晶模块 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 } /* 函数功能:对LCD的显示模式进行初始化设置 */ void LcdInitiate(void) { DelayXms(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间 WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口 DelayXms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x38); DelayXms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x38); //连续三次,确保初始化成功 DelayXms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x0c); //显示模式设置:显示开,无光标,光标不闪烁 DelayXms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x06); //显示模式设置:光标右移,字符不移 DelayXms(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除 DelayXms(5); //延时5ms ,给硬件一点反应时间 } 

TLC2543控制部分代码

欢迎大家来到IT世界,在知识的湖畔探索吧! sbit SDO=P3^0; //数据输出引脚 sbit SDI=P3^1; //数据输入引脚 sbit CS=P3^2; //片选引脚 sbit CLK=P3^3; //时钟脉冲引脚 sbit EOC=P3^4; //转换结束引脚 //将模拟信号转换成数字信号 unsigned int A_D(unsigned char CH_i); 
//TLC2543.c #include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #include"LCD1602.h" #include"TLC2543.h" #include"Delay.h" /* 函数功能:将模拟信号转换成数字信号 */ unsigned int A_D(unsigned char CH_i) //CH_i,通道值 { unsigned int AD_Val; //储存12位的A/D转换结果 unsigned char i; AD_Val=0; CS=1; //一个转换周期开始 EOC=0; CLK=0; //为第一个脉冲作准备 _nop_(); _nop_(); CS=0; //CS置0,片选有效 EOC=1; //EOC开始应设为高电平 CH_i<<=4; //将通道值(D7,D6,D5,D4)移入高四位,转换通道设置 CH_i|=0x02; //D3,D2,D1,D0=0,0,1,0 ,输出数据为12位,先输出低位 for(i=0;i<8;i++) //将A/D转换方式控制字写入TLC2543,并读取低8位转换结果 { AD_Val>>=1; //将读取结果逐位右移(先输出的是低位) CLK=0; _nop_(); if((CH_i&0x80)==0x80) SDI=1; else SDI=0; CH_i<<=1; //在脉冲上升沿,从高位至低位依次将控制字写入TLC2543 CLK=1; _nop_(); if(SDO==1) //在脉冲下降沿,TLC2543输出数据,写入AD_Val的第12位 { AD_Val|=0x800; } else { AD_Val|=0x000; } } SDI=0; //8个数据流输入后,SDI端必须保持在一个固定的电平上,指引EOC变高 for(i=8;i<12;i++) //读取转换值的第8至第11位 { AD_Val>>=1; CLK=0; _nop_(); CLK=1; _nop_(); if(SDO==1) { AD_Val|=0x800; //在脉冲下降沿,TLC2543输出数据,写入AD_Val的第12位 } else { AD_Val|=0x000; //第12位写 ‘0’ } } CLK=0; //在第12个时钟下降沿来临时,EOC开始变低,开始对本次采样的模拟量进行A/D转换, _nop_(); //给硬件一点转换时间 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); CS=1; // 停止转换,高电平无效 EOC=0; return AD_Val; } 

延时函数代码

欢迎大家来到IT世界,在知识的湖畔探索吧!//Delay.h //延时1ms void Delay1ms(); //延时若干毫秒 void DelayXms(unsigned int DelayCounter);
 #include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #include"LCD1602.h" #include"TLC2543.h" #include"Delay.h" /* 函数功能:延时1ms (3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒 */ void Delay1ms() { unsigned char i,j; for(i=0;i<10;i++) for(j=0;j<33;j++) ; } /* 函数功能:延时若干毫秒 入口参数:n */ void DelayXms(unsigned int DelayCounter) { unsigned int i; for(i=0;i<DelayCounter;i++) Delay1ms(); }

1.6. 实例仿真

完成本实例的电路设计和程序设计后,将程序编译后生成的hex文件装载到单片机中,开始仿真模式,观察仿真结果,同时可以调节电位器的滑动端,使得TLC2543模拟电压输入端的电压发生变化,观察获取的电压值是否正确并显示在液晶上。

视频加载中…

1.7. 总结

本例是我们学习A/D和D/A转换知识的第5个实例,本实例最大区别是采集电压值由之前的8位变成了12位。老实说,8位A/D或者D/A在现在已经很少用了。所以我们需要掌握和使用位以上的A/D或D/A。

基于proteus的51单片机开发实例38-TLC2543

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/101637.html

(0)
上一篇 2天前
下一篇 2天前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信