前 言 DS18B2普遍都是和单片机配合使用,很少有关于DSP与DS18B20的连接的接口报道,所以此文详细介绍了TMS320LF2407与 DS18B20的连接方法,并且很详细的介绍了如何用C语言完成精确的软件延时,从而完成DS18B20与TMS320LF2407之间的基于单线总线协议的数据通讯。
1 DS18B20的时序
1. 1 复位时序
复位使用DS18B20时,首先需将其复位,然后才能执行其它命令。复位时,主机将数据线拉为低电平并保持480us~960us,然后释放数据线,再由上拉电阻将数据线拉高15~60us,等待DS18B20发出存在脉冲,存在脉冲有效时间为60~240us,这样,就完成了复位操作。
1.2 写时序
在主机对DS18B20写数据时,先将数据线置为高电平,再变为低电平,该低电平应大于1us。在数据线变为低电平后15us内,根据写“1”或写“0” 使数据线变高或继续为低。DS18B20将在数据线变成低电平后15us~60us内对数据线进行采样。要求写入DS18B20的数据持续时间应大于 60us而小于120us,两次写数据之间的时间间隔应大于1us。
1.3 读时序
读时隙当主机从DS18B20读数据时,主机先将数据线置为高电平,再变为低电平,该低电平应大于1us,然后释放数据线,使其变为高电平。DS18B20在数据线从高电平变为低电平的15us内将数据送到数据线上。主机可在15us后读取数据线.。
2 TMS320LF2407与DS18B20的连接
DS18B20有三个引脚。其与TMS320LF2407A的接线图如下。VDD管脚接5V电压给传感器供电。DQ管脚为数据线,与 TMS320LF2407A的IOPA6连接的同时,还要接一个4.7K的上拉电阻,并接到5V的电源上,使数据线在空闲状态下能自动上拉为高电平。 GND管脚接地。
3 软件设计
3.1 精确的软件定时的实现
众所周知,TMS320LF2407的内核属于C2000系列的处理器,处理速度达到30MIPs,也就是每条指令所花的时间理论上只有33ns。但是实际情况是,由于DSP外部电路的数据处理速度和数据调用等因素,往往处理速度达不到这个数量级。那怎样测出每条指令的处理时间从而计算出软件延时程序的精确时间呢?计算方法如下:
1、延时程序的C语言代码为:
for(loopindex=0;loopindex
其中loopindex 为unsigned int,无符号整形数值, N为常量,根据所要求的延时时间,计算得出。具体算法在下面给出。
2、这个for语句在CCS中的编译器编译后所产生的汇编语言为:
LACL #0h
SACL *, 0
LACL *
SUB N(计算得到的循环次数)
BCND 转移的地址,GEQ
LACC *, 0
ADD #1h
SACL *, 0
LACL *
SUB N(计算得到的循环次数)
BCND 转移的地址,LT
这些汇编语句所占用的时间可以计算成公式:DELAY=(9N+4)*单个指令周期。
3、测试出一个指令周期
系统所用晶振为20M,倍频以后的时钟频率为40M,定时器1的分频为1,也就是说定时器的计时周期为25ns。开启定时器,单步运行上面的汇编语句,看定时器每次运行后所增加的数值。测试得到,在每次单步运行占一个指令周期的汇编语句后,定时器的数值增加10。也就是说,每个单指令周期的指令占用的时间为:25ns*10=250ns,也就是0.25us。
4、延时程序的最终计算公式为:
DELAY =(9n+4)*0.25us。
由公式可以看出,当n=0时,DELAY=1us,当n=65535时,DELAY= 150ms。
3.2 主要程序
由于**篇幅的关系,这里只给出复位程序、读字节程序和整个读温度的主程序,写命令字的程序可以根据上面所述的时序自行编写。
#define nop() {asm( nop );}
#define DATA_PORT PADATDIR
#define DATA_MODE 0x0040
#define DATA_OUT 0x4000
#define DATA_BIT 0x0040
#define PIN_HIGH() {PADATDIR=PADATDIR|DATA_OUT|DATA_BIT;}
#define PIN_LOW() {DATA_PORT=(PADATDIR|DATA_OUT)&(~DATA_BIT);}
#define PIN_LEAVE() {DATA_PORT=DATA_PORT&(~DATA_OUT)|DATA_BIT;}
/* 传感器复位程序 */
unchar reset(void)
{ unchar retval;
unint loopindex="0";
PIN_HIGH();
nop();nop();nop();nop(); /* 延时1us*/
PIN_LOW();
for(loopindex=0;loopindex<213;loopindex++){;} /*置总线为低电平并保持至少480us */
PIN_HIGH();
for(loopindex=0;loopindex<26;loopindex++){;} /*等电阻拉高总线并保持15-60us */
PIN_LEAVE(); /*接受应答信号*/
nop();
if((DATA_PORT & DATA_BIT) == 0x0000)
{ retval = 0; }
else
{ retval = 1; }
PIN_HIGH();
for(loopindex=0;loopindex<106;loopindex++){;} /*延时60-240us */
return(retval); /*返回应答信号 */
}
/* 从传感器中读一个字节 */
void read_byte(unchar *ReadByte)
{
int i;
unchar temp="0";
unint loopindex="0";
PIN_HIGH();
for(i=0;i<8;i++)
{
temp="temp">>1;
PIN_LOW();
nop();nop();nop();nop(); /*延时2us */
nop();nop();nop();nop();
PIN_HIGH();
for(loopindex=0;loopindex<6;loopindex++){;} /* 延时14us */
PIN_LEAVE();
nop();
if((DATA_PORT & DATA_BIT) == 0x0000)
{ temp="temp" & 0x7F; }
else
{ temp="temp" | 0x80; }
PIN_HIGH();
for(loopindex=0;loopindex<26;loopindex++){;} /* 延时60us */
}
*ReadByte=temp;
return;
}
/* 将读得的温度转化为十进制 */
float transform(unchar *T)
{
unchar temp="0";
float temprature="0";
temp=temp|(*(T+1)<<8);
temp=temp|*T;
if((temp&0x0F800)==0x0F800)
{ temprature="0-"((~temp)+1)*0.0625; }
else
{ temprature="temp"*0.0625; }
return(temprature);
}
/* 读取温度主函数,返回十进制温度数 */
float read_temp()
{
Unchar buff[2];
float temprature="0";
unint loopindex="0";
while (reset()==1){}; /* 复位等待从机应答 */
write_byte(0xCC); /* 忽略ROM匹配 */
write_byte(0x44); /* 发送温度转化命令 */
for(loopindex=0;loopindex<65535;loopindex++){;} /* 延时300ms,等待数模转换 */
for(loopindex=0;loopindex<65535;loopindex++){;}
while(reset()==1){}; /* 再次复位,等待从机应答 */
write_byte(0xCC); /* 忽略ROM匹配 */
write_byte(0xBE); /* 发送读温度命令 */
read_byte(buff); /* 读出温度低8位 */
read_byte(buff+1); /* 读出温度高8位 */
temprature="transform"(buff);
PIN_HIGH(); /* 释放总线 */
return(temprature);
}
4 结束语
DS18B20是一款非常优秀的单总线数字式传感器。硬件设计简单,运行可靠。通过分析C语言编译后的汇编语言可以很明确的计算出软件延时的时间,从而满足单线总线通讯的时序要求,从而可以出色的完成DSP与DS18B20通讯的软件设计。
5 本文创新点有两个:
1、通过C编译器编译出来的相应的C语言的延时程序,从而得到其对应的汇编语言,再通过定时器计时,能够知道单指令周期的时间,从而能够精确的计算出软件延时程序的延时时间。
2、通常DS18B20都是与单片机配合使用的,而本文则详细的介绍了DS18B20与DSP的结合使用方法,其区别主要是在端口的操作上和延时的控制上。
|