专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

实时时钟+红外+温度传感器+LCD1602显示

作者:寒竹子   来源:本站原创   点击数:  更新时间:2014年05月02日   【字体:

 此程序是在51hei单片机开发板上面做的,如需要移植到自己的电路上,修改相应的端口即可,开发板完整的电路图下载:  点这里 (注意:只需要看相关部分的连线如液晶屏 等和单片机的连接方式,其他部分可以忽略)

/**
  ****************************************************************************
  * @file      main.c
  * @author    xr
  * @date      2014年4月10日22:21:56
  * @version   V1.2.3
  * @brief     在LCD1602上显示时钟,当前温度值,和NEC协议的红外解码值
  * @note      单片机STC89C52RC MCU  晶振 11.0592MHZ
  ****************************************************************************
  */

#include <reg52.h>
#include "mytype.h"
bit fack = 0;//接收到温度数据标志位
bit flag1s = 0;//1s时间标志位
bit flag200ms = 0;//200ms标志
uint8 thr0, tlr0;
uint8 counter = 0, i = 0;
//数码管编码
uint8 code LedTable[] = { 
    0xC0,  //"0"
                0xF9,  //"1"
                0xA4,  //"2"
                0xB0,  //"3"
                0x99,  //"4"
                0x92,  //"5"
                0x82,  //"6"
                0xF8,  //"7"
                0x80,  //"8"
                0x90,  //"9"
                0x88,  //"A"
                0x83,  //"B"
                0xC6,  //"C"
                0xA1,  //"D"
                0x86,  //"E"
                0x8E   //"F"
   };
extern void InitLcd1602();
extern void LcdShowStr(uint8 x, uint8 y, uint8 * str);
extern bit StartDs18B20();
extern bit ReadDs18B20Temp(int * temp);
extern void InitDS1302();
extern void DS1302BurstRead(uint8 * time);
extern void InitInfrared();
//外部变量只是声明,不可以重新赋值
extern bit Irflag;//红外遥控器解码数据接收完成标志
extern uint8 Ircode[4];//存放遥控器解码值(用户码, 用户码反码,键码,键码反码)

void ConfigTimer0(uint16 xms);
uint8 IntToString(uint8 * str, int dat);
void main(void)
{
 uint8 buf[4];
 uint8 len = 0;
 int temp;//温度
 int intT, decT;//整数部分,小数部分
 uint8 str[20];
 uint8 time[20];//保存时间(BCD码值)
 uint8 psec = 0xFF;//sec最大是59,所以一定能刷新显示
 
 InitLcd1602();
 InitDS1302();
 ConfigTimer0(10);//定时10ms
 StartDs18B20();
 InitInfrared();
 
 while (1)
 {
  if (Irflag) //红外解码
  {
   Irflag = 0;
   
   buf[0] = Ircode[2] / 10 % 10;//按键码的十位数
   buf[1] = Ircode[2] % 10;//按键码的个位数
   str[0] = buf[0] + '0';
   str[1] = buf[1] + '0';
   str[2] = '\0';
   
   LcdShowStr(14, 1, str);
  }
  
  if (flag200ms) //200ms刷新时钟显示
  {
   flag200ms = 0;
   
   DS1302BurstRead(time);
   if (psec != time[0]) //time[0]保存的是sec寄存器的BCD码值
   {
    //刷新显示
    //日期
    str[0] = '2';
    str[1] = '0';
    str[2] = (time[6] >> 4) + '0';//取年十位
    str[3] = (time[6] & 0x0F) + '0';//取年个位转字符
    str[4] = '-';
    str[5] = (time[4] >> 4) + '0'; //月十位
    str[6] = (time[4] & 0x0F) + '0'; //月个位
    str[7] = '-';
    str[8] = (time[3] >> 4) + '0'; //日十位
    str[9] = (time[3] & 0x0F) + '0'; //日个位
    str[10] = '\0';
    
    LcdShowStr(0, 0, str);
    
    //时间
    str[0] = (time[2] >> 4) + '0';//时十位
    str[1] = (time[2] & 0x0F) + '0';//时个位
    str[2] = ':';
    str[3] = (time[1] >> 4) + '0';
    str[4] = (time[1] & 0x0F) + '0';
    str[5] = ':';
    str[6] = (time[0] >> 4) + '0';
    str[7] = (time[0] & 0x0F) + '0';
    str[8] = '\0';
    
    LcdShowStr(0, 1, str);
    
    //星期
    str[0] = (time[5] & 0x0F) + '0';//星期只有一位数字
    str[1] = '\0';
    
    LcdShowStr(11, 0, "Week");
    LcdShowStr(15, 0, str);
    
    psec = time[0];
   }
  }
  
  if (flag1s) //1s刷新温度显示
  {
   flag1s = 0;
   
   fack = ReadDs18B20Temp(&temp);//读取温度
   if (fack) //读取成功
   {
    intT = (temp >> 4);//整数部分,将小数部分移出
    decT = (temp & 0x000F);//小数部分
    len = IntToString(str, intT);//将intT整数部分转换成字符存入str中,并返回有效字符个数
    str[len++] = '.';//小数点
    decT = decT * 10 / 16 % 10;//小数部分转换
    str[len++] = decT + '0';
    str[len] = '\0';
    
    LcdShowStr(8, 1, "T:");
    LcdShowStr(10, 1, str);    
   }
   else
   {
    LcdShowStr(0, 0, "error!");
   }
  }
  StartDs18B20();//重新启动温度转换
 }
}
//定时器T0配置
void ConfigTimer0(uint16 xms)
{
 uint16 tmp;
 tmp = 65536-xms*11059200/12/1000;
 thr0 = (uint8)(tmp >> 8);//取高字节
 tlr0 = (uint8)(tmp & 0x00FF);//取低字节
 TMOD &= 0xF0;//清零T0控制位
 TMOD |= 0x01;//T0方式1
 TH0 = thr0;
 TL0 = tlr0;//装入定时初值
 TR0 = 1;//启动T0定时器
 EA  = 1;//开总中断
 ET0 = 1;//开定时器T0中断
 
 //PT0 = 1;//设置T0中断优先级为最高级
}
//整数转换成str
unsigned char IntToString(unsigned char * str, signed int dat)
{
 unsigned char len = 0;//统计有效字符的个数
 signed char i = 0;//计数器
 unsigned char buff[6];//数据分解缓冲区
 
 if (dat < 0) //负数
 {
  dat = -dat;//取绝对值
  *str++ = '-';//前面加上-
  len++;//长度++
 }
 
 //分解整数dat到buff中
 do
 {
  buff[i++] = dat % 10;
  dat /= 10;
 } while (dat > 0);//分解到dat==0为止
 len += i;//长度+i,有效字符个数
 while (i-- > 0) //拷贝转换后的ASIIC码字符到str接收指针中
 {
  *str++ = buff[i] + '0';//转换成ASCII字符
 }
 *str = '\0';//加上串结束符
 
 return len;//返回有效字符个数
}
//定时器T0中断服务
void timer0_ISP() interrupt 1

 TH0 = thr0;
 TL0 = tlr0;
 counter++;
 if (counter >= 20)
 {
  counter = 0;
  flag200ms = 1;
  i++;
  if (i >= 5)
  {
   i = 0;
   flag1s = 1;
  }
 }
}


 /**********自定义头文件************/
#ifndef _MYTYPE_H_H
#define _MYTYPE_H_H
typedef unsigned int uint16;
typedef unsigned char uint8;
typedef unsigned long uint32;
#endif //_MYTYPE_H_H

 /***************LCD1602.c*********************/
#include <reg52.h>
#include "mytype.h"
//LCD1602
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_EN = P1^5;
#define LCD1602_DB P0
//液晶忙碌等待
void WaitLcd1602()
{
 uint8 sta;
 
 LCD1602_DB = 0xFF;//拉高P0口
 
 LCD1602_RS = 0;
 LCD1602_RW = 1;
 do
 {
  LCD1602_EN = 1;
  sta = LCD1602_DB;
  LCD1602_EN = 0;//关闭液晶的数据输出
 } while (sta & 0x80);
}
//写命令
void WriteLcd1602Cmd(uint8 cmd)
{
 WaitLcd1602();
 
 LCD1602_RS = 0;
 LCD1602_RW = 0;
 LCD1602_DB = cmd;
 LCD1602_EN = 1;//高脉冲
 LCD1602_EN = 0;
}
//写数据
void WriteLcd1602Data(uint8 dat)
{
 WaitLcd1602();
 
 LCD1602_RS = 1;
 LCD1602_RW = 0;
 LCD1602_DB = dat;
 LCD1602_EN = 1;//高脉冲
 LCD1602_EN = 0;
}
//液晶初始化
void InitLcd1602()
{
 WriteLcd1602Cmd(0x38);//设置16*2显示 5*7点阵 8位数据口
 WriteLcd1602Cmd(0x0C);//开显示不显示光标
 WriteLcd1602Cmd(0x06);//写入一个字符时字符指针++且地址++
 WriteLcd1602Cmd(0x01);//清屏
}
//写str到LCD1602
void LcdShowStr(uint8 x, uint8 y, uint8 * str)
{
 uint8 addr;
 
 if (y == 0)
 { //第一行
  addr = 0x00 + x;
 }
 else
 { //第二行
  addr = 0x40 + x;
 }
 
 WriteLcd1602Cmd(0x80 | addr);
 while (*str != '\0')
 {
  WriteLcd1602Data(*str++);
 }
}

/**
  *********************************************************************
  * @file     infrared.c
  * @author   xr
  * @date     2014年4月11日08:25:04
  * @version  V1.2.3
  * @brief    红外通信-NEC协议红外遥控器解码驱动
  * @note     单片机STC89C52RC MCU 晶振 11.0592MHZ
  *********************************************************************
  */
 
#include <reg52.h>
#include "mytype.h"
//红外通信接口位声明
sbit IRD = P3^3;
bit Irflag = 0;//红外遥控器解码数据接收完成标志
uint8 Ircode[4];//存放遥控器解码值(用户码, 用户码反码,键码,键码反码)
extern void LcdShowStr(uint8 x, uint8 y, uint8 * str);
/**
  * @brief     红外通信配置
  * @param     无
  * @retval    无
  */
void InitInfrared()
{
 //使用定时器T1作为计数,不定时也不进入T1中断
 TMOD &= 0x0F;//清零T1控制位
 TMOD |= 0x10;//设置T1方式1
 ET1 = 0;//禁止T1中断
 TR1 = 0;//在外部中断引脚即红外通信引脚没有载波(低电平)和空闲(高电平)时,先关闭T1计数
 TH1 = 0;
 TL1 = 0;//清零T1计数值
 
 //使能外部中断1
 IT1 = 1;//设置INT1中断触发方式为负边沿触发
 EX1 = 1;//开启外部中断1
 EA  = 1;//开启总中断
 PX1 = 1;
}
/**
  * @brief     获取红外通信引脚载波(低电平)计数值
  * @param     无
  * @retval    载波计数值(即T1计数值)
  */
uint16 GetLowCounter() //计数值*(12/11059200)即是载波时间,计数值=TH1*256+TL1
{
 IRD = 1;//在检测IRD引脚电平时要将此引脚拉高释放
 TH1 = 0;
 TL1 = 0;//清零T1计数值
 TR1 = 1;//开启T1计数
 
 while (!IRD) //若IRD=0,T1开始计数
 {
  //超时判断,因为引导码的载波时间是9ms,所以不能等待太长时间
  if (TH1 > 0x40) //超过20ms就强制退出 (TH1*256*(12/11059200)s)
  {
   break;
  }
 }
 TR1 = 0;//关闭T1计数
 
 return (TH1*256 + TL1);//返回计数值(TL1加满到256向TH1进1)
}
/**
  * @brief     获取空闲时间计数值(高电平)
  * @param     无
  * @retval    空闲计数值
  */
uint16 GetHeighCounter()
{
 IRD = 1;//拉高释放引脚,以检测IRD引脚的电平
 TH1 = 0;
 TL1 = 0;//清零T1计数值
 TR1 = 1;//开启计数
 
 while (IRD)
 {
  if (TH1 > 0x40) //等待超出20ms,则认为是错误,强制退出
  {
   break;
  }
 }
 TR1 = 0;//关闭T1计数
 
 return (TH1*256 + TL1);//返回T1计数值
}
/**
  * @brief      外部中断1服务程序(判断解码)
  * @param      无
  * @retval     无
  */
void EXINT1_ISP() interrupt 2 //INT1中断标号:2
{
 //NEC协议:引导码(9ms载波+4.5ms的空闲) 用户码-用户反码-键码-键码反码-停止位
 //   比特值0:(560us的载波+560us的空闲) 比特值1:(560us的载波+1.68ms的空闲)
 uint8 i, j;
 uint8 byte;//接收字节
 uint16 time;//获取时间
 
 //首先判断引导码
 time = GetLowCounter();//time*12/11059200*1000ms
 if ((time < 7834) || (time > 8755)) //如果不在8.5ms-9.5ms的范围就清零外部中断1标志位,退出中断
 {
  IE1 = 0;//清零中断标志
  return;//退出中断函数
 }
 time = GetHeighCounter();//空闲
 if ((time < 3686) || (time > 4608)) //如果不在4ms-5ms的范围就退出中断
 {
  IE1 = 0;//中断标志硬件置位,软件清零
  return;
 }
 //引导码正确,开始接收解码数据
 
 for (i = 0; i < 4; i++) //接收4个字节数据
 {
  for (j = 0; j < 8; j++) //每个字节8bit
  {
   time = GetLowCounter();//载波时间计数
   if ((time < 424) || (time > 608)) //如果载波时间不在460-660us的范围则认为是误码,退出中断
   {
    IE1 = 0;
    return;
   }
   //检测到560us的载波,开始判断是560us的空闲还是1.68ms的空闲
   time = GetHeighCounter();//空闲
   if ((time > 424) && (time < 608)) //560us的空闲(即比特0)
   {
    //低位在先,逐位右移
    byte >>= 1;//右移一位0
   }
   else if ((time > 1198) && (time < 1659)) //1.68ms的空闲 1.3-1.8ms
   {
    byte >>= 1;//低位在先,先右移出一位
    byte |= 0x80;//再将这一位置1
   }
   else
   {
    //误码
    IE1 = 0;
    return;
   }
  }
  Ircode[i] = byte;//循环接收解码字节数据
  
 }
 //4个字节全部接收完成
 Irflag = 1;
 IE1 = 0;
}

 /**
  *******************************************************************
  * @file     ds1302.c
  * @author   xr
  * @date     2014年4月10日17:31:07
  * @version  V1.2.3
  * @brief    DS1302底层驱动   单片机STC89C52RC MCU  晶振11.0592MHZ
  *******************************************************************
  */
 
#include <reg52.h>
#include "mytype.h"
//DS1302时钟线,数据线,和使能引脚位声明
sbit DS1302_SCK = P3^5;
sbit DS1302_SIO = P3^4;
sbit DS1302_CE  = P1^7;
/**
  * @brief    DS1302写一个字节数据
  * @param    待写入的字节
  * @retval   无
  */
void DS1302WriteByte(uint8 byte)
{
 uint8 mask = 0x01;//发送掩码(低位在前,逐位发送)
 DS1302_SCK = 0;
 
 for (mask = 0x01; mask != 0; mask <<= 1) ////发送掩码(低位在前,逐位发送)
 {
  if ((mask & byte) == 0)
  {
   DS1302_SIO = 0;
  }
  else
  {
   DS1302_SIO = 1;
  } //将数据准备好
  DS1302_SCK = 1;//先来一个上升沿,从机DS1302进行数据的采样锁存
  DS1302_SCK = 0;//再来一个下降沿,主机进行数据的输出
 }
 //当一个字节的数据发送完成后,主机(即单片机)释放SIO数据总线,由DS1302进行数据的发送
 DS1302_SIO = 1;
}
/**
  * @brief     DS1302读一个字节的数据
  * @param     无
  * @retval    返回读取到的数据
  */
uint8 DS1302ReadByte()
{
 uint8 byte = 0;//存放待读取的字节
 uint8 mask = 0x01;//接收掩码(低位在先,逐位接收)
 DS1302_SCK = 0;
 
 for (mask = 0x01; mask != 0; mask <<= 1) //(低位在先,逐位接收)
 {
  if (DS1302_SIO == 1)
  {
   byte |= mask;//字节byte的相应位置1
  }
  else
  {
   byte &= ~mask;//字节byte的相应位清零
  }
  DS1302_SCK = 1;//先来一个上升沿,主机进行数据采样接收
  DS1302_SCK = 0;//再来一个下降沿,从机DS1302进行数据输出
 }
 
 return (byte);
}
/**
  * @brief     向DS1302寄存器中写入数据
  * @param     待写入数据的寄存器地址reg和待写入的数据dat
  * @retval    无
*/
void WriteDS1302(uint8 reg, uint8 dat)
{
 DS1302_CE = 1;//使能DS1302
 DS1302WriteByte((reg << 1) | 0x80);//寄存器的最高位固定位1第二位为RAM/CLK选择位,A5-A1为寄存器地址位
          //且有效位为A3-A1,A0位为读写方向位
 DS1302WriteByte(dat);//写入数据
 DS1302_CE = 0;//关闭片选
 
 DS1302_SIO = 0;//由于本版本的开发板上的DS1302的SIO口没有加上拉电阻,在释放SIO后SIO处于
     //非0非1的不稳定状态,由于IO口的内部输出通过反相器输出,给SIO=0则SIO口
     //会输出一个高电平1,从而保持SIO数据口的稳定!
}
/**
  * @brief     读DS1302寄存器
  * @param     待读取的寄存器地址reg
  * @retval    读取到的数据dat
  */
uint8 ReadDS1302(uint8 reg)
{
 uint8 dat = 0;
 
 DS1302_CE = 1;//使能片选
 DS1302WriteByte((reg << 1) | 0x81);//左移出一位存放读写位,这里选择读
 dat = DS1302ReadByte();
 DS1302_CE = 0;
 
 DS1302_SIO = 0;
 
 return (dat);
}
/**
  * @brief      DS1302 Burst触发模式连续写八个寄存器
  * @param      待写入数据指针*dat
  * @retval     无
  */
void DS1302BurstWrite(uint8 * dat)
{
 uint8 i = 0;
 
 DS1302_CE = 1;//使能片选
 DS1302WriteByte(0xBE);//A5-A1写入1,触发DS1302的突发模式连续读写八次
 for (i = 0; i < 8; i++)
 {
  DS1302WriteByte(dat[i]);//写Sec-WP八个寄存器
 }
 DS1302_CE = 0;//关闭片选
 
 DS1302_SIO = 0;//通过反相器SIO口输出1,保持稳定
}
/**
  * @brief     DS1302 Burst模式连续读取八个寄存器
  * @param     待接收读取的数据的指针*time
  * @retval    无
  */
void DS1302BurstRead(uint8 * time)
{
 uint8 i = 0;
 
 DS1302_CE = 1;//使能片选
 DS1302WriteByte(0xBF);//触发突发模式读操作
 for (i = 0; i < 8; i++)
 {
  time[i] = DS1302ReadByte();//读取Sec-WP八个寄存器
 }
 DS1302_CE = 0;//关闭片选
 
 DS1302_SIO = 0;//使SIO口处于稳定
}
/**
  * @brief      DS1302初始化
  * @param      无
  * @retval     无
  */
void InitDS1302()
{
 uint8 ch = 0;//用于检测DS1302停止状态
 uint8 InitTime[] = {0x56, 0x59, 0x23, 0x10, 0x04, 0x04, 0x14, 0x00};//2014年4月10日23:59:56 WP=0
 
 //读取秒寄存器
 ch = ReadDS1302(0);
 if ((ch & 0x80) != 0) //检测秒寄存器的最高位CH,CH为1标志DS1302已经停止运行,要去除写保护,写入初始时间
 {
  DS1302BurstWrite(InitTime);//突发模式写
 }
}

/**
  ******************************************************************
  * @file     ds18b20.c
  * @author   xr
  * @date     2014年4月1日21:03:47
  * @version  V1.2.3
  * @brief    温度传感器DS18B20检测温度值程序
  * @note     单片机STC89C52RC MCU   晶振 11.0592MHZ
  ******************************************************************
  */
 
#include <reg52.h>
#include <intrins.h>
//温度传感器引脚
sbit IO_DS18B20 = P3^2;
/**
  * @brief    软件延时xus
  * @param    无
  * @retval   无
  */
void delayx10us(unsigned int xus)

 do
 {
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
 } while (xus--); //8个_nop_()和函数的进栈出栈时间大约10us
}
/**
  * @brief    DS18B20温度传感器初始化检测存在脉冲
  * @param    无
  * @retval   无
  */
bit ReadDs18B20Ack()
{
 bit ack; //存放检测到的DS18B20的存在脉冲
 
 EA = 0;//由于DS18B20的时序时间的要求很高,进出中断需要十几个us会影响时序时间
 IO_DS18B20 = 0;//复位脉冲
 delayx10us(60);//持续600us
 IO_DS18B20 = 1;//释放总线,来检测DS18B20的存在脉冲
 delayx10us(6);//延时60us后来读取DS18B20的存在脉冲,这个时候肯定可以读取到
 ack = IO_DS18B20;
 while (!IO_DS18B20);//等待存在脉冲的结束
 EA = 1;//重新开启中断
 
 return ack;//返回存在脉冲
}
/**
  * @brief    DS18B20写一个字节数据
  * @param    待写入数据 dat
  * @retval   无
  */
void WriteDs18B20(unsigned char dat)
{
 unsigned char mask = 0x01;//低位在前,逐位发送
 
 EA = 0;//在发送每一位时必须将总中断关闭,避免进出中断时间影响DS18B20的读写
 
 for (mask = 0x01; mask != 0; mask <<= 1)
 {
  IO_DS18B20 = 0;//主机拉低
  _nop_();
  _nop_();//延时2us,写1或0时延时>1us
  if ((mask & dat) == 0)
  {
   IO_DS18B20 = 0;
  }
  else
  {
   IO_DS18B20 = 1;
  }
  delayx10us(6); //延时60-120us等待DS18B20来读取数据
  IO_DS18B20 = 1;//释放总线,这时DS18B20会来采样数据进行写入
 }
 EA = 1;//写入一个字节数据完毕,打开总中断
}
/**
  * @brief    读DS18B20一个字节
  * @param    无
  * @retval   读取的数据
  */
unsigned char ReadDs18B20()
{
 unsigned char mask = 0x01;//低位在前,逐位接收
 unsigned char dat = 0;
 
 EA = 0;//DS18B20在读取数据前要关闭中断,避免进出中断时间,影响读取
 for (mask = 0x01; mask != 0; mask <<= 1)
 {
  IO_DS18B20 = 0;//读0或读1时主机要先拉低>1us再拉高释放>1us时间,然后主机对DS18B20进行数据的采样读取
  _nop_();
  _nop_();
  IO_DS18B20 = 1;
  _nop_();
  _nop_();
  if (IO_DS18B20 == 0)
  {
   dat &= ~mask;//相应位置1
  }
  else
  {
   dat |= mask;//相应位清零
  }
  delayx10us(6);//延时60-120us,等待主机数据的采样
 }
 EA = 1;//开总中断
 
 return dat;
}
/**
  * @brief    启动DS18B20温度转换,启动成功则返回应答ack
  * @param    无
  * @retval   返回复位存在脉冲
  */
bit StartDs18B20()
{
 bit ack;
 
 ack = ReadDs18B20Ack();//进行DS18B20复位,并读取DS18B20的存在脉冲
 if (ack == 0)
 {
  WriteDs18B20(0xCC);//跳过ROM的器件地址寻址,因为只有一个DS18B20
  WriteDs18B20(0x44);//启动温度转换
 }
 
 return ~ack;//ack==0则转换成功
}
/**
  * @brief    读取DS18B20的温度值
  * @param    无
  * @retval   返回复位存在脉冲的取反值
  */
bit ReadDs18B20Temp(int * temp) //温度值保存到temp指针指向的变量中
{
 bit ack;//保存复位的存在脉冲
 unsigned char lsb, msb;//温度值的低字节和高字节
 
 ack = ReadDs18B20Ack();//DS18B20复位,并读取DS18B20的存在脉冲
 if (ack == 0) //复位成功
 {
  WriteDs18B20(0xCC);//跳过ROM多个DS18B20的寻址
  WriteDs18B20(0xBE);//读暂存寄存器中的数据
  lsb = ReadDs18B20();//因为读取是从低位向高位读取的,所以先读取的是低字节数据
  msb = ReadDs18B20();//读取高字节数据
  //将温度值的低字节和高字节数据进行合并成16bit数据,易于计算
  *temp = ((int)(msb) << 8) + lsb;//先将高字节强制转换成16为数据,将高字节移到高八位,再将低字节放到低八位即可
 }
 
 return ~ack;//ack == 0表示读取成功
关闭窗口

相关文章