新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 我的TLC2543学习笔记——基于msp430g2553单片机

我的TLC2543学习笔记——基于msp430g2553单片机

作者:时间:2016-11-28来源:网络收藏
Createdon:2012-9-8

Author:zhangbin

本文引用地址:http://www.eepw.com.cn/article/201611/322845.htm

学习笔记

formsp430g2553

redesignedbyzhangbin

2012-09-08

versions:12_09_01

AllRightsReserved

TLC2543具有4线制串行接口,分别为片选端(CS),串行时钟输入端(I/OCLOCK),串行数据输入端(DATAIN)和串行数据输出端(DATAOUT)(转换结束脚EOC可以不接)。它可以直接与SPI器件进行连接,不需要其他外部逻辑。同时,它还在高达4MHz的串行速率下与主机进行通信。

TLC2543的特点及引脚

TLC2543是TI的12bit串行A/D转换器,11个模拟输入通道。使用开关电容逐次逼近技术完成,A/D转换过程.由于是串行输入结构,能够MCU的I/O资源.其特点有:

1)12bit分辨率A/D转换器;

2)在工作温度范围内10us转换时间;

3)11个模拟输入通道;

4)3路内置自测试方式;

5)采样率为66kb/s;

6)线性误差+1LSB(max);

7)有转换结束(EOC)输出;

8)具有单、双极性输出;

9)可编程的MSB或LSB前导;

10)可编程的输出数据长度.

���12-Bit-ResolutionA/DConverter

���10-μsConversionTimeOverOperating

Temperature

���11AnalogInputChannels

���3Built-InSelf-TestModes

���InherentSample-and-HoldFunction

���LinearityError...±1LSBMax

���On-ChipSystemClock

���End-of-ConversionOutput

���UnipolarorBipolarOutputOperation

(SignedBinaryWithRespectto1/2the

AppliedVoltageReference)

���ProgrammableMSBorLSBFirst

���ProgrammablePowerDown

���ProgrammableOutputDataLength

���CMOSTechnology

���ApplicationReportAvailable

我用的tlc2543是直插的,引脚图如下:

各引脚的详细说明如下:

引脚号

名称

I/O

说明

1~9,11,12

AIN0~AIN10

I

模拟量输入端。11路输入信号由内部多路器选通。对于4.1MHz的I/OCLOCK,驱动源阻抗必须小于或等于50Ω,而且用60pF电容来限制模拟输入电压的斜率

15

 

I

片选端。在端由高变低时,内部计数器复位。由低变高时,在设定时间内禁止DATAINPUT和I/OCLOCK

17

DATAINPUT

I

串行数据输入端。由4位的串行地址输入来选择模拟量输入通道

16

DATAOUT

O

A/D转换结果的三态串行输出端。为高时处于高阻抗状态,为低时处于激活状态

19

EOC

O

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

10

GND

地。GND是内部电路的地回路端。除另有说明外,所有电压测量都相对GND而言

18

I/OCLOCK

I

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

14

REF+

I

正基准电压端。基准电压的正端(通常为Vcc)被加到REF+,最大的输入电压范围由加于本端与REF-端的电压差决定

13

REF-

I

负基准电压端。基准电压的低端(通常为地)被加到REF-

20

Vcc

电源

写程序时,要参考对应的时序图,严格按照时序进行操作就可以了,我用到的时序图如下:

是16时钟的,使用CS,MSBfirst:

对tlc2543进行操作的时候,尤其是要用到它的多通道工作时,要特别注意各个通道的操作,因为如果操作不当,就有可能读出的不是想要通道的数据(我就遇到过类似的问题)。下面我就这个问题介绍一下我自己的经验和解决办法。

首先先看一下数据手册上的输入寄存器的命令介绍:

在进行操作之前,必须要看清楚上面的命令表格。要特别注意,通道选择的指令的位置在8位输入指令的高8位D7~D4,清楚了这一点,就可以明白程序中对tlc2543进行操作的函数中为什么会有一句port<<=4;//左移4位了。

还要注意一点是:对TLC2543进行操作函数的原型是uinttlc_read(ucharport),其中参数port为指定的通道数。调用它的时候,通道0对应的port为0x00(或十进制的0),调用形式应该是tlc_read(0x00);通道1,对应的为tlc_read(0x01)或tlc_read(1);通道6对应的为tlc_read(0x06)或tlc_read(6)。总之上面所使用的port的代表通道数在port八位的低四位,这样通过上面的移位指令port<<=4;就可以把这4位通道指令移到高四位了,而这刚好符合上面表格中寄存器对命令的规则。

如果想在调用tlc_read(ucharport)时用port的高四位代表选择的通道数,如通道1为0x10,通道3为0x30,通道6为0x60等的话,那么这样的port8位直接送入,通道选择的4位数据就直接在高4位了,很容易就知道函数中的移位指令port<<=4;就不应该再要了。

上面是通道选择的时候要注意的问题。但是还有一个问题是通道选择正确,注意了上面的问题,但是读出的数据就不是我们想要的通道的数据。这就涉及到下面的问题了。

从给2543送入选择的通道数,到它AD转换完成了,输出数据这一过程需要一段时间,时间很短,但是就产生了一个问题。问题是这样的:我上面所写的函数uinttlc_read(ucharport)是有返回值的,返回值是tlc输出的AD转换的结果。由于我在实现该函数的时候,没有让tlc转换多次(一般是3次),而是直接转换一次就输出了结果(具体程序我下面会贴出)。值就导致了本次转换输出的结果是上一次输入命令选择的通道的转化值。而这一次输入命令选择的通道的转换结果,就在下一次输出。上面的问题不难理解,明白了上面的问题,就很容易知道了解决办法了,有两个:1,直接在函数uinttlc_read(ucharport)中,控制tlc循环对这一次选择的通道port转换多次(一般为3次,比较保险,速度又比较快);2,函数uinttlc_read(ucharport)不改动,在调用的时候控制循环多次(一般为3次),对这一次选择的通道进行多次转换,然后在取值。上面的两种方法都可以保证本次取得的值就是本次选择的通道的AD转换值。

有很多人的程序都是使用了上面的第一种方法,我自己实现的是第二种方法,这两种方法的本质其实是一样的,都是用多次采样的方法来保证输出结果和选择通道是相对应的。

上面我根据自己的理解,对tlc2543进行了大概了介绍,着重介绍了一些容易出错,较难理解的地方。我也在网上查了一些资料,但一般都是只有程序,而没有较详细的说明,如果自己再慢慢琢磨的话,就比较浪费时间了,而且比较容易出错,而上面的值得注意的地方也比较难以理解。我身边也有同学在网上找来了程序就直接用,而不对它进行细心的分析研究,这样的话肯定是出错的概率是比较高的,而且也不能真正的掌握它的使用方法。所以我就把我自己的理解写了出来,希望对你有所帮助。

当然更详细,更权威的资料当然是对应的数据手册了,所以要经常查阅,并且以它为准。

好了下面是我写的程序,比较好用,我一直都在用,没有发现有什么大的问题,实现了控制多通道的转换。

单片机使用的是TI的msp430g2553

注释的也比较详细:

#include

#include"ser_12864.h"

#defineCLR_CLOCKP2OUT&=~BIT0;//时钟输入

#defineSET_CLOCKP2OUT|=BIT0;

#defineCLR_INP2OUT&=~BIT1;//数据输入

#defineSET_INP2OUT|=BIT1;

#defineCLR_CSP2OUT&=~BIT2;//片选

#defineSET_CSP2OUT|=BIT2;

#defineDATA_OUTP2IN&BIT3;//数据输出

#defineEOCP1IN&BIT7;//转换结束端

//这是针对tlc2543进行IO口配置的函数

voidtlc_init()//tlc初始化

{

P2DIR|=BIT0+BIT1+BIT2;

P2DIR&=~BIT3;

P1DIR&=~BIT7;

}

//名称:read2543

//功能:TLC2543驱动模块

//输入参数:port通道号

//输出参数:ad转换值

uinttlc_read(ucharport)

{

uintad=0;

uchari=0;

CLR_CLOCK;

CLR_CS;

port<<=4;//左移4位

for(i=0;i<12;i++)

{

if(P2IN&BIT3)

ad|=0x01;

if(port&0x80)

{

SET_IN;

}

elseif((port&0x80)==0)

{

CLR_IN;

}

SET_CLOCK;

//delay(3);

CLR_CLOCK;

//delay(3);

port<<=1;

ad<<=1;

}

SET_CS;

//while(P1IN&BIT7);//等待转换结束此句话可以不要

while((P1IN&BIT7)==0);//等待转换结束此句话可以不要

ad>>=1;

return(ad);

}

voidmain(void)

{

uintad_data_0=0;//tlc的采样值

uintad_data_5=0;

uchari=0;

unsignedchars1[]={"Tlc2543"};

unsignedchars2[]={"ch_6:"};

unsignedchars3[]={"ch_8:"};

//unsignedchars4[]={"2012-06-24-78-55"};

WDTCTL=WDTPW+WDTHOLD;//停止看门狗定时器

BCSCTL1=CALBC1_12MHZ;//设定cpu时钟DCO频率为12MHz

DCOCTL=CALDCO_12MHZ;

P2DIR|=BIT4+BIT5;//液晶的两条线

init_lcd();

tlc_init();

wr_string(0,0,s1);

P1DIR|=BIT6;//调试指示灯

for(;;)

{

ad_data_0=0;

ad_data_5=0;

P1OUT^=BIT6;

for(i=0;i<3;i++)

{

ad_data_0=tlc_read(0x06);//选择通道6

delay_ms(1);//适当延迟,等待转换必须的

}

wr_string(0,1,s2);

wr_int(3,1,ad_data_0);

for(i=0;i<3;i++)

{

ad_data_5=tlc_read(0x08);//选择通道8

delay_ms(1);

}

wr_string(0,2,s3);

wr_int(4,2,ad_data_5);

//ad_data=tlc_read(7);

//wr_int(0,3,ad_data);

delay_ms(500);

}

}

//本程序是用msp430控制12位的串行ADltc2543

//目前可以实现控制通道0进行转换,读取转换值,检验正确,

//但是控制多个通道一次进行转换,输出结果,还没有实现,需要进一步了解ltc2543,改进程序

//for(;;)

//{

//ad_data_0=0;

//ad_data_5=0;

//P1OUT^=BIT6;

//ad_data_0=tlc_read(0x06);//选择通道6

//wr_string(0,1,s2);

//wr_int(3,1,ad_data_0);

//

////delay_ms(100);

//

//ad_data_5=tlc_read(0x08);//选择通道8

//wr_string(0,2,s3);

//wr_int(4,2,ad_data_5);

////ad_data=tlc_read(7);

////wr_int(0,3,ad_data);

//

//delay_ms(400);

//

//}

//如上面的一段程序,我本来是想让tlc分别采用通道6和通道8,然后再读出采样值,但是实验的结果是:我读出的结果通道6和通道8的刚好相反

//目前还没有完全清楚原因。我想有可能是采样时序的问题没有搞清楚,有可能是第一次送入通道6的地址,让通道6进行转换,但是得等到下一次才能读出

//结果。而这一次读的结果是上一次送入的地址转换的结果。这样的话就是这一次转换的结果,下一次才能读出,而这一次读出的结果是上一次

//转换的值,其对应的转换通道也是上一次确定的

//如上面源程序中,采用这种方法可以解决这个问题,因为输入一次新的地址后,让tlc多转换几次,这样就可以确保是本次的结果和本次的通道

//相对应了,一般循环3次以上就可以了



评论


技术专区

关闭