原创 CC2430 驱动DS18B20(续)

2011-5-16 23:17 3363 9 10 分类: 通信

//从DS18b20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
unsigned char readBit(void)
{
    unsigned char bi,bii;
    SET_OUT;//转为输出
    ds = 0;
    Delay_nus(1); //延时,协议要求至少保持1us
    ds = 1;//释放总线
    SET_IN;//转为输入
    bi = ds;//立即取样,在开始读取命令发出后,数据会有效15us
    bii=bi;
    Delay_nus(45);//既然说最小是60us那就60好了
    SET_OUT;
    ds=1;//说要给1us的recovery time between slots这样也使得读完后恢复初始化状态
    return bii;
}
//读取一字节数据, 通过调用readBit()来实现
unsigned char readByte(void)
{
    unsigned int i;
    unsigned char j, dat;
    dat = 0;
    for(i=0; i<8; i++)
    {
    j = readBit();
    //最先读出的是最低位数据
    dat = (j << 7) | (dat >> 1);
    }
    return dat;
}
//向DS18B20写入一字节数据
//写有两周种0、All write time slots must be a minimum of 60us in duration
//中间也1us recovery time between individual write slots
//拉低表示开始
void writeByte(unsigned char dat)
{
    unsigned char j;
    unsigned char bi;
    SET_OUT;//倒转位输出口
    for(j = 0; j < 8; j++)
    {
        bi = dat & 0x01;
        dat=dat>>1;
        //写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1
        if(bi)//To generate a Write 1 time slot, after pulling the 1-Wire bus low,
        //thebusmaster must release the 1-Wire within 15us
        {
            ds = 0;//拉低约16us, 符号要求15~60us内
            Delay_nus(2);//至少1us
            ds = 1;//释放总线
            Delay_nus(60); //总时隙不低于60us要求
        }
        else //写"0", 将DQ拉低60us~120us
        {
            ds = 0;
            Delay_nus(62); //拉低约62us
            ds = 1;
            Delay_nus(2); //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再
            //延时64us了
        }
    }
}
//向DS18B20发送温度转换命令
void sendChangeCmd(void)
{
    dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化
    delay(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号
    writeByte(0xcc); //写入跳过序列号命令字 Skip Rom
    writeByte(0x44); //写入温度转换命令字 Convert T
}
//向DS18B20发送读取数据命令
void sendReadCmd(void)
{
    dsInit();
    delay(1);
    writeByte(0xcc); //写入跳过序列号命令字 Skip Rom
    writeByte(0xbe); //写入读取数据令字 Read Scratchpad
}
//获取当前温度值
int getTmpValue(void)
{
    unsigned int tmpvalue;
    int value; //存放温度数值
    float t;
    unsigned char low, high;
    sendReadCmd();
    //连续读取两个字节数据
    low  = readByte();
    high = readByte();
    //将高低两个字节合成一个整形变量
    //计算机中对于负数是利用补码来表示的
    //若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的value
    tmpvalue = high;
    tmpvalue <<= 8;
    tmpvalue |= low;
    value = (int)tmpvalue;
    //使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度
    t = value * 0.0625;
    //将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入
    //如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度
    //如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度
    value = (int)(t);//value = (int)(t*100 + (value > 0 ? 0.5 : -0.5)); //大于0加0.5, 小于0减0.5
    return value;
}

void Delay_nus(uint16 s) {
  while (s--)
  {
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
   
  }
}

uint8 myApp_ReadTemperature( void )
{
#if defined HAL_MCU_CC2430
   int  tempValue=0;//jia
   uint16 value;

  /* Clear ADC interrupt flag 此中断清除也是原SimpleApp中的*/
  ADCIF = 0;
//***************************************原来SimpleApp的部分2011-4-21*******************************************
//  ADCCON3 = (HAL_ADC_REF_125V | HAL_ADC_DEC_128 | HAL_ADC_CHN_VDD3);
//注释掉的这些函数是原来的,建议修改的时候保留,这样利于以后搞清楚自己的修改过程,免得新程序没搞好
//原来的也坏掉了,另外建议在注释掉的地方加上时间等标记,这是良好的习惯
  /* Wait for the conversion to finish */
//  while ( !ADCIF );
  /* Get the result */
//  value = ADCL;
//  value |= ((uint16) ADCH) << 8;
  /*
   * value now contains measurement of Vdd/3
   * 0 indicates 0V and 32767 indicates 1.25V
   * voltage = (value*3*1.25)/32767 volts
   * we will multiply by this by 10 to allow units of 0.1 volts
   */
//  value = value >> 6;   // divide first by 2^6
//  value = value * 37.5;
//  value = value >> 9;   // ...and later by 2^9...to prevent overflow during multiplication
//******************************************************************************************************************************
    //启动温度转换///jia
    sendChangeCmd();//jia
    //读取温度转换值
    tempValue = getTmpValue();//jia
   value=(uint16)tempValue;
  return value;

#endif    // CC2430
}
另外说明,函数的注释我写的十分多,其实是没有必要的,正常的程序里应尽量简洁把关键说明白就行了,太多的反而不好。
但这里写这么多是为了使看到本程序的人能够详细的了解处理过程,方便大家……
再次声明:请尊重本人劳动成果,转载请注明出处
PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1696769 2011-5-18 15:46

很不错,很细致。
相关推荐阅读
用户401512 2012-07-23 18:45
dsPIC产生PWM控制H桥
最近在群里遇到一个人问dsPIC 单片机PWM波的相位问题。首先需要产生互补、占空比可随时调整的PWM波形控制H桥,但互补PWM波形的相位并不是像单片机直接产生的那样(完全对着,如图1),而是需要第...
用户401512 2012-05-30 00:21
评论:@shaoziyang's Blog 博客中提到的“在精简版的XP中安装EK-LM3S811-ND-Rev2驱动失败的...”
太有用了,谢谢...
用户401512 2011-05-16 23:15
CC2430驱动DS18B20
CC2430驱动DS18B20经过验证之后,结果终于出来了,在SimpleApp程序的SimpleSensor程序中用的应该是默认的16Mhz晶振,...
EE直播间
更多
我要评论
1
9
关闭 站长推荐上一条 /3 下一条