美信DS28E05单总线EEPROM通信方式详解(以STM32F030为例)

概述

DS28E05是一款112字节用户可编程EEPROM芯片,分为7页,每页16字节。存储器页通过保护字节可单独设置为写保护或者EPROM仿真模式。每个器件都带有唯一的64位ROM注册码(ROM ID),由工厂刻入器件。DS28E05通过Maxim Integrated单触点1-Wire®接口高速通信,在多点1-Wire网络中,ROM ID作为节点地址。

关键特性

单触点1-Wire接口

112字节用户EEPROM,具有1K次写循环

用户存储器可编程为写保护以及OTP EPROM仿真模式

唯一、工厂编程的64位ROM ID

与主机通信速率高达76.9kbps (仅高速模式)

工作范围:3.3V ±10%, -40°C至+85°C

IO引脚具有±8kV HBM ESD保护(典型值)

3引脚SOT23和6引脚TSOC封装

应用

配件/PCB识别

消费品的售后管理

模拟感应器校准

医用传感器校准数据存储

通信方式与程序

​ DS28E05是通过单总线协议连接的,根据文档显示,标准的单总线协议是不行的,只能使用快速的单总线协议(Overdrive Speed)才行。

如图为读写周期的时间,最短的读写周期仅有2个微秒,注意读的时候不要超过2个微秒,否则就读不出数据了。

整个周期

复位时序图

复位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/******************************************
1-Wire器件复位, 并检查应答;有应答返回0, 无应答返回1
*******************************************/
unsigned char Reset( void )
{
unsigned char testCount = 50;
GPIO_DS28E05_Out_Mode();
DS28E05_Write_1();
DS28E05_Write_0();
delay_us(60); //复位60us低脉冲保持
DS28E05_Write_1(); //释放总线后9us读应答
GPIO_DS28E05_Input_Mode();
while(testCount--)
{
if( 0 == DS28E05_ReadBit() )
{
delay_us(2);
return 0;
}
}
return 1;
}

写数据时序图

写时序

写数据程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/******************************************
写数据位1
*******************************************/
void WriteBit_1( void )
{
DS28E05_Write_1();
DS28E05_Write_0(); //拉低总线保持1us
delay_us(1);
DS28E05_Write_1(); //释放总线延时大于12us
delay_us(20);//20us
}
/******************************************
写数据位0
*******************************************/
void WriteBit_0( void )
{

DS28E05_Write_1();
DS28E05_Write_0(); //拉低总线保持8-16us
delay_us(12); //9-10us
DS28E05_Write_1(); //释放总线延时6us
delay_us(9);
}

读数据程序

读时序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/******************************************
读数据位
*******************************************/
unsigned char value1;
static unsigned char Read_Bit( void )
{
GPIO_DS28E05_Out_Mode();
DS28E05_Write_1();
DS28E05_Write_0(); //拉低总线保持1us
delay_us(1);
DS28E05_Write_1();
DS28e05_IO_IN();//最重要的一步,一定要用寄存器操作,否则会错过读取的时间,经检测,整个读取周期为2-3微妙
value1 = DS28E05_ReadBit();
delay_us(2);
return value1;
}

写一个字节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/******************************************
写字节
*******************************************/
static void Write_Byte( unsigned char value )
{
unsigned char i;
GPIO_DS28E05_Out_Mode();
for( i = 0; i < 8; i++ )
{
if( value & 0x01 )
{
WriteBit_1();
}
else
{
WriteBit_0();
}
value = value >> 1;
}
}

读一个字节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/******************************************
读字节
*******************************************/
static unsigned char Read_Byte( void )
{
int i, value;
value = 0;
for( i = 0; i < 8; i++ )
{
value >>= 1;
if( Read_Bit() )
value |= 0x80;
}
return value;
}

读写ROM和flash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/******************************************
功能:读8位家族码;48位序列号;8位CRC码;读取成功返回0
参数:*id--读取的数据存放地址
返回:0--操作成功;1--总线不可用;
*******************************************/
unsigned char DS28E05_ReadRom( unsigned char *id )
{
unsigned char i,j;
while(Reset());
Write_Byte( Rom_Read_Cmd ); //写命令
for( i = 0; i < 8; i++ )
{
j= Read_Byte();
*id++ = j;
}
return ( 0 );
}
/******************************************
功能: 读EPROM
参数: tgaddr--目标地址;
len--要读取的字节数;
*buffer--存放地址
返回:0--操作成功;1--总线不可用;
*******************************************/
unsigned char DS28E05_ReadMemory( unsigned char tgaddr, unsigned char len, unsigned char * buffer )
{
unsigned char i;
if( Reset() != 0 )
return ( 1 );
Write_Byte( Rom_Skip_Cmd ); //写命令
Write_Byte( Memory_Read_Cmd ); //写命令
Write_Byte( tgaddr ); //写地址低字节
Write_Byte( 0 ); //写地址高字节
for( i = 0; i < len; i++ )
{
buffer[ i ] = Read_Byte();
}
Reset();
return ( 0 );
}
//写eeprom

int ds28e05WriteMemory(uint8_t address, char *buffer, int length)
{
uint8_t a,b;
uint8_t sf,ef;
uint8_t sb[2]={0};
uint8_t eb[2]={0};
uint8_t spage, epage, npage, wpage;
uint8_t nseg, wseg=0;
uint8_t wBytes=0, rBytes=0, wAddr = 0;

// Calculate pages
spage = ((address & PAGE_MASK) >> 4);
epage = (((address + length) & PAGE_MASK) >> 4);
if (epage == NUM_PAGES) epage = NUM_PAGES - 1;
npage = epage - spage;
printf("spage=%d,epage=%d\n",spage,epage);
printf("npage=%d,length=%d\n",npage,length);
//This memory must be written respecting 16bits boundaries
sf = (address&0x01) != 0;
ef = ((address+length)&0x01) != 0;
printf("sf=%d,ef=%d\n",sf,ef);
if (ef)
{
DS28E05_ReadMemory( address+length,1, &eb[1]);
eb[0] = buffer[length-1];
length++;
}
if (sf)
{
DS28E05_ReadMemory(address-1,1, &sb[0]);
sb[1] = buffer[0];
length++;
address--;
}
// Write pages
for (wpage = 0; wpage <= npage; wpage++)
{
wAddr = address + wBytes;
// Calculate segments to write
if ((length - wBytes) > (BYTES_PER_PAGE))
// Will we pass a page boudary
if (wAddr % (SEG_SIZE * BYTES_PER_SEG) == 0)
nseg = SEG_SIZE;
else
nseg = (BYTES_PER_PAGE - (wAddr % (BYTES_PER_PAGE))) >> 1;
else
nseg = ((length - wBytes) & SEG_MASK) >> 1;

printf("nseg=%d\n",nseg);

if( Reset() != 0 )
return ( 1 );
Write_Byte( Rom_Skip_Cmd );
Write_Byte(DS28E05_WRITE_MEMORY);
Write_Byte(wAddr);
Write_Byte(0xff);
// Write segments within page
for (wseg = 0; wseg < nseg; wseg++)
{
if (sf)
{
Write_Byte(sb[0]);
Write_Byte(sb[1]);
wBytes += 2;
rBytes++;
sf = 0;
}
else if (ef && (length - wBytes) <= 2)
{
Write_Byte(eb[0]);
Write_Byte(eb[1]);
wBytes += 2;
rBytes++;
ef = 0;
}
else
{
Write_Byte(buffer[rBytes]);
Write_Byte(buffer[rBytes+1]);
wBytes += 2;
rBytes += 2;
}

a = Read_Byte();
b = Read_Byte();

printf("Readback: %02x %02x (%c%c)\n", a, b, a, b);

Write_Byte(0xff);

delay_ms(16);

a = Read_Byte();

printf("Verification byte: %02x\n", a);

if(a !=0xAA)
goto error;
}

Reset();;
}

return 1;
error:
Reset();
return 0;
}

详细的程序,请到我的github仓库查找或者关注我的公众号索取。

Daniel wechat
如果有帮助就支持一下我吧,或者关注我一下吧!