//程序功能:完成msp430f2131读写ds1991
//芯片配置: msp430f2131的MCLK来至DCO,配置成1M
#include "msp430x20x1.h" //头文件
//宏定义一些常用的代码,写成函数形式,方便阅读理解。
#define TM_OUT(level) P2OUT = ((unsigned int)level) ? (P2IN|BIT4) : (P2IN&~BIT4)
#define TM_DIR(level) P2DIR = ((unsigned int)level) ? (P2DIR|BIT4) : (P2DIR&~BIT4)
#define TM_IN (P2IN&BIT4)
/******************************
函数 wrbyte()
功能:DS1991写数据
*byte1为数据指针,
num表示写的数据个数
********************************/
void wrbyte(unsigned char *byte1,unsigned char num)
{
unsigned char i=0,j=0,k=0,byte=0,temp=0;
TM_DIR(1);
for(k=0;k<num;k++)
{
byte=*(byte1+k);
for(j=0;j<8;j++)
{
temp=(byte>>j)&0x01; //14us
TM_OUT(0); //1us
i=0; //2us //总线值低电平tLow1=1us~15us
TM_OUT(temp);
//TM=temp; //4us//写周期TH=60us-tLow1, 对方在检测到总线=0开始15us后,将总线采样写入
for(i=0;i<0x12;i++); //91us
TM_OUT(1);
for(i=0;i<1;i++); //5us
}
}
}
/******************************
函数:rbyte()
功能:DS1991读数据
num表示读的数据个数
函数返回指针
********************************/
unsigned char *rbyte(unsigned char num)
{
unsigned char i,j,k,byte1=0,byte2=0;
unsigned char *pp,temp[48]={0};
for(k=0;k<num;k++)
{
for(j=0;j<8;j++)
{
TM_OUT(0); //总线值低电平tSu<1us
i=0;
i=1; //2us
TM_OUT(1); //等待总线数据到达tLOW=1us~15us
TM_DIR(0);
//采样周期,对方在检测到总线=0开始15us后,将数据放在总线上,持续时间0~45us
//然后释放总线,总时间共60us-TL.
if(TM_IN) byte2|=0x01;
byte2=byte2<<7;
byte1=byte1>>1;
byte1=byte1|byte2;
byte2=0;
for(i=0;i<0x8;i++); //40us
TM_DIR(1);
TM_OUT(1);
for(i=0;i<1;i++); //5us
}
temp[k]=byte1;
}
pp=temp;
return pp;
}
/******************************
函数:rext()
功能:测试DS1991是否在线
DS1991在线则返回1,
否则返回0
********************************/
unsigned char rest(void)
{
unsigned char i=0;
unsigned char k=0;
TM_DIR(1); //5u
TM_OUT(0); //9u
for(i=0;i<0x61;i++); //3+x*5 //492us //发复位低脉冲tRSTL>80us
TM_OUT(1); //9u //释放总线,等待上拉电阻将总线恢复高电平tPDH=5us~60us
TM_DIR(0); //5u
i=0;
do //等待对方返回低脉冲, tPDL=60us~240us
{
if(TM_IN==0)
{
k=1;
for(i=0;i<0x09;i++); //52us
i=0;
do
{
if(TM_IN==1) //等待对方恢复高电平
break;
}while(i++<0x20);
TM_DIR(1);
TM_OUT(1);
for(i=0;i<0x61;i++); //482us
break;
}
}
while(i++<0x35); //530us
TM_DIR(1);
TM_OUT(1);
for(i=0;i<0x5;i++); //27us
return k;
}
unsigned char *rdsubkey(unsigned char quNO)
{
unsigned char temp[56]={0};
unsigned char i=0,*pp;
i=rest();
temp[0]=0xcc;
wrbyte(temp,1);
i=(quNO<<6);
temp[0]=0x66;temp[1]=(0x10+i);temp[2]=(0xff-temp[1]); // Read
wrbyte(temp,3);
pp=rbyte(0x8); //读取ID
for(i=0;i<8;i++)
temp=*(pp+i);
wrbyte(oldpw,8);//写密码
pp=rbyte(0x30); //读取数据
for(i=0;i<0x30;i++)
temp[i+0x08]=*(pp+i);
i=rest();
pp=temp;
return pp;
}
//注意考虑操作的可靠性
void TM_pro(void)
{
unsigned int i=0;
unsigned char j=0,*pp,temp[56]={0};
_DINT(); //关中断
for(;;)
{
i=rest(); //测试TM卡是否在线,i=1表示在线,
//在线则跳出循环
if(i==1){break;}
if(j++>0x0A){break;} //不在线时,多测试几次,这里为10次
for(i=0;i<1000;i++);
}
if(i==1) //TM卡在线
{
// 读取8 位家族码48 位唯一的序列号和8 位CRC 校验码
temp[0]=0x33;
wrbyte(temp,1);
pp=rbyte(0x8);
for(i=0;i<8;i++)
temp=*(pp+i);
if(temp[0]==0x02) //ds1991家族码为02
{
pp=rdsubkey(0x10); //00,01,10
for(i=0;i<56;i++)
temp=*(pp+i);
switch(temp[8])
{}
}
else;//家族码不正确
}
else ; //卡不在线
TM_DIR(0);
_EINT();
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
BCSCTL1=CALBC1_1MHZ;
DCOCTL=CALDCO_1MHZ;
for (;;)
{
if(tmflag==1)
{
P2IE |= 0x00; // P2.4 interrupt enabled
P2IES |= 0x00;
tmflag=0;
//TM_pro();
// 读取8 位家族码48 位唯一的序列号和8 位CRC 校验码
temp[0]=0x33;
wrbyte(temp,1);
pp=rbyte(0x8);
for(i=0;i<8;i++)
temp=*(pp+i);
if(temp[0]==0x02) //ds1991家族码为02
{
i=rest();
temp[0]=0xcc; //Skip ROM
wrbyte(temp,1);
temp[0]=0x96;temp[1]=0xc0;temp[2]=(0xff-temp[1]); //Write Scratchpad [96H]
wrbyte(temp,3);
temp[0]=0x34;
wrbyte(temp,1);
// pp=rbyte(0x8);
// for(i=0;i<8;i++)
// temp=*(pp+i);
// wrbyte(temp,8);
// wrbyte(id,8);
// wrbyte(pw,8);
i=rest();
i=rest();
temp[0]=0xcc;
wrbyte(temp,1);
temp[0]=0x69;temp[1]=0xc0;temp[2]=(0xff-temp[1]); // Read Scratchpad [69H]
wrbyte(temp,3);
pp=rbyte(0x2);
for(i=0;i<2;i++)
temp=*(pp+i);
i=rest();
i=9;
}
}
TM_DIR(0);
P2IE |= 0x10; // P2.4 interrupt enabled
P2IES |= 0x10; // P2.4 Hi/lo edge
P2IFG &= ~0x10;
_EINT();
}
}