#define DS18B20_GPIO_PORT (GPIOC)
#define DS18B20_GPIO_PIN (GPIO_Pin_2)
#define DS18B20_PIN_SET_OUT() GPIO_Init(DS18B20_GPIO_PORT, (GPIO_Pin_TypeDef)DS18B20_GPIO_PIN, GPIO_Mode_Out_PP_High_Fast)
#define DS18B20_PIN_SET_IN() GPIO_Init(DS18B20_GPIO_PORT, (GPIO_Pin_TypeDef)DS18B20_GPIO_PIN, GPIO_Mode_In_PU_No_IT)
#define DS18B20_WR1() GPIO_SetBits(DS18B20_GPIO_PORT, (GPIO_Pin_TypeDef)DS18B20_GPIO_PIN)
#define DS18B20_WR0() GPIO_ResetBits(DS18B20_GPIO_PORT, (GPIO_Pin_TypeDef)DS18B20_GPIO_PIN)
#define R_DS18B20() GPIO_ReadInputDataBit(DS18B20_GPIO_PORT, (GPIO_Pin_TypeDef)DS18B20_GPIO_PIN)
/* Private macro -------------------------------------------------------------*/
#define READ_ROM 0x33 //读取序列号
#define SKIP_ROM 0xCC //跳过ROM
#define MATCH_ROM 0x55 //匹配ROM
#define CONVERT_TEM 0x44 //转换温度
#define READ_RAM 0xBE //读暂存器
#define WRITE_RAM 0x4E //写暂存器
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void _delay_us(uint16_t nCount)
{
nCount *= 3;
while(--nCount);
}
/**
* @brief _delay_ms
* @param nCount
* @retval None
*/
void _delay_ms(uint16_t nCount)
{
while(nCount--)
{
_delay_us(1000);
}
}
/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/
void Alarm_for_No_DS18B20(void)
{
//单总线上没有发现DS18B20则报警,该动作据具体应用具体处理
}
//---------------------------------------------------------------------
unsigned char DS18B20_Start(void) //复位ds18b20芯片
{
unsigned char i,succ=0xff;
DS18B20_PIN_SET_OUT(); //置为输出口
DS18B20_WR0(); //总线产生下降沿,初始化开始
for(i=0; i<30; i++)_delay_us(25); //总线保持低电平在480 - 960微秒之间 ;i<20;(25us)
DS18B20_WR1(); //总线拉高
DS18B20_PIN_SET_IN(); //置为输入,主机释放总线,准备接收DS18B20的应答脉冲
i=0;
while(R_DS18B20()) //等待DS18B20发出应答脉冲
{
_delay_us(5); //5
if(++i>12) //DS18B20检测到总线上升沿后等待15-60us
{
succ=0x00; //如果等待大于约60us,报告复位失败
break;
}
}
i=0;
while(!R_DS18B20()) //DS18B20发出存在脉冲,持续60-240us
{
_delay_us(5); //5
if(++i>48) //如果等带大于约240us,报告复位失败
{
succ=0x00;
break;
}
}
_delay_us(20);
return succ;
}
//---------------------------------------------------------------------
void DS18B20_SendU8(unsigned char d8)//向DS18B20写一字节函数
{
unsigned char i;
DS18B20_PIN_SET_OUT(); //置为输出口
for(i=0; i<8; i++)
{
DS18B20_WR0(); //总线拉低,启动“写时间片”
_delay_us(2); //大于1微妙
if(d8&0x01)DS18B20_WR1();
_delay_us (32); //延时至少60微秒,使写入有效
_delay_us (30);
DS18B20_WR1(); //总线拉高,释放总线,准备启动下一个“写时间片”
d8>>=1;
_delay_us (1);
}
DS18B20_PIN_SET_IN(); //主机释放总线
}
//---------------------------------------------------------------------
unsigned char DS18B20_ReadU8(void)//从DS18B20读1个字节函数
{
unsigned char i,d8;
for(i=0; i<8; i++)
{
d8>>=1;
DS18B20_PIN_SET_OUT();//置为输出口
DS18B20_WR0(); //总线拉低,启动读“时间片”
_delay_us(2); //大于1微妙
DS18B20_WR1(); //主机释放总线,接下来(2~15)us内读有效
DS18B20_PIN_SET_IN(); //引脚设定为输入口,准备读取
_delay_us(2); //延时2个us后进行读
if(R_DS18B20())d8|=0x80;//从总线拉低时算起,约15微秒内读取总线数据
_delay_us(32); //60us后读完成
_delay_us(30);
DS18B20_WR1(); //总线拉高,主机释放总线,准备启动下一个“写时间片”
}
DS18B20_PIN_SET_IN(); //主机释放总线
return(d8);
}
//------------------------------------------------------------------------------------
void Init_DS18B20(void) //初始化DS18B20
{
unsigned char i;
i=DS18B20_Start(); //复位
if(!i) //单总线上没有发现DS18B20则报警
{
Alarm_for_No_DS18B20();
return;
}
DS18B20_SendU8 (SKIP_ROM); //跳过rom匹配
DS18B20_SendU8 (WRITE_RAM); //设置写模式
DS18B20_SendU8 (0x64); //设置温度上限100摄氏度
DS18B20_SendU8 (0x8a); //设置温度下线-10摄氏度
DS18B20_SendU8 (0x7f); //12bit(默认)
}
//--------------------------------------------------------------------------------------
unsigned int Read_DS18B20(void) //读取并计算要输出的温度
{
unsigned char i;
unsigned char tl;
unsigned int th;
i=DS18B20_Start(); //复位
if(!i) //单总线上没有发现DS18B20则报警
{
Alarm_for_No_DS18B20();
return 0;
}
_delay_ms(1);
DS18B20_SendU8(SKIP_ROM); //发跳过序列号检测命令
DS18B20_SendU8(CONVERT_TEM); //命令Ds18b20开始转换温度
i=0;
_delay_ms(1);
while(!R_DS18B20()) //当温度转换正在进行时,主机读总线将收到0,转换结束为1
{
_delay_ms(3);
if(++i>250) break; //至多转换时间为750ms
}
DS18B20_Start(); //初始化
_delay_ms(1);
DS18B20_SendU8(SKIP_ROM); //发跳过序列号检测命令
DS18B20_SendU8(READ_RAM); //发读取温度数据命令
tl=DS18B20_ReadU8(); //先读低8位温度数据
th=DS18B20_ReadU8()<<8; //再读高8位温度数据
return (th|tl)*10>>4; //温度放大了10倍,*0.0625=1/16=>>4
}
上一篇:STC-ISP下载失败的原因与解决汇总
下一篇:单片机上操作系统的好处
推荐阅读最新更新时间:2024-03-16 16:12