#include <reg52.h>
#include <INTRINS.H>
#include <stdio.h>
/* ***************************************************** */
// 起別名定義
/* ***************************************************** */
typedef unsigned char uChar8;
typedef unsigned int uInt16;
typedef enum{FALSE,TRUE} BOOL;
/* ***************************************************** */
// 宏定義
/* ***************************************************** */
#define LM75ADevIDAddr 0x90
#define IIC_WRITE 0x00
#define IIC_READ 0x01
/* ***************************************************** */
// 位定義
/* ***************************************************** */
sbit SCL = P1^1;
sbit SDA = P1^0;
sbit fuhao=P2^0;
sbit shiwei=P2^1;
sbit gewei=P2^2;
sbit xiaoshu=P2^3;
/* ***************************************************** */
// 全局變量定義
/* ***************************************************** */
bit p_bH0L_Flag; // 溫度"0"上、下標志位
float p_fLM75ATemp; // 溫度值
/* ***************************************************** */
// 數組定義
/* ***************************************************** */
//此表為 LED 的字模, 共陰數碼管 0-9 帶小數點
uChar8 code Dis_Dot[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
//此表為 LED 的字模, 共陰數碼管 0-9 不帶小數點
uChar8 code Dis_NoDot[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//此表為“0上”和“0下”顯示字模,“0上”用“P”、“0下”用“F”表示。
uChar8 code Dis_UP[2] = {0xc6,0x8e};
/* ***************************************************** */
// 函數名稱:Delay5US()
// 函數功能:微秒延時
// 入口參數:延時微秒數(ValUS)
// 出口參數:無
/* ***************************************************** */
void Delay5US(void)
{
_nop_();_nop_();_nop_();_nop_();
}
/* ***************************************************** */
// 函數名稱:DelayMS()
// 函數功能:毫秒延時
// 入口參數:延時毫秒數(ValMS)
// 出口參數:無
/* ***************************************************** */
void DelayMS(uInt16 ValMS)
{
uInt16 uiVal,ujVal;
for(uiVal = 0; uiVal < ValMS; uiVal++)
for(ujVal = 0; ujVal < 120; ujVal++);
}
/* ***************************************************** */
// 函數名稱:LedDisplay()
// 函數功能:數碼管顯示
// 入口參數:待顯示數字(TempVal)
// 出口參數:無
/* ***************************************************** */
void LedDisplay(long int TempVal)
{
uChar8 ShiInt,GeInt,BaiDec;
// BaiInt = TempVal / 100000;
// if(BaiInt == 0) // 意圖是讓最高位“0”別顯示
// BaiInt = 10;
ShiInt = TempVal / 10000 ;
GeInt = TempVal / 1000 % 10;
BaiDec = TempVal / 100 % 10;
fuhao=1;
shiwei=0;
gewei=0;
xiaoshu=0;
P0 = Dis_UP[p_bH0L_Flag];
DelayMS(2);
fuhao=0;
shiwei=1;
gewei=0;
xiaoshu=0;
P0 = Dis_NoDot[ShiInt];
DelayMS(2);
fuhao=0;
shiwei=0;
gewei=1;
xiaoshu=0;
P0 = Dis_Dot[GeInt];
DelayMS(2);
fuhao=0;
shiwei=0;
gewei=0;
xiaoshu=1;
P0 = Dis_NoDot[BaiDec];
DelayMS(2);
}
/* ***************************************************** */
// 函數名稱:IIC_Start()
// 函數功能:IIC起動
// 入口參數:無
// 出口參數:無
/* ***************************************************** */
void IIC_Start(void)
{
SDA = 1;
Delay5US();
SCL = 1;
Delay5US();
SDA = 0;
Delay5US();
}
/* ***************************************************** */
// 函數名稱:IIC_Stop()
// 函數功能:IIC停止
// 入口參數:無
// 出口參數:無
/* ***************************************************** */
void IIC_Stop(void)
{
SDA = 0;
Delay5US();
SCL = 1;
Delay5US();
SDA =1;
}
/* ***************************************************** */
// 函數名稱:IIC_Ack()
// 函數功能:IIC應答
// 入口參數:無
// 出口參數:無
/* ***************************************************** */
void IIC_Ack(void)
{
SCL = 0; // 為產生脈沖準備
SDA = 0; // 產生應答信號
Delay5US(); // 延時你懂得
SCL = 1;Delay5US();
SCL = 0;Delay5US(); // 產生高脈沖
SDA = 1; // 釋放總線
}
/* ***************************************************** */
// 函數名稱:IIC_RdAck()
// 函數功能:讀IIC應答
// 入口參數:無
// 出口參數:是否應答真值
/* ***************************************************** */
BOOL IIC_RdAck(void)
{
BOOL AckFlag;
uChar8 uiVal = 0;
SCL = 0;Delay5US();
SDA = 1;
SCL = 1;Delay5US();
while((1 == SDA) && (uiVal < 255))
{
uiVal ++;
AckFlag = SDA;
}
SCL = 0;
return AckFlag; // 應答返回:0;不應答返回:1
}
/* ***************************************************** */
// 函數名稱:IIC_Nack()
// 函數功能:IIC不應答
// 入口參數:無
// 出口參數:無
/* ***************************************************** */
void IIC_Nack(void)
{
SDA = 1;
SCL = 0;Delay5US();
SCL = 1;Delay5US();
SCL = 0;
}
/* ***************************************************** */
// 函數名稱:OutputOneByte()
// 函數功能:從IIC器件中讀出一個字節
// 入口參數:無
// 出口參數:讀出的一個字節(uByteVal)
/* ***************************************************** */
uChar8 OutputOneByte(void)
{
uChar8 uByteVal = 0;
uChar8 iCount;
SDA = 1;
for (iCount = 0;iCount < 8;iCount++)
{
SCL = 0;
Delay5US();
SCL = 1;
Delay5US();
uByteVal <<= 1;
if(SDA)
uByteVal |= 0x01;
}
SCL = 0;
return(uByteVal);
}
/* ***************************************************** */
// 函數名稱:InputOneByte()
// 函數功能:向IIC器件寫入一個字節
// 入口參數:待寫入的一個字節(uByteVal)
// 出口參數:無
/* ***************************************************** */
void InputOneByte(uChar8 uByteVal)
{
uChar8 iCount;
for(iCount = 0;iCount < 8;iCount++)
{
SCL = 0;
Delay5US();
SDA = (uByteVal & 0x80) >> 7;
Delay5US();
SCL = 1;
Delay5US();
uByteVal <<= 1;
}
SCL = 0;
}
/* ***************************************************** */
// 函數名稱:IIC_WrDevAddAndDatAdd()
// 函數功能:向IIC器件寫入器件和數據地址
// 入口參數:器件地址(uDevAdd),數據地址(uDatAdd)
// 出口參數:寫入是否成功真值
/* ***************************************************** */
BOOL IIC_WrDevAddAndDatAdd(uChar8 uDevAdd,uChar8 uDatAdd)
{
IIC_Start(); // 發送開始信號
InputOneByte(uDevAdd); // 輸入器件地址
IIC_RdAck(); // 讀應答信號
InputOneByte(uDatAdd); // 輸入數據地址
IIC_RdAck(); // 讀應答信號
return TRUE;
}
/* ***************************************************** */
// 函數名稱:IIC_RdDatFromAdd()
// 函數功能:向IIC器件讀數據
// 入口參數:器件ID(uDevID)、數據存儲地址(uStaAddVal)
// 待存數據(*p)、連續存儲數據的個數(uiLenVal)
// 出口參數:無
/* ***************************************************** */
void IIC_RdDatFromAdd(uChar8 uDevID, uChar8 uStaAddVal, uChar8 *p, uChar8 uiLenVal)
{
uChar8 iCount;
IIC_WrDevAddAndDatAdd(uDevID | IIC_WRITE,uStaAddVal);
IIC_Start();
InputOneByte(uDevID | IIC_READ);
// IIC_READ 為寫命令后綴符
IIC_RdAck();
for(iCount = 0;iCount < uiLenVal;iCount++)
{
*p++ = OutputOneByte();
if(iCount != (uiLenVal - 1))
IIC_Ack();
}
IIC_Nack();
IIC_Stop();
}
/* ***************************************************** */
// 函數名稱:LM75A_ReadReg()
// 函數功能:讀LM75A任意寄存器值
// 入口參數:寄存器地址(addr),uLenVal,讀出字節的長度
// 出口參數:寄存器內容(*val)
/* ***************************************************** */
void LM75A_ReadReg(uChar8 addr, uChar8 *val, uChar8 uLenVal)
{
IIC_RdDatFromAdd(LM75ADevIDAddr, addr, val, uLenVal);
}
/* ***************************************************** */
// 函數名稱:LM75A_TempConv()
// 函數功能:溫度轉換
// 入口參數:無
// 出口參數:無
/* ***************************************************** */
void LM75A_TempConv(void)
{
uChar8 TempML[2]={0}; // 臨時數值,用于存放Temp的高低字節
uInt16 uiTemp; // 用于存放Temp的11位字節數據
LM75A_ReadReg(0x00,TempML,2); // 讀出溫度,并存于數組TempHL中
uiTemp = (uInt16)TempML[0]; // 將高字節存入變量uiTemp中
uiTemp = (uiTemp << 8 | TempML[1]) >> 5; // 接著并入后3位,最后右移5位就是11位補碼數(8+3共11位)
/* ***** 首先判斷溫度是“0上”還是是“0下” ***** */
if(!(TempML[0] & 0x80)) // 最高位為“0”則為“0上”
{
p_bH0L_Flag = 0;
p_fLM75ATemp = uiTemp * 0.125;
}
else // 這時為“0下”(p_fLM75ATemp)℃
{
p_bH0L_Flag = 1;
p_fLM75ATemp = (0x800 - uiTemp) * 0.125;// 由于計算機中負數是以補碼形式存的,所以有這樣的算法。
}
}
/* ***************************************************** */
// 函數名稱:UART_Init()
// 函數功能:串口初始化
// 入口參數:無
// 出口參數:無
/* ***************************************************** */
void UART_Init(void)
{
TMOD &= 0x0f; // 清空定時器1
TMOD |= 0x20; // 定時器1工作于方式2
TH1 = 0xfd; // 為定時器1賦初值
TL1 = 0xfd; // 等價于將波特率設置為9600
ET1 = 0; // 防止中斷產生不必要的干擾
TR1 = 1; // 啟動定時器1
SCON |= 0x40; // 串口工作于方式1,不允許接收
}
/* ***************************************************** */
// 函數名稱:main()
// 函數功能:讀取LN75A溫度值,數碼管顯示并串口打印
// 入口參數:無
// 出口參數:無
/* ***************************************************** */
void main()
{
long int DisTemp;
uChar8 i;
UART_Init();
while(1)
{
LM75A_TempConv();
/* ***** 數碼管顯示部分 ***** */
DisTemp = p_fLM75ATemp * 1000; // 將溫度全部轉換成整數,以便數碼管顯示
LedDisplay(DisTemp);
/* ***** 串口打印部分 ***** */
i++;
if(100 == i)
{
i = 0;
if(!p_bH0L_Flag)
{
TI = 1;
printf("當前溫度:+%.3f℃\n",p_fLM75ATemp);
while(!TI);
TI = 0;
}
else
{
TI = 1;
printf("當前溫度:-%.3f℃\n",p_fLM75ATemp);
while(!TI);
TI = 0;
}
}
}
} |