TMP101 I2C溫度傳感器的C51實(shí)現(xiàn)
前段時(shí)間 STM32 的I2C應(yīng)用搞的一塌糊涂,自我感覺(jué)十分不爽。又找出了一片 德州儀器 的12位 I2C 接口的溫度傳感器 TMP101來(lái) 練練手。先在SMT32接線時(shí)連電源都接錯(cuò)了,上拉也沒(méi)接。算了先在51 上跑跑,不久一定要在STM32跑起來(lái)。
#include
#include
#define OP_WRITE 0x92// 器件地址以及寫(xiě)入操作 浮空了地址引腳
#define OP_READ 0x93// 器件地址以及讀取操作
sbit SDA=P1^2;//定義總線連接端口
sbit SCL=P1^1;
sbit WP=P1^0;//No connect here 一個(gè)標(biāo)記
float tmp;char a[6]; char num;
unsigned char Number[4]={0xf9,0xb0,0x92,0x80};// 溫度碼值
unsigned char const dofly[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xc6};// 顯示段碼值0123456789C
unsigned char code seg[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//分別對(duì)應(yīng)相應(yīng)的數(shù)碼管點(diǎn)亮
void mDelay(unsigned int j)//A normal delay
{
unsigned int i;
for(;j>0;j--)
{
for(i=0;i<125;i++);
}
}
/**********************************************************
延時(shí)子程序 (4.34us)
**********************************************************/
void delayNOP(void)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
/**********************************************************
延時(shí)子程序
**********************************************************/
void delayms(unsigned int ms)
{
unsigned char k;
while (ms--)
{
for (k = 0; k < 114; k++)
;
}
}
/**********************************************************
啟動(dòng)子程序
在 SCL 高電平期間 SDA 發(fā)生負(fù)跳變
**********************************************************/
void iic_start()
{
SDA = 1;
SCL = 1;
delayNOP();
SDA = 0;
delayNOP();
SCL = 0;
}
/**********************************************************
停止子函數(shù)
在 SCL 高電平期間 SDA 發(fā)生正跳變
**********************************************************/
void iic_stop()
{
SDA = 0;
SCL = 1;
delayNOP();
SDA = 1;
delayNOP();
SCL = 0;
}
/**********************************************************
發(fā)送應(yīng)答位子函數(shù)
在 SDA 低電平期間 SCL 發(fā)生一個(gè)正脈沖
**********************************************************/
void iic_ack()
{
SDA = 0;
SCL = 1;
delayNOP();
SCL = 0;
SDA = 1;
}
/**********************************************************
發(fā)送非應(yīng)答位子函數(shù)
在 SDA 高電平期間 SCL 發(fā)生一個(gè)正脈沖
**********************************************************/
/*void iic_noack()
{
SDA = 1;
SCL = 1;
delayNOP();
SCL = 0;
SDA = 0;
}*/
/**********************************************************
應(yīng)答位檢測(cè)子函數(shù) 這里沒(méi)用
**********************************************************/
/*bit iic_testack()
{
bit ack_bit;
SDA = 1; //置SDA為輸入方式
SCL = 1;
delayNOP();
ack_bit = SDA;
SCL = 0;
delayNOP();
return ack_bit; //返回TMP101應(yīng)答位
}*/
/**********************************************************
讀一個(gè)字節(jié)子程序
從TMP101讀數(shù)據(jù)到MCU
**********************************************************/
unsigned char readbyte()
{
unsigned char i, read_data;
SDA = 1;//置SDA為輸入方式
for (i = 0; i < 8; i++)
{
SCL = 1;//使SDA數(shù)據(jù)有效
read_data <<= 1;//調(diào)整接收位
if (SDA)
//讀SDA
read_data++;
SCL = 0;//繼續(xù)接收數(shù)據(jù)
}
return (read_data);
}
/**********************************************************
發(fā)送一個(gè)字節(jié)子程序
從MCU移出數(shù)據(jù)到TMP101
**********************************************************/
void writebyte(unsigned char write_data)
{
unsigned char i;
for (i = 0; i < 8; i++)
// 循環(huán)移入8個(gè)位
{
SDA = (bit)(write_data &0x80);//將發(fā)送位送入SDA數(shù)據(jù)線
SCL = 1;
delayNOP();
SCL = 0;//SDA數(shù)據(jù)線上數(shù)據(jù)變化
write_data <<= 1;//調(diào)整發(fā)送位
}
}
/**********************************************************
init TMP101
**********************************************************/
void init()
{
iic_start();
writebyte(OP_WRITE);//寫(xiě)0x92 SLAVE ADDRESS
iic_ack();
//while(iic_testack());
writebyte(0x01);//寫(xiě)配置命令Pointer Register Type
iic_ack();
//while(iic_testack());
writebyte(0xfe);//寫(xiě)數(shù)據(jù) Configuration Register
iic_ack();
//while(iic_testack());
delayms(1);
iic_stop();//發(fā)送結(jié)束
}
/**********************************************************
讀出12位溫度
**********************************************************/
void RdFromROM()
{
iic_start();
writebyte(OP_WRITE);//寫(xiě)0x92
iic_ack();
//while(iic_testack());
writebyte(0x00);//寫(xiě)讀取地址
iic_ack();
//while(iic_testack());
iic_start();
writebyte(OP_READ);//寫(xiě)0x93
iic_ack();
Number[0] = readbyte();//讀出數(shù)據(jù)寫(xiě)
iic_ack();//發(fā)送應(yīng)答位
delayms(1);
Number[1] = readbyte();//讀出數(shù)據(jù)
iic_ack();//發(fā)送應(yīng)答位 按理應(yīng)該發(fā)送 非應(yīng)答的 但是TMP101 的時(shí)序圖是應(yīng)答
delayms(1);
//iic_noack(); //發(fā)送非應(yīng)答位 非應(yīng)答也能調(diào)通的
iic_stop();//發(fā)送結(jié)束
}
void maketemp()//處理溫度
{
long int temp=0;
temp=Number[0];
temp<<=4;
temp=temp|((Number[1]&0xf0)>>4);
tmp=(temp/16.0);
a[0]=(char)tmp/10;
a[1]=(char)tmp%10;
a[2]=(char)((int)(tmp*10)%10);
a[3]=(char)((int)(tmp*100)%10);
a[4]=(char)((int)(tmp*1000)%10);
a[5]=10;
}
void main()
{
unsigned char i=0;
WP=1;
TMOD=0x01;//定時(shí)器設(shè)置
TH0=0x4c;
TL0=0x00;
IE=0x82;
TR0=1;
init();//初始化
mDelay(400);
RdFromROM();//讀溫度
maketemp();//轉(zhuǎn)換
WP=0;
while(1)
{
for (i=0;i<=5;i++)//數(shù)碼管公陽(yáng)掃描
{
P2=seg[i];P0=dofly[a[i]];mDelay(2);
P2=0xbf;P0=0X7F;mDelay(1);//小數(shù)點(diǎn)
}
}
}
void tim(void) interrupt 1 using 1//中斷,用于溫度檢測(cè)間隔
{
IE=0x00;//關(guān)中斷
num++;
if (num==5)
{
num=0;//12位的溫度轉(zhuǎn)換典型時(shí)間為320ms 這個(gè)中斷為50ms 11.0592MHz
RdFromROM();//讀溫度
maketemp();//轉(zhuǎn)換
}
TH0=0x4c;//定時(shí)器重裝值
TL0=0x00;
IE=0x82;//開(kāi)中斷
}