- 打卡等级:初来乍到
- 打卡总天数:8
- 最近打卡:2026-04-29 09:54:19
注册会员
- 积分
- 189
|
请问那位有读取多路18b20 id程序,自己查资料弄了,读出不出来,也不知那不对
sbit DQ = P7^3; //DS18B20的数据口
u8 MinusFlag; //负数标志,0:正数,1:负数
unsigned char DS18B20_ID[MaxSensorNum][8]; // 存检测到的传感器DS18B20_ID的数组,前面的维数代表单根线传感器数量上限
unsigned char DS18B20_SensorNum; // 检测到的传感器数量(从1开始,例如显示1代表1个,8代表8个)
/**************************************
复位DS18B20,并检测设备是否存在
**************************************/
void DS18B20_Reset()
{
DQ = 0; //送出低电平复位信号
delay_us(480); //延时至少480us
DQ = 1; //释放数据线
delay_us(15);
}
/**************************************
从DS18B20读1字节数据
**************************************/
u8 DS18B20_ReadByte()
{
u8 i;
u8 dat = 0;
for (i=0; i<8; i++) //8位计数器
{
dat >>= 1;
DQ = 0; //开始时间片
delay_us(1); //延时等待
DQ = 1; //准备接收
delay_us(1); //接收延时
if (DQ) dat |= 0x80; //读取数据
delay_us(60); //等待时间片结束
}
return dat;
}
/**************************************
向DS18B20写1字节数据
**************************************/
void DS18B20_WriteByte(u8 dat)
{
u8 j;
u8 testb;
for (j = 1; j <= 8; j++)
{
testb = dat & 0x01;
dat = dat >> 1;
if (testb)
{
DQ=0;// 写1
delay_us(10);
DQ=1;
delay_us(50);
}
else
{
DQ=0;// 写0
delay_us(60);
DQ=1;// 释放总线
delay_us(2);
}
}
}
// 检测从机给主机返回的应答脉冲。从机接收到主机的复位信号后,会在15~60us后给主机发一个应答脉冲
u8 DS18B20_Answer_Check(void)
{
u8 delay=0;
// 等待应答脉冲(一个60~240us的低电平信号 )的到来
// 如果100us内,没有应答脉冲,退出函数,注意:从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
while (DQ&&delay <100)
{
delay++;
delay_us(1);
}
// 经过100us后如果没有应答脉冲;退出函数
if (delay>=100)//Hu200
return 1;
else
delay=0;
// 有应答脉冲且存在时间不超过240us
while (!DQ&&delay<240)
{
delay++;
delay_us(1);
}
if (delay>=240)
return 1;
return 0;
}
u8 DS18B20_INit()
{
DS18B20_Reset();
return DS18B20_Answer_Check();
}
/*void ds18b20_rom()
{
int j;
DS18B20_Reset(); //设备复位
DS18B20_WriteByte(0x33); //发送读序列号命令
for(j=0;j<8;j++)
FAC_DATA_Table.ds18b20_rom_buf[0][j]=DS18B20_ReadByte();
}*/
// 从DS18B20读取2个位
u8 DS18B20_Read_2Bit(void)//读二位 子程序
{
u8 i;
u8 dat = 0;
for (i = 2; i > 0; i--)
{
dat = dat << 1;
DQ=0;
delay_us(2);
DQ=1;
delay_us(12);
if (DQ) dat |= 0x01;
delay_us(50);
}
return dat;
}
// 写1位到DS18B20
void DS18B20_Write_Bit(u8 dat)
{
DQ=0;
delay_us(1);
if(dat & 0x01)DQ=1;
else DQ=0;
delay_us(60);
DQ=1;
delay_us(1);
}
// 自动搜索ROM
u8 DS18B20_Search_Rom()
{
u8 k, l, chongtuwei, m, n, num;
u8 zhan[5];
u8 ss[64];
u8 tempp;
l = 0;
num = 0;
do
{
DS18B20_Reset(); //注意:复位的延时不够
delay_us(480); //480、720
DS18B20_WriteByte(0xf0);
for (m = 0; m < 8; m++)
{
u8 s = 0;
for (n = 0; n < 8; n++)
{
k = DS18B20_Read_2Bit();//读两位数据
k = k & 0x03;
s >>= 1;
if (k == 0x01)//01读到的数据为0 写0 此位为0的器件响应
{
DS18B20_Write_Bit(0);
ss[(m * 8 + n)] = 0;
}
else if (k == 0x02)//读到的数据为1 写1 此位为1的器件响应
{
s = s | 0x80;
DS18B20_Write_Bit(1);
ss[(m * 8 + n)] = 1;
}
else if (k == 0x00)//读到的数据为00 有冲突位 判断冲突位
{
//如果冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1
chongtuwei = m * 8 + n + 1;
if (chongtuwei > zhan[l])
{
DS18B20_Write_Bit(0);
ss[(m * 8 + n)] = 0;
zhan[++l] = chongtuwei;
}
else if (chongtuwei < zhan[l])
{
s = s | ((ss[(m * 8 + n)] & 0x01) << 7);
DS18B20_Write_Bit(ss[(m * 8 + n)]);
}
else if (chongtuwei == zhan[l])
{
s = s | 0x80;
DS18B20_Write_Bit(1);
ss[(m * 8 + n)] = 1;
l = l - 1;
}
}
else
{
return 5;//没有搜索到
}
}
tempp = s;
DS18B20_ID[num][m] = tempp; // 保存搜索到的ID
}
num = num + 1;// 保存搜索到的个数
} while (zhan[l] != 0 && (num < MaxSensorNum));
DS18B20_SensorNum=num;
return num;
}
//========================================================================
// 函数: u16 ReadTemperature()
// 描述: 读取温度函数。
// 参数: none..
// 返回: 温度值.
// 版本: VER1.0
// 日期: 2020-7-30
// 备注:
//========================================================================
float ReadTemperature(u8 chi)
{ u8 i;
u16 TempH, TempL, Temperature;
DS18B20_Reset(); //设备复位
DS18B20_Answer_Check();
DS18B20_WriteByte(0xcc); //跳过ROM命令
DS18B20_WriteByte(0x44); //开始转换命令
//while (!DQ); //等待转换完成
DS18B20_Reset(); //设备复位
DS18B20_Answer_Check();
//DS18B20_WriteByte(0xCC); //跳过ROM命令
DS18B20_WriteByte(0x55); //pi
for(i=0;i<8;i++)
DS18B20_WriteByte(FAC_DATA_Table.ds18b20_rom_buf[chi]); //读暂存存储器命令
DS18B20_WriteByte(0xBE); //读暂存存储器命令
TempL = DS18B20_ReadByte(); //读温度低字节
TempH = DS18B20_ReadByte(); //读温度高字节
if(TempH & 0xf8) //判断是否位负数
{
MinusFlag = 1; //设置负数标志
Temperature = (TempH<<8) | TempL;
Temperature = ~Temperature + 1;
Temperature *= 0.625 / 100.0f * (float)FAC_DATA_Table.Adjust_s.Temp; //0.0625 * 10,保留1位小数点
}
else
{
MinusFlag = 0; //清除负数标志
Temperature = (((TempH<<8) | TempL) * 0.625); //0.0625 * 10,保留1位小数点
}
return Temperature;
}
void main(void)
{
u8 i,j;
IO_INIT();
EG1163S_OFF=0;
OFFON=0;
IRON = 0;//T12控制
//P5n_push_pull(0x04); //P5.2 设置为推挽输出
I2C_INIT();
ADC_config();
DMA_ADC_Config();
EA = 1; //打开总中断
LCM_Config(); //LCM初始化
DMA_Config(); //LCM_DMA初始化, 使用DMA方式显示下面的字符串.
ST7735_init();
LCD_Display_Dir(2); //屏幕方向
display();
UartInit();
PID_nitialization();
PWMA_config();
PWMB_config();
BEEP=0;
UpdatePwm_CC(min2);
MCP4725_Write_VCC(0);
user_menu_init();
while(DS18B20_INit())
{
printf("DS18B20 cheak failed!\r\n");
}
printf("DS18B20 read!\r\n");
DS18B20_Search_Rom();
printf("DS18B20_SensorNum:%d\r\n",DS18B20_SensorNum);
for(i=0;i<DS18B20_SensorNum;i++)
{
for(j=0;j<8;j++)
printf("0x%02x,",DS18B20_ID[j]); //串口打印
printf("\r\n");
}
// RSTFLAG |= 0x04; //设置看门狗复位需要检测P3.2的状态,否则看门狗复位后进入USB下载模式
while (1)
{
if( EG1163S_OFF==1)
CV_DAC=PID_Compute((float)min1,(float)OUT_VCC*100);
else
{
CV_DAC=0;
MCP4725_Write_VCC(0);
}
//UpdatePwm_CV(min1);
MCP4725_Write_VCC(CV_DAC);
UpdatePwm_CC(min2);
UpdatePwm_PID(1500);
}
}
这个程序,挂载了3个18b20,有时候能正确读出来1个id,有时候一个都不行,要么就是读出来的id是错误的,自己用0x33一个一个读出id后,可以正确读出各路的温度,就一次型读取多路id不行,求大佬帮忙看看,多谢了
|
|