⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 1wire.c

📁 我编写的多通道利用DB18B20监测温度的AVR子程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
		}
		if(crc8 != 0){return 0x14;}						//返回crc校验失败
		if((config!=0x7f)&&(tem_datal!=0x00)&&(tem_datal!=0x00))//配置错误,温度报警设置错误
		{return 0x24;}									//配置失败
	}
	//读供电方式
	onewire_reset();									//复位;
	if(haveic == 0){return 0x04;}						//返回无设备
	onewire_write(0x55);								//匹配rom
	onewire_writerom(num);								//匹配64bit rom 注册码
	onewire_write(0xb4);								//读供电方式
	if(onewire_rbit() == 0)
	{return 0x44;}										//返回寄生供电!
	return 0x00;
}
/*********************************************************
所有通道循环温度转换
*********************************************************/
void syscyc(void)
{
	start_tempad(8);									//所有通道广播温度转换(加入短路检测)
	for(bus_num=0;;)
	{
		if(onoff!=0x55)									//不许可?
		{
			onoff=0xaa;
			break;
		}
		WDR();
		if(icnum[bus_num]!=0)							//wire有无器件/有有无短路/无
		{
			setdata = set[bus_num];
			clrdata = clr[bus_num];
			bus1;
			if(duanlu[bus_num]!=0xaa)					//是短路?
			{
				if(busindata==0)						//GND短路?
				{
					dianlu[bus_num]+=3;
					if(dianlu[bus_num]>=(128+30))
					{
						duanlu[bus_num]=0X05;
					}
					delay2us();
				}
				else
				{
					bus0;delay15us();
					if(busindata!=0)					//VCC短路。
					{
						dianlu[bus_num]+=3;
						if(dianlu[bus_num]>=(128+30))
						{
							duanlu[bus_num]=0X50;
						}
					}
					else
					{
						duanlu[bus_num]=0xaa;
						dianlu[bus_num]-=1;
						if(dianlu[bus_num]<=(128-30))
						{
							duanlu[bus_num]=0Xaa;
						}
					}
					buspullup;
				}
			}
			else if(onewire_rbit/*_dl*/() == 1)					//完毕(wait750ms),得到温度数据(加入短路检测)
			{
				return_alldata();
				start_tempad(bus_num);
			}
			//防止溢出:
			if(dianlu[bus_num]>=(128+50)){dianlu[bus_num]=(128+50);}
			if(dianlu[bus_num]<=(128-50)){dianlu[bus_num]=(128-50);}
		}
		bus_num++;
		if(bus_num==8)
		{
			bus_num = 0x00;
		}
		if(setup==0x55){break;}
		if(add_change==0x55){break;}
	}
}
/*********************************************************
广播启动温度转换
*********************************************************/
void start_tempad(uchar num)
{
	if(num==8)
	{
		for(bus_num=0;bus_num<8;bus_num++)
		{
			
			if(icnum[bus_num]!=0)
			{
				setdata = set[bus_num];
				clrdata = clr[bus_num];
				onewire_reset();						//复位;
				if(haveic == 0){break;/*//UDR=0x04;out485();*/}	//返回无设备
				onewire_write(0xcc);					//广播——跳跃rom
				onewire_write(0x44);					//温度转换			
			}
		}
	}
	else if(num<8)
	{
		setdata = set[bus_num];
		clrdata = clr[bus_num];
		onewire_reset();								//复位;
		if(haveic == 0){/*//UDR=0x04;out485();*/}		//返回无设备
		onewire_write(0xcc);							//广播——跳跃rom
		onewire_write(0x44);							//温度转换	
	}
//	else{}												//无效!!
}
/*********************************************************
返回通道所有ic温度数据
*********************************************************/
void return_alldata(void)
{
	uchar jb_ic_num;									//通道ic计数器
	uint jb_temp;
	for(jb_ic_num=0;jb_ic_num<icnum[bus_num];jb_ic_num++)
	{
		DDRB=led_ddr[bus_num];							//控制led
		PORTB&=led_portb[bus_num];						//控制led
		if(onewire_randc()==0X55)						//复位;
		{
			return_data(jb_ic_num);
		}
		DDRB=0xf0;PORTB|=0x0f;							//控制led
	}
}
/*********************************************************
返回温度数据
*********************************************************/
void return_data(uchar num)
{
	uchar tem_datal,tem_datah;
	//if(haveic == 0){return 0x04;}						//返回无设备
	onewire_write(0x55);								//匹配rom
	onewire_writerom(num);								//匹配64bit rom 注册码
	onewire_write(0xbe);								//读暂存器9字节
	tem_datal = onewire_read();
	t_data[bus_num][num*2] = tem_datal;
	tem_datah = onewire_read();
	t_data[bus_num][num*2+1] = tem_datah;
}
/********************************************************
匹配64bit rom 注册码
**********************************************************/
void onewire_writerom(uchar num)
{
	uchar jb_byte_num;									//位计数
	for(jb_byte_num=0;jb_byte_num<8;jb_byte_num++)
	{
		onewire_write(allbus_ic_id[bus_num][(num)][jb_byte_num]);
	}
}
/**************************************************
初始化:根据总线复位,得到总线有无设备(DS18B20)标志haveic;
**************************************************/
void onewire_reset(void)
{
	uchar aaa;
	bus1;
//bus = 0; 480us
	bus0;												//bus = 0;
	delay500us();										//480us
	buspullup;											//bus=1;
//等待bus稳定 nus;
//询问bus上有无设备;从机响应75-300us;本机 480us.
	delay120us();
	aaa=busindata;
	if(aaa == 0)
	{haveic = 1;}										//
	else{haveic = 0;}									//总线无设备
//等待总线恢复空闲并延时;
	delay380us();
}
/**************************************************
初始化+短路检测:本次失败返回0xaa,否则,返回0x55.
**************************************************/
uchar onewire_randc(void)
{
	uchar aaa;
	bus1;
	if(busindata==0)						//GND短路?
	{
		dianlu[bus_num]+=3;
		if(dianlu[bus_num]>=(128+30))
		{
			duanlu[bus_num]=0X05;
		}
		delay2us();
		return 0xaa;
	}
//bus = 0; 480us
	bus0;									//bus = 0;
	delay380us();							//480us
	if(busindata!=0)						//VCC短路。
	{
		dianlu[bus_num]+=3;
		if(dianlu[bus_num]>=(128+30))
		{
			duanlu[bus_num]=0X50;
		}
		return 0xaa;
	}
	else
	{
		duanlu[bus_num]=0xaa;
		dianlu[bus_num]-=1;
		if(dianlu[bus_num]<=(128-30))
		{
			duanlu[bus_num]=0Xaa;
		}
	}
	delay120us();
	buspullup;											//bus=1;
//等待bus稳定 nus;
//询问bus上有无设备;从机响应75-300us;本机 480us.
	delay120us();
	aaa=busindata;
	if(aaa == 0)
	{haveic = 1;}										//
	else{haveic = 0;}									//总线无设备
//等待总线恢复空闲并延时;
	delay380us();
	return ox55;
}
/*********************************************
写1字节(ROM或存贮器命令)到总线(DS18B20)
*********************************************/
void onewire_write(uchar byte)
{
	uchar jb1,jb2;
	bus1;
	for(jb2=0;jb2<=7;jb2++)
	{
		jb1=byte&0x01;
		if(jb1==0x01)
		{
	//严格时序0
	CLI();
	//写1时隙
			bus0;										//输出LOW 15us
			delay13us();
			buspullup;									//释放总线HIGH 47us
	//严格时序1
	SEI();
			delay47us();
		}
		else
		{
	//写0时隙
			bus0;										//输出LOW 60us
			delay60us();
			buspullup;									//释放总线HIGH 1.5us
			delay2us();
		}
		delay3us();										//释放总线HIGH 2us
		byte=byte>>1;
	}
}
/********************************************
写单位
*************************************************/
void onewire_wbit(uchar jbbit)
{
	bus1;
	if(jbbit!=0)
	{
	//严格时序0
	CLI();
	//写1时隙
		bus0;											//输出LOW 15us
		delay15us();
		buspullup;										//释放总线HIGH 47us
	//严格时序1
	SEI();
		delay47us();
	}
	else
	{
	//写0时隙
		bus0;											//输出LOW 60us
		delay60us();
		buspullup;										//释放总线HIGH 1.5us
		delay2us();
	}
	delay3us();										//释放总线HIGH 2us
}
/*********************************************
从总线(DS18B20)上读1字节数据
*********************************************/ 
uchar onewire_read(void)
{
	uchar jb1,byte,aaa;
	byte=0x00;
	bus1;
	for (jb1=0;jb1<=7;jb1++)
	{
		byte=byte>>1;
	//严格时序0
	CLI();
	//读时隙:
		bus0;											//输出LOW 1-2us
		delay2us();										//2us
		buspullup;										//释放总线HIGH 等待10us
		delay7us();
		aaa=busindata;
		if(aaa != 0)
		{byte|=0x80;}
	//严格时序1
	SEI();
		delay15us();
		buspullup;
		delay37us();
		delay3us();	
	}
	return byte;
}
/********************************************
读单位
*********************************************/
uchar onewire_rbit(void)
{
	uchar jbbit;
	bus1;
	//严格时序0
	CLI();
	//读时隙:
	bus0;												//输出LOW 1-2us
	delay3us();											//2us
	buspullup;											//释放总线HIGH 等待10us
	delay7us();
	jbbit = busindata;
	//严格时序1
	SEI();
	delay15us();
	buspullup;
	delay37us();
	delay3us();	
//	bus1;
	if(jbbit == 0x00)
	return 0;
	else return 1;
}
/********************************************************
精准延时0.5us子程序(n+1)*0.5us
(nus*8-1)+9/16=(n+1)*0.5us
8:1t 5t 2t
-1:当为最后一次判断,brne _L2 1t
9:赋值R16 1t rcall 3t nop 1t ret 4t
*********************************************************/
void delayhalfus(uchar nus)
{
	asm("_L2: subi R16,1");  	// 1t
	asm(" nop"); asm(" nop"); asm(" nop"); asm(" nop");
	asm(" nop");				// 5t
	asm(" brne _L2");			// 2t/1t
	WDR();				// 1t
	asm(" ret");				// 4t
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -