📄 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 + -