⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds1631.c

📁 ds1631温度传感器程序
💻 C
字号:

#include <reg52.h>		   	// 引用标准库的头文件
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int
#define READ  1
#define WRITE 0

sbit SDA = P1^4;			// 串行数据
sbit SCL = P1^6;			// 串行时钟

uchar idata SLAdd;    		// 从器件地址
uchar idata SLAdd1;
uchar idata sbuf[8];   		// 数据发送缓冲区
uchar idata rbuf[8];   		// 数据接收缓冲区
bit   bdata NACK;    		// 器件坏或错误标志位
bit   bdata nackFlag;   	// 非应答标志位
bit   ackFlag;                   //应答标志
float temp_c;                // temperature in deg. C
float temp_f;                // temperature in deg. F
unsigned char MSB;            // temp byte MSB
unsigned char LSB;            // temp byte LSB
unsigned char Config;

/* 延时约5微秒,对于12M时钟 */
void delay5us()
{
	uint i;
	for (i=0;i<5;i++)
		_nop_();
}
/*延时约3微秒,对12M时钟*/
void delay3us()
{
    uint i;
	for(i=0;i<3;i++)
	    _nop_();
}

/* 起始条件子函数:SCL为高电平,SDA产生一个下降沿*/
void start(void)
{
	SDA = 1;			// 启动I2C总线
	SCL = 1;
	delay5us();
	SDA = 0;            //SCL为高,SDA出现下降沿后起始条件成立
	delay5us();
	SCL = 0;
	delay3us();
}

/* 停止条件子函数:SCL为高电平,SDA产生一个上升沿 */
void stop(void)
{
	SDA = 0;			// 停止I2C总线数据传送
	SCL = 1;
	delay5us();
	SDA = 1;            //SCL为高,SDA出现上升沿后起停止条件成立
	delay5us();
	SCL = 0;
	delay3us();
}

/* 主机发送ACK */
void ack(void)
{
	SDA = 0;			// 主机发送应答位
	SCL = 1;
	delay5us();
	SDA = 1;
	SCL = 0;
	delay3us();
}

/* 发送非应答子函数 */
void n_ack(void)
{
	SDA = 1;			// 发送非应答位
	SCL = 1;
	delay5us();
	SDA = 0;
	SCL = 0;
	delay3us();
}

/* 应答位检查子函数 */
void checkack(void)
{

	SDA = 1;    		// 应答位检查(将p1.4设置成输入,必须先向端口写1)
        _nop_();
        _nop_();
	SCL = 1;
	_nop_();
	_nop_();
        _nop_();

	if(SDA == 1)    	// 若SDA=1表明非应答,置位非应答标志F0(F0是程序状态字PSW.5用户可以根据需要置位或者复位)
	  ackFlag = 0;
	else ackFlag = 1;      //SDA拉低应答

	SCL = 0;
	//delay3us();
}

void I2CBitDly(void)                            // wait approximately 4.7uS
{						// tune to xtal. This works at 11.0592MHz
	unsigned int time_end = 10;
	unsigned int index;

	for (index = 0; index < time_end; index++);
	return;
}

/* 发送一个字节数据子函数 */
void sendbyte(uchar idata ch)
{
	uchar idata n = 8;
	uchar idata temp;
	temp = ch;  //8f  1000 1111
	while(n--)
	{
		if((temp&0x80) == 0x80)    // 若要temp最高位为1则发送1;否则就发送0
		{
			SDA = 1;       //发送1
			SCL = 1;
			delay5us();
			SDA = 0;
			SCL = 0;
		}
		else
		{
			SDA = 0;       // 发送0
			SCL = 1;
			delay5us();
			SCL = 0;
		}
		temp = temp<<1;    // 数据左移一位
	}

}


/* 发送n字节数据子程序
void sendnbyte(uchar idata *sla, uchar n)
{
	uchar idata *p;
	start();				// 发送启动信号
	sendbyte(sla);    		// 发送从器件地址字节,控制字
	checkack();    			// 检查应答位
        if(ackFlag == 0)            // 如果非应答
	{
		NACK = 1;
		return;    		    // 若非应答表明器件错误或已坏,置错误标志位NACK
	}
	p = sbuf;               //发送命令字,数据字节

	while(n--)
	{
		sendbyte(p);
		checkack();    	    // 检查应答位
		if (ackFlag == 0)
		{
			NACK=1;
			return;    	    // 若非应答表明器件错误或已坏,置错误标志位NACK
		}
		p++;
	}
//	stop();    			    // 全部发完则停止
}*/



/* 接收一字节子程序 */
uchar recbyte()
{
	uchar idata n=8;               // 从SDA线上读取一位数据字节,共8位
	uchar idata temp = 0;
	while(n--)
	{
		SDA = 1;
		SCL = 1;
		temp = temp<<1;          // 左移一位
		if(SDA == 1)
			temp = temp|0x01;    // 若接收到的数为1,则temp最后一位置1
		else
			temp = temp&0xfe;    // 否则temp最后一位置0
		SCL=0;                   //???
	}
	return(temp);
}



void I2CSCLHigh(void)    // Set SCL high, and wait for it to go high
{
	register int err;
	SCL = 1;
	while (! SCL)
	{
	  err++;
		if (!err)
		{
		return;
		}
	}
}


void I2CSendByte(unsigned char bt)
{
	register unsigned char i;
	for (i=0; i<8; i++)
	{
		if (bt & 0x80) SDA = 1; // Send each bit, MSB first changed 0x80 to 0x01
		else SDA = 0;
		I2CSCLHigh();
		I2CBitDly();
		SCL = 0;
		I2CBitDly();
		bt = bt << 1;
	}
        checkack();
        if(ackFlag == 0)            // 如果非应答
	{
		NACK = 1;
		return;            // 若非应答表明器件错误或已坏,置错误标志位NACK
	}

}


void I2CSendAddr(unsigned char addr, unsigned char rd)
{
	start();
	I2CSendByte(addr+rd); // send address byte
}


unsigned char I2CGetByte(unsigned char lastone) // last one == 1 for last byte; 0 for any other byte
{
	register unsigned char i, res;
	res = 0;
	for (i=0;i<8;i++) // Each bit at a time, MSB first
	{
		I2CSCLHigh();
		I2CBitDly();
		res = res<<1;
		if (SDA) res++;
		SCL = 0;
		I2CBitDly();
	}
	SDA = lastone;  // Send ACK according to 'lastone'
	I2CSCLHigh();
	I2CBitDly();
	SCL = 0;
	SDA = 1;       // end transmission
	SCL = 1;
	I2CBitDly();
	return(res);
}

void WriteConfig(unsigned char Address, unsigned char Data) //Pass Device Address such as 0x90h or 0x92h
{
                                                    // Routine to write data to Config Register
     I2CSendAddr(Address,WRITE); // send START and control byte
     I2CSendByte (0xAC); // send Access Config command byte
     I2CSendByte (Data); // send data
     stop(); // send STOP
}


void GetConfig(unsigned char Address) //Pass an Address such as 0x90h or 0x92h
{
                                      // Routine to read data from Config Register
     I2CSendAddr(Address,WRITE); // send START and control byte
     I2CSendByte(0xAC); // send Access Config command byte
     I2CSendAddr(Address,READ); // send repeat START and control byte
     Config = I2CGetByte(1); // read Config Register
     stop(); // send STOP
}
/*******************************************************


void recnbyte()//uchar sla, uchar no)
{
	uchar i,sla=0x90;

	start();			// 发送启动信号
	sendbyte(sla);

	checkack();			// 检查应答位
	if(ackFlag == 0)
	{
		NACK = 1;
		return;
	}


        start();
        sendbyte(sla+1);          // 发送控制字  读DS1631信息
        checkack();
        if(ackFlag == 0)
	{
		NACK = 1;
		return;
	}
//	p = rbuf;			// 接收字节存放在rbuf中,指针P指向rbuf
	for(i=0;i<2;i++)
	{
		rbuf[i] = recbyte();

		ack();    		// 收到一个字节后,MCU主机发送一个应答位

	}
	n_ack();    		// 收到最后一个字节后发送一个非应答位
	stop();
}
********************************************************/


/* 主函数,模拟实现I2C总线的数据收发 */
void main(void)
{

        unsigned char Address = 0x90;
      WriteConfig(0x90,0x0e);
      GetConfig(0x90);

  while(1)
  {
        I2CSendAddr(Address,WRITE); // send START and control byte
	I2CSendByte(0x51); // send Start Convert Tcommand byte
	stop(); // send STOP
	I2CBitDly(); // wait

	I2CSendAddr(Address,WRITE); // send START and control byte
	I2CSendByte(0xAA); // send Read Temperature command byte

	I2CSendAddr(Address,READ); // send repeat START and control byte
	MSB = I2CGetByte(0); // read Temp MSB
	LSB = I2CGetByte(1); // read Temp LSB
	stop(); // send STOP

	if(MSB>=0x80) //if sign bit is set, then temp is negative
	temp_c = (float)((MSB<<8 | LSB) - 65536) * 0.0625;
	else
	temp_c = (float)((MSB<<8|LSB) * 0.00390625);
        /*
	temp_f =( temp_c * 9/5) + 32;
*/

  }

}





⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -