本人现在在做基于STM32的DS18B20的测温,但是一直不成功。就拿初始化来说,按照时序图是先给低电平480us或以上,再给15us的高电平,然后就放开总线,18B20就开始复位。我的初始化程序时要看18B20有没有复位完成。但是我用示波器来看的时候前面给的开始信号是正确的,但是后面读18B20的复位输出的时候,18B20一直处于高电平.......为什么呢?
- char ds18b20_Reset(void)
- {
- uint8_t count = 0,i = 0;
- GPIO_Out_Config();
- DQ_L;
- Delay_us(480);
- DQ_H;
- Delay_us(15);
- GPIO_In_Config();//IPU模式能读数,但是一直为1,18b20可能坏了
- Delay_us(10);
- while(count < 100)
- {
- i = DQ_Read;
- if(i == 1)
- {
- NOP();
- count++;
- }
- else
- break;
- }
- if(count >= 100)
- return 0;
- else
- count = 0;
- while(count <240)
- {
- i = DQ_Read;
- if(i ==0)
- {
- NOP();
- count++;
- }
- break;
- }
- if(count >= 240)
- return 0;
- else
- return 1;
- }
复制代码 以上是初始化的,GPIO的输出模式是PP推挽,GPIO的输入模式是IPU上拉输入;
求大神指点一二啊
单片机是STM32F103ZET的,现在经过修改后,能读出数据,但是高八位要么全0,要么全1;低八位总是全0。而且18b20复位完成后,不发送任何指令,直接读数据口,读出来的有时是1,有时是0。根据时序图,复位完成后,数据口应该是一直高电平才对。
完整的程序如下:
- #include "stm32_18b20.h"
- void ds18b20_Config(void)
- {
- unsigned char Init_Flag;
- Init_Flag = ds18b20_Reset();
- if(Init_Flag)
- printf("\r\n 1 \r\n");//复位成功
- else
- {
- printf("\r\n -1 \r\n");//复位失败
- while(1);
- }
- }
- void ds18b20_WriteCmd(uint8_t cmd)
- {
- uint8_t i, ch;
- GPIO_Out_Config();
- for(i = 0; i < 8; i++)
- {
- ch = cmd;
- ch = ch & 0x01;
- cmd = cmd >> 1;
-
- DQ_L;
- Delay_us(15);//起始15us低电平
- if(ch)//写入1
- {
- DQ_H;
- NOP();NOP();NOP();NOP();NOP();
- DQ_L;
- Delay_us(65);
- }
- else//写入0
- {
- DQ_L;
- Delay_us(65);
- DQ_H;
- NOP();NOP();NOP();NOP();NOP();
- }
- }
- }
- uint8_t ds18b20_ReadData(void)
- {
- uint8_t i,s = 0, dat = 0, data = 0;
- ds18b20_Config();
- for(i = 0; i < 8; i++)
- {
- data = data >> 1;
- DQ_L;
- NOP();
- DQ_H;
- Delay_us(12);//放开总线
- s = DQ_Read;
- if(s)
- dat = 1;
- else
- dat = 0;
- Delay_us(45);
- s = 0;
- data = data | (dat << 7);
- }
- return data;
- }
- char ds18b20_Reset(void)
- {
- uint8_t count = 0,i = 0;
- GPIO_Out_Config();
- DQ_L;
- Delay_us(480);//复位信号
- DQ_H;
- Delay_us(15);//释放总线
- while(count < 100)
- {
- i = DQ_Read;
- if(i == 1)
- {
- Delay_us(1);
- count++;
- }
- else
- break;
- }
- if(count >= 100)
- return 0;
- else
- count = 0;
- while(count <240)
- {
- i = DQ_Read;
- if(i ==0)
- {
- Delay_us(1);
- count++;
- }
- break;
- }
-
- if(count >= 240)
- return 0;
- else
- {
- Delay_us(750);
- i = DQ_Read;
- printf("\r\n i = %d\r\n ",i);
- return 1;
- }
- }
- void ds18b20_TransCmd(void)
- {
- ds18b20_Config();
- ds18b20_WriteCmd(0xcc);//1100 1100
- ds18b20_WriteCmd(0x44);//0100 0100
- }
- void ds18b20_ReadCmd(void)
- {
- ds18b20_Config();
- ds18b20_WriteCmd(0xcc);//1100 1100
- ds18b20_WriteCmd(0xbe);//1011 1110
- }
- float ds18b20_GetTemp(void)
- {
- uint8_t tempH = 0, tempL = 0, temp = 0;
- float tem = 0;
- ds18b20_TransCmd();
- Delay_ms(1000);
-
- ds18b20_ReadCmd();
- tempL = ds18b20_ReadData();
- tempH = ds18b20_ReadData();
- // printf("\r\n 0x%d \r\n", tempH);
- // printf("\r\n 0x%d \r\n", tempL);
-
- temp = (tempH << 8) + tempL;
- tem =temp * 0.0625;
- printf("\r\n tem %f \r\n", tem);
- return tem;
- }
- void NOP(void)
- {
- uint8_t i = 1;
- i--;
- }
复制代码 用示波器看过延时程序的实现是正确的。复位函数里的复位信号给的也是正确的。
电路图里左边是电源线,中间是数据线,右边是地线
|
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分
评分
查看全部评分