51单片机对SPI总线上挂接多个25AA040的读写操作+Proteus仿真

51单片机对SPI总线上挂接多个X5045的读写操作+Proteus仿真


  • Proteus仿真图
    在这里插入图片描述

实例代码

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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//对SPI总线上挂接多个25AA040的读写操作
#include<reg51.h> //包含单片机寄存器的头文件
#include<intrins.h> //包含\_nop\_()函数定义的头文件
sbit SCK=P3^4; //将SCK位定义为P3.4引脚
sbit SI=P3^5; //将SI位定义为P3.5引脚
sbit SO=P3^6; //将SO位定义为P3.6引脚
sbit CS1=P3^7; //将CS定义为P3.7引脚
sbit CS2=P3^3; //将CS1位定义为P3.7引脚
#define WREN 0x06 //写使能锁存器允许
#define WRDI 0x04 //写使能锁存器禁止
#define READ 0x03 //读出
#define WRITE 0x02 //写入
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:延时1ms
(3j+2)\*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:延时若干毫秒
入口参数:n
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void delaynms(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:从X5045的当前地址读出数据
出口参数:x
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
unsigned char ReadCurrent(void)
{
unsigned char i;
unsigned char x=0x00; //储存从X5045中读出的数据
SCK=1; //将SCK置于已知的高电平状态
for(i = 0; i < 8; i++)
{
SCK=1; //拉高SCK
SCK=0; //在SCK的下降沿输出数据
x<<=1; //将x中的各二进位向左移一位,因为首先读出的是字节的最高位数据
x|=(unsigned char)SO; //将SO上的数据通过按位“或“运算存入 x
}
return(x); //将读取的数据返回
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:写数据到X5045的当前地址
入口参数:dat
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void WriteCurrent(unsigned char dat)
{
unsigned char i;
SCK=0; //将SCK置于已知的低电平状态
for(i = 0; i < 8; i++) // 循环移入8个位
{
SI=(bit)(dat&0x80); //通过按位“与”运算将最高位数据送到S
//因为传送时高位在前,低位在后
SCK=0;
SCK=1; //在SCK上升沿写入数据
dat<<=1; //将y中的各二进位向左移一位,因为首先写入的是字节的最高位
}
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:写数据到第一个X5045的指定地址
入口参数:addr
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void WriteSet1(unsigned char dat,unsigned char addr)
{
CS2=1; //使第二个X5045的片选无效
SCK=0; //将SCK置于已知状态
CS1=0; //拉低CS,选中X5045
WriteCurrent(WREN); //写使能锁存器允许
CS1=1; //拉高CS
CS1=0; //重新拉低CS,否则下面的写入指令将被丢弃
WriteCurrent(WRITE); //写入指令
WriteCurrent(addr); //写入指定地址
WriteCurrent(dat); //写入数据
CS1=1; //拉高CS
SCK=0; //将SCK置于已知状态
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:写数据到第二个X5045的指定地址
入口参数:addr
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void WriteSet2(unsigned char dat,unsigned char addr)
{
CS1=1; //使第一个X5045的片选无效
SCK=0; //将SCK置于已知状态
CS2=0; //拉低CS,选中X5045
WriteCurrent(WREN); //写使能锁存器允许
CS2=1; //拉高CS
CS2=0; //重新拉低CS,否则下面的写入指令将被丢弃
WriteCurrent(WRITE); //写入指令
WriteCurrent(addr); //写入指定地址
WriteCurrent(dat); //写入数据
CS2=1; //拉高CS
SCK=0; //将SCK置于已知状态
}

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:从第一个X5045的指定地址读出数据
入口参数:addr
出口参数:dat
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
unsigned char ReadSet1(unsigned char addr)
{
unsigned char dat;
CS2=1; //使第二个X5045的片选无效
SCK=0; //将SCK置于已知状态
CS1=0; //拉低CS,选中X5045
WriteCurrent(READ); //开始读
WriteCurrent(addr); //写入指定地址
dat=ReadCurrent(); //读出数据
CS1=1; //拉高CS
SCK=0; //将SCK置于已知状态
return dat; //返回读出的数据
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:从第二个X5045的指定地址读出数据
入口参数:addr
出口参数:dat
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
unsigned char ReadSet2(unsigned char addr)
{
unsigned char dat;
CS1=1; //使第一个X5045的片选无效
SCK=0; //将SCK置于已知状态
CS2=0; //拉低CS,选中X5045
WriteCurrent(READ); //开始读
WriteCurrent(addr); //写入指定地址
dat=ReadCurrent(); //读出数据
CS2=1; //拉高CS
SCK=0; //将SCK置于已知状态
return dat; //返回读出的数据
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:看门狗复位程序
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void WatchDog1(void)
{
CS1=1; //拉高CS
CS1=0; //CS引脚的一个下降沿复位看门狗定时器
CS1=1; //拉高CS
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:看门狗复位程序
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void WatchDog2(void)
{
CS2=1; //拉高CS
CS2=0; //CS引脚的一个下降沿复位看门狗定时器
CS2=1; //拉高CS
}

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
函数功能:主程序
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void main(void)
{
unsigned char x;
while(1)
{
WriteSet1(0xf0,0x10); //将数据“0xaa”写入第一个X5045的指定地址“0x10”
delaynms(10); //X5045的写入周期为约10ms
x=ReadSet1(0x10); //将数据从第一个X5045中的指定地址读出来
WriteSet2(x,0x20); //将数据x写入第二个X5045的指定地址“0x20
delaynms(10); //X5045的写入周期为约10ms
P1=ReadSet2(0x20); //将数据从第二个X5045中的指定地址读出来,送P1口显示
delaynms(100); //延时100ms
WatchDog1(); //复位第一个X5045的看门狗
WatchDog2(); //复位第二个X5045的看门狗
}
}



程序源码和仿真资源

1
2
3
链接:https://pan.baidu.com/s/17EMkzZEq8RgHeqcwGlO_wQ 
提取码:9q4s