#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;
}
}
}
} |