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

📄 1wire.c

📁 我编写的多通道利用DB18B20监测温度的AVR子程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*总线示意图:*/
//    -------------------                 VCC
//   |      ATMEGA16     |                 |
//   |                   |                R=1K
//   |                   |                 |
//   |      pullup+busin |-------R=100------------BUS----->
//   |                   |                 |
//   |                   |               R=22
//   |                   |                 |
//   |         pulldown  |---斜率控制-----K
//   |                   |                 |
//    -------------------                 GND
/*DS18B20寄存器示意表*/
//byte0		temperature LSB;
//byte1		temperature MSB;		EEPROM
//byte2*	TH reg;				<->TH reg;
//byte3*	TL reg;				<->TL reg;
//byte4*	CONFIG;				<->CONFIG;
//byte5		reserve;
//byte6		reserve;
//byte7		reserve;
//byte8*	CRC;
#include <iom16v.h>
#include <macros.h>
#ifndef uchar
#define uchar unsigned char
#define uint unsigned int
#endif
//管脚定义:
#define on_led_on		PORTB&=~(1<<6)
#define on_led_off		PORTB|=(1<<6)
#define err_led_on		PORTB&=~(1<<7)
#ifndef busin
#define busin			DDRA							//定义1-8管脚方向:输入数据值;输出强上拉
#define busup			PORTA							//定义上拉管脚值:赋为1,使其具有强上拉的作用
#define busindata		(PINA&setdata)					//数据输入脚的值:if=00,data=0;else data=1.
#define busdown			PORTC							//数据下拉管脚值。
#define rs485rx;	PORTD |=(1<<2);						//接收数据:1:485(0)
#define rs485tx;	PORTD &=~(1<<2);					//发送数据
#endif
//总线赋值:
#define bus0;	busdown = setdata;						//下拉总线:=0;
#define bus1;	busdown =0x00;/*&= clrdata;*/			//释放总线:=1;(1k上拉)
#define buspullup;	
//bus1;busin=setdata;busup=0XFF;asm(" nop");asm(" nop");asm(" nop");asm(" nop");busin=0x00;/*&=clrdata;*/	//动态上拉总线0.5ms:=1;(动态上拉+1k上拉)
//延时时间定义:
#define delay1us();		delayhalfus(1);
#define delay2us();		delayhalfus(2);					//1.5us
#define delay3us();		delayhalfus(3);					//2us
#define delay5us();		delayhalfus(9);					//5us
#define delay7us();		delayhalfus(12);				//6.5us
#define delay8us();		delayhalfus(16);				//8.5us
//#define delay10us();	delayhalfus(19);				//10us
#define delay13us();	delayhalfus(25);				//13.5us
#define delay15us();	delayhalfus(29);				//15us
#define delay37us();	delayhalfus(73);				//37us
#define delay45us();	delayhalfus(89);
#define delay47us();	delayhalfus(93);
#define delay60us();	delayhalfus(119);
//#define delay80us();	delayhalfus(159);
#define delay120us();	delayhalfus(239);
#define delay380us();	delayhalfus(199);delayhalfus(199);delayhalfus(159);
//#define delay400us();	delayhalfus(199);delayhalfus(199);delayhalfus(199);
#define delay500us();	delayhalfus(249);delayhalfus(249);delayhalfus(249);delayhalfus(249);
//
void search_8bus(void);									//搜索全部(8个)通道子程序
void search_8ic(void);									//搜索单通道子程序(最多搜索8个节点)
uchar search_ic(void);									//搜寻器件注册码
void ini_allbus(void);									//初始化所有通道
void ini_wire(void);									//初始化通道上所有传感器
uchar ini_ic(uchar);									//传感器初始化
void syscyc(void);										//所有通道循环温度转换
void start_tempad(uchar);								//广播启动温度转换
void return_alldata(void);								//返回通道所有ic温度数据
void return_data(uchar);								//返回数据
void onewire_writerom(uchar);							//匹配64bit rom 注册码
void onewire_reset(void);								//总线复位
void onewire_write(uchar);								//写1字节
uchar onewire_read(void);								//读1字节
void onewire_wbit(uchar);								//写单位
uchar onewire_rbit(void);								//读单位
uchar onewire_randc(void);								//
void delayhalfus(uchar);								//延时程序(n+1)/2us
extern delay256us(uchar);
extern void eeprom_rd_add(void);

const uchar crctable[] = {
	0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
	157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
	35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
	190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
	70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
	219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
	101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
	248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
	140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
	17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
	175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
	50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
	202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
	87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
	233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
	116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
const uchar set[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
const uchar clr[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
extern const uchar led_ddr[8];
extern const uchar led_portb[8];

uchar allbus_ic_id[8][8][8];							//8个通道
uchar icnum[8] = {0,0,0,0,0,0,0,0};						//查询到的第几个ic,也可以得到通道的节点数。
uchar t_data[8][16];									//温度数据
uchar haveic;											//总线有设备
uchar bus_num;											//总线通道循环计数
uchar setdata,clrdata;									//已知通道,对bus的操作。
uchar lastadd;											//上次查询差异位的位计数
extern uchar setup;										//通讯setup_sign
extern uchar duanlu[8];									//短路状态:正常aa;VCC短路50;GND短路05.
extern uchar dianlu[8];								//电路计数器。
extern uchar onoff;										//关机
extern uchar add_change;
/*******************************************************
搜索全部(8个)通道子程序:
串口通道发送:通道号;子程序发送所有搜索号;0XFF
********************************************************/
void search_8bus(void)
{
	for(bus_num=0;bus_num<8;bus_num++)
	{
		DDRB=led_ddr[bus_num];							//控制led
		PORTB&=led_portb[bus_num];						//控制led
		setdata = set[bus_num];
		clrdata = clr[bus_num];
		search_8ic();									//搜索指定(通过全局变量bus_num)通道子程序。
		////eeprom work;
		DDRB=0xf0;PORTB|=0x0f;							//控制led
	}
}
/*******************************************************
搜索单通道子程序(最多搜索8个节点):串口发送所有搜索号
无设备返回05;搜索失败返回15;crc校验失败返回25;字节无效返回35;通道ic过多返回45。
********************************************************/
void search_8ic(void)
{
	uchar jb1,jb2,jb3,jb4;								//局变
	lastadd = 0;									//上次查询差异位的位计数!!
	icnum[bus_num]= 0;
	for(jb1=0;jb1<8;jb1++)
	{
		jb2 = search_ic();
		if(jb2 == 0xff)
		{
			icnum[bus_num]++;
			break;
		}
		else if(jb2 == 0x05)
		{/*UDR = 0x05;out485();*/}
		else if(jb2 == 0x15)
		{/*UDR = 0x15;out485();*/}
		else if(jb2 == 0x25)
		{/*UDR = 0x25;out485();*/}
		else if(jb2 != 0x00)
		{/*UDR = 0x35;out485();*/}						//返回字节无效
		else
		{
//			for(jb3=0;jb3<8;jb3++)
//			{
//				jb4 = allbus_ic_id[bus_num][icnum[bus_num]][jb3];
//				UDR = jb4;	out485();				//返回id数据
//			}
			icnum[bus_num]++;
			if(jb1==7)
			{
				//UDR = 0x45;	out485();				//通道ic过多
			}
		}
	}
}
/*********************************************
从总线上搜寻器件(DS18B20)注册码:
正常时返回00,搜索已完返回ff;无设备返回05;搜索失败返回15;crc校验失败返回25。
*********************************************/ 	
uchar search_ic(void)
{
	uchar jb_bit_num;									//位计数
	uchar change_bit;									//选择的路径(0/1)
	uchar last;											//差异位的位计数(记录下该值,判断下一个ic的id)
	uchar jb1,jb2;										//局变
	uchar bita,bitb;									//位与位补码
	uchar jbcrc,crc8;
	last = 0x00;
	onewire_reset();									//复位;
	if(haveic == 0){return 0x05;}						//返回无设备
	onewire_write(0xf0);								//搜寻指令
	for(jb_bit_num=1;jb_bit_num<=64;jb_bit_num++)
	{
		bita = onewire_rbit();
		bitb = onewire_rbit();
		if((bita==1)&&(bitb==1))
		{return 0x15;}									//返回搜索失败
		else
		{                               
			if(bita!=bitb)
			{
				change_bit = bita;
			}
			else 
			{
				if(jb_bit_num == lastadd)				//bita=bitb=0;
				{
					change_bit = 1;
				}
				else if(jb_bit_num > lastadd)
				{
					change_bit = 0;
				}
				else									//jb_bit_num < last
				{
					jb1 = (jb_bit_num-1)/8;
					jb2 = (jb_bit_num-1)%8;
					change_bit = allbus_ic_id[bus_num][(icnum[bus_num]-1)][jb1]&set[jb2];
				}
				if(change_bit == 0)
				{
					last = jb_bit_num;
				}
			}
			jb1 = (jb_bit_num-1)/8;
			jb2 = (jb_bit_num-1)%8;
			if(change_bit == 0)
			{allbus_ic_id[bus_num][icnum[bus_num]][jb1] &= clr[jb2];}
			else
			{allbus_ic_id[bus_num][icnum[bus_num]][jb1] |= set[jb2];}
			onewire_wbit(change_bit);
		}
	}
	crc8=0x00;
	for(jbcrc=0;jbcrc<8;jbcrc++)						//crc校验
	{
		jb1 = allbus_ic_id[bus_num][icnum[bus_num]][jbcrc];
		jb1 ^= crc8;
		crc8 = crctable[jb1];
	}
	if(crc8 != 0x00)
	{
		return 0x25;									//crc校验失败
	}
	if(last == 0)
	{
		return 0xff;									//返回搜索完毕;
	}
	lastadd = last;
	return 0x00;										//正常返回
}
/*********************************************************
初始化所有通道上传感器
************************************************************/
void ini_allbus(void)
{
	for(bus_num=0;bus_num<8;bus_num++)
	{
		//UDR = bus_num;	out485();
		setdata = set[bus_num];
		clrdata = clr[bus_num];
		ini_wire();
		//UDR = 0xff;	out485();
	}
}
/*********************************************************
初始化通道上所有传感器
正常时返回00;无设备返回04;配置失败返回24;crc校验失败返回14,94;
超时溢出返回34;pipei失败返回0x84;寄生供电返回0x44;字节无效返回0x54。
************************************************************/
void ini_wire(void)
{
	uchar jb_ic_num;									//通道ic计数器
	uchar jb1;
	for(jb_ic_num=0;jb_ic_num<icnum[bus_num];jb_ic_num++)
	{
		jb1 = ini_ic(jb_ic_num);
		if(jb1 == 0x04){/*//UDR = 0x04;out485();*/}		//返回无设备
		else if(jb1==0x14)
		{/*//UDR = 0x14;out485();*/}					//返回crc校验失败
		else if(jb1==0x24)
		{/*//UDR = 0x24;out485();*/}					//配置失败
		else if(jb1==0x94)
		{/*//UDR = 0x94;out485();*/}					//返回crc校验失败
		else if(jb1==0x34)
		{/*//UDR = 0x34;out485();*/}					//返回超时溢出。
		else if(jb1==0x84)
		{/*//UDR = 0x84;out485();*/}					//pipei失败
		else if(jb1==0x44)
		{/*//UDR = 0x44;out485();*/}					//返回寄生供电!
		else if(jb1!=0x00)
		{/*//UDR = 0x54;out485();*/}					//返回字节无效
	}
}
/*********************************************************
初始化温度传感器
正常时返回00;无设备返回04;配置失败返回24;crc校验失败返回14,94;
超时溢出返回34;pipei失败返回0x84;寄生供电返回0x44;字节无效返回0x54。
*********************************************************/
uchar ini_ic(uchar num)
{
	uchar tem_datal,tem_datah;							//
	uchar crc8,config;									//
	uchar jb1,jb2,jb3;
	onewire_reset();									//复位;
	if(haveic == 0){return 0x04;}						//返回无设备
	onewire_write(0x55);								//匹配rom
	onewire_writerom(num);
//	{return 0x84;}										//匹配64bit rom 注册码
	onewire_write(0xbe);								//读暂存器9字节
	crc8 = 0x00;
	for(jb1=0;jb1<9;jb1++)
	{
		jb2 = onewire_read();
		crc8 = crctable[crc8^jb2];				
		//UDR = jb2;out485();
		if(jb1==2){tem_datal = jb2;}					//温度低报警值
		else if(jb1==3){tem_datah = jb2;}				//温度高报警值
		else if(jb1==4){config = jb2;}					//配置字节
	}
	if(crc8 != 0){return 0x94;}							//返回crc校验失败
	if(config!=0x7f&&tem_datal!=0x00&&tem_datal!=0x00)	//配置错误,温度报警设置错误
	{
		//写暂存器3字节
		onewire_reset();								//复位;
		if(haveic == 0){return 0x04;}					//返回无设备
		onewire_write(0x55);							//匹配rom
		onewire_writerom(num);							//匹配64bit rom 注册码
		onewire_write(0x4e);							//写暂存器3字节
		onewire_write(0x00);
		onewire_write(0x00);
		onewire_write(0x7f);
		//复制暂存器至eeprom3字节
		onewire_reset();								//复位;
		if(haveic == 0){return 0x04;}					//返回无设备
		onewire_write(0x55);							//匹配rom
		onewire_writerom(num);							//匹配64bit rom 注册码
		onewire_write(0x48);							//复制暂存器3字节
		onewire_write(0x00);
		onewire_write(0x00);
		onewire_write(0xff);
		//eeprom回读暂存器
		onewire_reset();								//复位;
		if(haveic == 0){return 0x04;}					//返回无设备
		onewire_write(0x55);							//匹配rom
		onewire_writerom(num);							//匹配64bit rom 注册码
		onewire_write(0xb8);							//eeprom回读暂存器
		for(jb3=0;;jb3++)
		{
			if(busindata!=0){break;}					//回读完毕。
			if(jb3>250){return 0x34;}					//返回超时溢出。
		}
		//
		onewire_reset();								//复位;
		if(haveic == 0){return 0x04;}					//返回无设备
		onewire_write(0x55);							//匹配rom
		onewire_writerom(num);							//匹配64bit rom 注册码
		onewire_write(0xbe);							//读暂存器9字节
		crc8 = 0x00;
		for(jb1=0;jb1<9;jb1++)
		{
			jb2 = onewire_read();
			crc8 = crctable[crc8^jb2];				
			if(jb1==2){tem_datal = jb2;}				//温度低报警值
			else if(jb1==3){tem_datah = jb2;}			//温度高报警值
			else if(jb1==4){config = jb2;}				//配置字节

⌨️ 快捷键说明

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