📄 1wire.c
字号:
/*总线示意图:*/
// ------------------- 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 + -