最近调试 ds2433 芯片,由于第一次接触1-wire总线,遇到了许多问题,但相关 ds2433中文资料 并不多,故作笔记总结,方便你我他。
调试环境:keil5
硬件环境:stm32F103C8T6 + ds2433
引脚分配:
stm32<--->ds2433
PB11<--->data
GND<--->GND
DS2433主要特性
4096位(512字节)EEPROM。
唯一的64位注册号。
1-wire总线通信。
先看主函数:
程序结构比较简单,初始化各个模块后,写入一组随机数值到ds2433,再从ds2433中读出全部数据。当串口接收到任意字符后,通过串口将读取到的数据发送到上位机串口助手上。
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级
uart_init(115200); //串口初始化为 115200
while(DS2433_Init()) { read_2433(RomCode); }
for( i=0;i<512;i++) pagedata[i] =rand()%256;
write_test(pagedata,Oid);//将pagedata写入ds2433.
read_2433(RomCode);//读取注册码
for( i=0;i<512;i++) read_test[i] = 0x00;//将读缓存数据初始化0x00
read_2433_alldata(read_test); //可以读取512个完整数据
read_2433(RomCode);
while(1)
{
uart_recv(buf,len);
if(len!=0)
uart_send(read_test,512);
}
}
ds2433初始化
//初始化DS2433的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
u8 DS2433_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PORTB口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PORTB.15 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_11); //输出1
DS2433_Rst();//复位
return DS2433_Check();
}
ds2433复位
//复位DS2433
void DS2433_Rst(void)
{
DS2433_IO_OUT(); //SET PG11 OUTPUT
DS2433_DQ_OUT=0; //拉低DQ
delay_us(750); //拉低750us
DS2433_DQ_OUT=1; //DQ=1
delay_us(15); //15US
}
等待ds2433响应
//等待DS2433的回应
//返回1:未检测到DS2433的存在
//返回0:存在
u8 DS2433_Check(void)
{
u8 retry=0;
DS2433_IO_IN(); //SET PG11 INPUT
while (DS2433_DQ_IN&&retry<200)
{
retry++;
delay_us(1);
};
if(retry>=200)return 1;
else retry=0;
while (!DS2433_DQ_IN&&retry<240)
{
retry++;
delay_us(1);
};
if(retry>=240)return 1;
return 0;
}
ds2433复位及在线监测
int OWTouchReset(void)
{
int result;
DS2433_Rst();//复位
result=DS2433_Check();
return result;
}
1-wire写1byte数据
// Write 1-Wire data byte
void OWWriteByte(int data)
{
int loop;
// Loop to write each bit in the byte, LS-bit first
for (loop = 0; loop < 8; loop++)
{
OWWriteBit(data & 0x01);
// shift the data byte for the next bit
data >>= 1;
}
}
1-wire总线写1比特数据
// Send a 1-Wire write bit. Provide 10us recovery time.
//
void OWWriteBit(int bit)
{
DS2433_IO_OUT(); //SET PG11 OUTPUT
if (bit)
{
// Write '1' bit
GPIO_ResetBits(GPIOB,GPIO_Pin_11);// Drives DQ low
delay_us(6);
GPIO_SetBits(GPIOB, GPIO_Pin_11);// Releases the bus
delay_us(60); // Complete the time slot and 10us recovery
}
else
{
// Write '0' bit
GPIO_ResetBits(GPIOB,GPIO_Pin_11);// Drives DQ low
delay_us(60);
GPIO_SetBits(GPIOB, GPIO_Pin_11);// Releases the bus
delay_us(10);
}
}
1-wire读取一字节数据
// Read 1-Wire data byte and return it
//
int OWReadByte(void)
{
int loop, result=0;
for (loop = 0; loop < 8; loop++)
{
// shift the result to get it ready for the next bit
result >>= 1;
// if result is one, then set MS bit
if (OWReadBit())
result |= 0x80;
}
return result;
}
1-wire读取1比特数据
// Read a bit from the 1-Wire bus and return it. Provide 10us recovery time.
//
int OWReadBit(void)
{
int result;
DS2433_IO_OUT(); //SET PG11 OUTPUT
GPIO_ResetBits(GPIOB,GPIO_Pin_11);// Drives DQ low
delay_us(6);
GPIO_SetBits(GPIOB, GPIO_Pin_11);// Releases the bus
delay_us(9);
DS2433_IO_IN(); //SET PG11 INPUT
result = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)& 0x01;// Sample the bit value from the slave
delay_us(55); // Complete the time slot and 10us recovery
return result;
}
读取ds2433中全部数据
void read_2433_alldata(u8 *page_data) //所有存储空间512字节全部读出
{
u16 page=0;
u8 i,j;
for(page=0;page<64;page++)
{
// select the device
if (OWTouchReset()) // Reset the 1-Wire bus
{
return ; // Return if no devices found
}
OWWriteByte(0xCC); // Send Skip ROM command to select single device
OWWriteByte(0xf0); // Read Authentication command
OWWriteByte(((page << 3)) & 0xFF); //TA1地址低8位,左移位数与每次读取长度相关
OWWriteByte(page>>5); // TA2 地址高八位
for (i = 0; i < 8; i++) //每起始地址,连续读8字节
page_data[page*8+i] = OWReadByte();
if (OWTouchReset()) // Reset the 1-Wire bus
{
return ; // Return if no devices found
}
}
向ds2433中写入512字节数据
void write_test(unsigned char *page_data,u8 *Oid)
{
int i,page,j;
unsigned char TA1,TA2,E_S;
for(j=0;j<64;j++)
{
if(OWTouchReset()) // Reset the 1-Wire bus
{
return ; // Return if no devices found
}
OWWriteByte(0xCC); // Send Skip ROM command to select single device
OWWriteByte(0x0F); // Read Authentication command
OWWriteByte((j<<3)&0xFF); //TA1
OWWriteByte((j>>5)&0xFF); //TA2
for (i = 0; i < 8; i++)
{
OWWriteByte(page_data[j*8+i]);
}
// select the device
if (OWTouchReset()) // Reset the 1-Wire bus
{
return; // Return if no devices found
}
OWWriteByte(0xCC); // Send Skip ROM command to select single device
OWWriteByte(0xAA);
TA1 = OWReadByte();
TA2 = OWReadByte();
E_S = OWReadByte();
delay_us(10);
for(i=0;i<8;i++)
{
Oid[i]=OWReadByte();
}
// select the device
if (OWTouchReset()) // Reset the 1-Wire bus
{
return; // Return if no devices found
}
OWWriteByte(0xCC); // Send Skip ROM command to select single device
OWWriteByte(0x55); // Read Authentication command
OWWriteByte(TA1 & 0xFF );
OWWriteByte(TA2); // TA2
OWWriteByte(E_S);
delay_us(5000);
// select the device
if (OWTouchReset()) // Reset the 1-Wire bus
{
return; // Return if no devices found
}
}
}
读DS2433注册码
//read 2433 product code
u8 read_2433(u8 *RomCode)
{
int i;
// select the device
if (OWTouchReset()) // Reset the 1-Wire bus
return 0; // Return if no devices found
OWWriteByte(0x33); // Send Read ROM command to select single device
// read the page data
delay_us(60);
for (i = 0; i < 8; i++)
RomCode[i] = OWReadByte();
if ( dscrcCheck(RomCode,8) )
{
return 0;
}
else
{
return 1;
}
}
CRC检查
///CRC check
u8 dscrcCheck(u8* p,u8 len)
{
uint8_t bit0,cbit,i,j,byte,temp;
temp=0;
for(j=0;j<len;j++)
{
byte=p[j];
for(i=0;i<8;i++)
{
cbit = temp & 0x01;
bit0 = byte & 0x01;
temp=temp>>1;
if( (cbit^bit0) ) temp^=0x8c;
byte>>=1;
}
}
return temp;
}
以上即是ds2433的驱动的核心源码,主要依据数据手册相关时序与指令完成。
需要注意的小问题是,手册中关于ds2433的存储地址存在笔误,末page页面地址应为0x01FE-0x01FF,而文档中为0x1FE0-0x01FF。
在调试成功后发现其实很简单,但在调试时遇到许多坑,但主要集中在对文档的不够熟悉,特别是地址和偏移量的换算。使用随机变量读写ds2433,便于检查写入与读出的数据是否一致,据此判断读取函数是否出现了问题。
详细使用可根据以上驱动函数灵活组合,实现具体应用。
网友评论