一、源代码$ b! D b# ]# O, T) {) t
$ p% [' L; u9 o3 c2 l
- void eeprom_init()* f. e7 C8 q' @( `
- {- ?, }8 m' m4 S# G
- GPIO_InitTypeDef GPIO_InitStructure;
; n, C7 h, ]3 }+ D3 C - SPI_InitTypeDef SPI_InitStructure;1 ^) h0 L: x3 b( o9 k
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 7 J) ?0 [* g0 o7 H6 p* `5 x
8 L+ v v. L' f- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12; // PB12 推挽
( A+ R7 f/ F; f/ S1 W E - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出. p3 u7 O+ d$ ]2 Z/ U C$ @5 K
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;9 L! W6 M2 L! s- r" t( n! c
- GPIO_Init(GPIOB, &GPIO_InitStructure);
7 x# [, c- K& _1 [ - GPIO_SetBits(GPIOB,GPIO_Pin_11|GPIO_Pin_12);# I8 t; b9 v {7 |7 F+ ?
- a' K ?9 j/ x' P8 r- D q- 6 k4 d& a3 l/ {% m' \7 Z
- " w" w0 f0 B6 \$ g" |: h
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 + w ]- h1 @" \# U3 e
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能
& ^- E! C1 m0 _
( |; e E" H8 m* u; m- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
$ g4 [# G, L6 d9 ?5 p u - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出
$ k5 w `/ @7 C# i- a( N - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;' s% Z5 G% R, G3 d1 W
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
7 c$ N; o- f# o - 2 K1 k: I4 j" B2 O2 F6 @
- GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉
^0 I$ R# D+ `$ i5 X5 d
9 i o3 s4 R; [- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工: H U, R0 b+ Z! J
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI5 r0 K8 K w! v% l1 a' o( n
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构- r# ^. l3 ^/ u. G w9 J( Y. l6 P
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
. E8 |8 t9 y& W0 Q% f$ ^ - SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样$ N; v. Z/ [( C. I# c8 ?
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
% |# L5 `1 D9 t$ J+ q - SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
% d. K3 @2 ^' m( L" ]( d - SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始7 L4 r) A7 {; o
- SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
[1 M/ T$ @3 F4 f! }" f - SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
. q8 ]" W7 O0 U) C, {
& G9 Z# P) H( U# _5 Q' k- SPI_Cmd(SPI2, ENABLE); //使能SPI外设
. K9 F- u3 f% ^1 i. ^* G - 3 w( \8 L7 G6 I4 m
- eeprom_read_write_byte(0xff);//启动传输
; A1 `+ \; Q% u - }
3 A; R, _: m9 H% T - //SPI 速度设置函数. D$ p5 H7 L8 c8 _9 b8 o
- //SpeedSet:$ y' `: I: |# P; n0 T& F
- //SPI_BaudRatePrescaler_2 2分频
1 v0 M. x/ T2 w, x3 T% g - //SPI_BaudRatePrescaler_8 8分频 4 l8 O4 \* k {( o( [9 B
- //SPI_BaudRatePrescaler_16 16分频
* E7 A c) a0 C/ O7 a1 G# r - //SPI_BaudRatePrescaler_256 256分频 * \1 v: @! e3 ?; p* ?' _
% H/ E/ T' J$ r: U* T- void eeprom_set_speed(u8 SPI_BaudRatePrescaler)
+ y7 q9 p5 y. c9 H2 U - {
+ Q5 e v% |: |9 o. y. Z6 \' _ V - assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
5 u. \ f/ n. I - SPI2->CR1&=0XFFC7;
" l+ J. R# T' k6 |2 M - SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI2速度
t% ^, P- L9 V" q. e - SPI_Cmd(SPI2,ENABLE);
$ X- Q* y: l# v - 5 D9 Z1 J$ n) B. M5 V, z1 J
- }
复制代码- //SPIx 读写一个字节* a% C: `% b2 S- \' I
- //TxData:要写入的字节 x! Z4 @7 M( j) F
- //返回值:读取到的字节1 {) {* F$ |& j
- u8 eeprom_read_write_byte(u8 TxData)
2 |* Z" y$ @; U8 E7 b4 v( s - {
$ `, y7 l4 T |+ y, s - u8 retry=0; 3 E0 x o ~0 a
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位' S8 l, J `$ v( ?
- {
7 r9 U1 c* T4 l- V( R - retry++;1 M, [. e6 t! P+ }. B9 k8 {
- if(retry>200)return 0;
' T) U; D! c2 i4 m - } ( N; ?& s, B8 ]6 m% w
- SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
4 W7 G; a- x$ T' T) O - retry=0;
4 {5 }9 c, v: |) \7 V9 X - 2 A$ B: H: U9 D6 _. J
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
9 N& a2 k9 b* f* h& i - {- P) I5 P& A K# g; R
- retry++;
8 P4 L7 \ t. C. D& l - if(retry>200)return 0;
. A7 |1 c5 I$ ~3 @, h. o - } , l/ }) R8 b" E
- return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据 3 a9 }! i: ^7 |+ P/ q' K0 n
- }
复制代码- //==============================================================================
) e9 q7 I* D1 {" R) U) q - // 描述: 在AT25读状态寄存器
; p# h. W: ]9 `9 T; s - // 输入: 无 L+ b# ^# U7 X2 m- c" a8 d6 S$ G
- // 返回: unsigned char dat 状态寄存器数据 h0 S$ a% M" \
- //==============================================================================
1 L+ @% W9 l& x& S - 4 i) A4 x/ Y; n/ T+ G& [4 I1 d3 Y
- ) T- o; R; }3 l2 T! W- ?; e# L# ?
- u8 eeprom_read_sr(void)
- ^6 i' v# { z5 \+ K# j* L3 { - {
: }( K0 h- {0 U/ A/ l - u8 dat; ( y5 j- O4 D- m
- eeprom_cs=0; * {) S% {/ s5 E% |
- eeprom_read_write_byte(RDSR); // 定入指令0x054 N; F T; W* Q1 D5 H. [3 @ x
- dat = eeprom_read_write_byte(0xff); // 读回数据 Q ?3 W. t- e9 z( q3 r
- eeprom_cs=1;
. h# z/ Q( b5 l" v4 u* a2 R - return dat;) R1 d- u; \! x( O! d
- }, E, k1 e# ~3 p" H
- $ T" `# }4 S2 K* [- x
- //==============================================================================- [% T$ X- e4 p3 T' o
- // 描述: 向AT25写入一个数据
) |3 s- H$ S" }" l) W - // 输入: unsigned char Dat 字符数据
, p0 H/ T1 }8 ~ - // unsigned int addr 写入的地址
. Z' _3 |; c5 t: s( F3 o5 H, u0 n, X - // 返回: 无
+ |# W* @! ?. q- \6 D+ C' Y - //==============================================================================, d6 O/ V- n! r$ o$ n
- void eeprom_write_byte(u16 addr,u8 Dat)8 m( Y& p. m! p5 x$ u
- { & A8 x0 p+ W0 X' Z3 `
- unsigned char Add;
, |2 g8 f6 b: S. F% o* c" F - while(eeprom_read_sr()&RDY); // 读状态寄存器+ q" C ?3 a! i$ t: f. X
-
8 o1 e1 B2 t, Z2 m- d% z - eeprom_cs=0;( d$ _/ O4 v: j+ c2 H- h
- eeprom_read_write_byte(WREN); // 写使能锁存
* w |. u! |% ?# G - eeprom_cs=1;4 X7 @: u' v% ^2 c- Q
- , `/ w }+ \; [( ^
- eeprom_cs=0; // 芯片使能
( e& Q0 N1 i) e" O - // 写入写操作指令 6 S( l8 ]* _/ `: m) T) U) N$ e% n
- if(addr>0x00ff)* P2 N# a1 I, t- k
- eeprom_read_write_byte((WRITE|0x08)); // 地址大于255
- D6 v* [5 b4 U3 l - else: P3 V6 \( U$ \! F: Q" \- y
- eeprom_read_write_byte(WRITE); // 地址小于255
% ?8 f5 t: [& L* r- f& S7 e3 T7 t8 e
$ d" _+ g. y8 w$ Z& h2 O8 a- // 写入地址 _$ U5 O& \6 Q' N Y M
- Add = (unsigned char)(addr & 0xff); // 将地址换成8位9 U0 {: [- q& c- c7 h v
- eeprom_read_write_byte(Add); # R f. [' x* ` J4 o% p
- % @) Z) H0 i+ w. A e5 }- M
- // 写入数据7 L. v4 G9 Q/ @7 u
- eeprom_read_write_byte(Dat);$ v7 }3 E) n' m _* [
- eeprom_cs=1; // 芯片关闭
4 Y$ E# D( ]! A. H# K& b- z2 n- o - }; q- w) K4 e, o
- //==============================================================================) a7 ^5 B, _& R1 P, {8 Q
- // 描述: 在AT25读一个字节操作0 j$ ]: X @+ S% J. l& i! \, \! y) E, L
- // 输入: 无( H8 @# b) ?& R' ?
- // 返回: unsigned char dat 读出一个字符数据/ G* H5 v2 C9 V% P1 p' D0 P1 s
- //==============================================================================
! [/ a3 i- M. H9 A - u8 eeprom_read_byte(u16 addr)
) l @) z" i7 I- n2 w - { ) e0 t8 C& C* N: Q9 {+ b' Q
- u8 dat,add;
% W5 G' _6 b% E# o - while(eeprom_read_sr()&RDY); // 读状态寄存器
# q, X ?9 ^0 t9 n" {9 B0 f - eeprom_cs=0;
5 i3 \( b$ g+ l) j - // 写入写操作指令 7 }2 ]: p6 L: E1 L* U
- if(addr>0x00ff). ]/ O' l& x M; L* }! o& b k
- eeprom_read_write_byte((READ | 0x08)); // 地址大于2550 ]5 W6 e% x3 Y7 \
- else
5 Y7 ^7 a7 i" e, M* S - eeprom_read_write_byte(READ); // 地址小于255! s& Z; Z8 W5 ]# v& t3 G) c$ U* u
- ) Q( v! V( t2 w$ |" v$ {* |
- // 写入地址
' r' y5 \" \% K R3 e0 u4 }- a - add = (unsigned char)(addr & 0xff); // 将地址换成8位
4 b: i; J. X! B8 i - eeprom_read_write_byte(add); : F# N5 R7 G7 x
- - s) h) R, E, a! A
- // 读出一个数据
( H& X) K8 Y9 b: R" a - dat=eeprom_read_write_byte(0xff);
; g! S- Z; U) v" A8 h9 M - eeprom_cs=1;7 o0 f. P4 c- A$ Y: i
- return dat;( s- V6 ~# L% W0 M3 o" Z. I, f
- }9 d0 B- A k; c+ o, D0 H
- //==============================================================================
K1 m& Z) S1 O# c* U' x& e - // 描述: 向AT25连续写入数据
" T* |! p; Y% p/ _. Y) o6 o - // 输入: unsigned char *PC 写入数据指针5 n& F7 S1 w8 O0 O D7 F# @7 A
- // unsigned int count 写入数量计数
% I# ~! ^5 h3 j: b8 j! L; N2 W - // unsigned int SatAddr 写入起始地址
, w) h, h. I9 e# t - // 返回: 无9 j$ ]; E4 l' ^! }
- //==============================================================================: S6 A4 S1 V" p7 L) C
- void eeprom_write_buf(u16 startAddr,u8 *buf,u16 count)' J' V' P b" V* a+ Q; |
- { + H! K* N# ^/ I, d# }
- u8 Add; * X" l1 X0 ?' | j
- u16 i;4 Y: k7 l# F; ?/ O; E; m/ u! O1 V: [
- while(eeprom_read_sr()&RDY); // 读状态寄存器/ x! O# R) [5 e
- + ~2 e, M% m; b
- eeprom_cs=0;: {, Y- e0 g) B; Y
- eeprom_read_write_byte(WREN); // 写使能锁存
' L+ l5 e) d! }/ M - eeprom_cs=1;
+ u9 y, ?( C$ D: _: k3 b - eeprom_cs=0;
& A0 y. q( v. P2 Z& m/ G. h - // 写入写操作指令 & Y# p9 O$ \0 P
- if(startAddr>0x00ff)
; g$ I/ n+ y& S$ o; V+ v! ?! ~1 g - eeprom_read_write_byte((WRITE|0x08)); // 地址大于255
]% ^) f2 O0 J4 T( }) z - else5 |4 r: z2 z3 _
- eeprom_read_write_byte(WRITE); // 地址小于255+ r+ S6 g4 G0 v/ ]6 l$ \7 P; m
- 8 g# H% x* F% E8 {* X4 O
- // 写入地址9 f q+ K9 T! |9 ~3 i' v
- Add = (unsigned char)(startAddr & 0xff); // 将地址换成8位
/ ?. J7 ]4 K4 I8 S3 L) Z4 w - eeprom_read_write_byte(Add);
|8 x8 ]& L9 W' }
- [$ D; D5 x1 D) J: B0 ?9 H$ e- for(i=0;i<count;i++)// 写入数据& V. x" N$ X6 N+ ^$ R
- {
0 e+ o r5 G# _2 f. m& X( I! o - eeprom_read_write_byte(*buf++);% W$ l! ~4 q' z/ A" v4 C Q
- }
8 R" \2 V" o# h4 h ?# m6 { - eeprom_cs=1; // 芯片关闭
- ~9 {- N; J* I - }" n, r+ R: O: l6 ]+ k
- //==============================================================================
# ]( g. @+ w1 E& u5 J9 b- E - // 描述: 在AT25连续读数据; {( ^5 |9 U1 q; d- p$ `! k' h
- // 输入: unsigned char *PC 读出数据指针8 A \: P' D( J$ J# k7 D2 d
- // unsigned int count 读出数量计数
& q$ W) P+ H& ^0 K5 d - // unsigned int SatAddr 读出起始地址
8 M; J/ @8 R6 m4 d6 p# h: B - // 返回: 无8 {, L# c4 Q8 }; |. I
- //==============================================================================
& |& O8 b7 L9 @$ z4 e - void eeprom_read_buf(u16 startAddr,u8 *buf,u16 count)
/ U* h$ y3 N T/ w( ^ - { ) @; y- r) E( z- X* I! E% i1 V
- unsigned char Add; ( O6 h2 T6 |' N4 D q$ g
- unsigned int i;
- b3 A; `/ k! V* ~: Y* i: Y - while(eeprom_read_sr()&RDY); // 读状态寄存器 $ t D2 T' M' L2 [+ V
- eeprom_cs=0;
0 d6 e: l) M' N, M* L - // 写入写操作指令
" y. q( y8 x; k$ i - if(startAddr>0x00ff)
! v2 q0 N8 ?/ v1 d' M: N - eeprom_read_write_byte((READ | 0x08)); // 地址大于255
4 A( I% B9 i! h6 k7 ~9 L - else9 y1 f; Z% j+ ~8 o, M( J! _* c
- eeprom_read_write_byte(READ); // 地址小于255
1 g, G& S4 U- V" B( E; v# f' w
" n* [4 Y1 Z& n+ [( y6 ]. Y- // 写入地址" k' k) Z! o7 ~
- Add = (unsigned char)(startAddr & 0xff); // 将地址换成8位
% e* |; |1 T8 H+ E - eeprom_read_write_byte(Add);
; j2 o" a H' N- l2 o1 s7 e3 _- e. Q* V- g
( o( e. h2 u7 C4 _% a5 c) L- // 读出n个数据
2 n& u2 d# h" ~& N Y - for(i=0;i<count;i++)
: J: m- |9 |3 k$ S - {
" f5 f5 y3 |9 C: R - *buf++ = eeprom_read_write_byte(0xff); r1 U: H3 g9 |# P9 R
- }1 F, T: e6 p& e+ L7 h
- eeprom_cs=1;
) ^8 W: k) |* p: P - }
复制代码 + u) {8 b7 x% t5 Z9 z) J6 e9 R8 d
二、测试7 T% @1 _0 G& A1 ~( O* }5 K
@0 _% I \2 o0 g9 q0 z& M- int main(void)
2 }; _, W. q. W" `' l( S - { . O7 j5 G/ a0 b1 J1 P
- u8 buf[5]={0x01,0x02,0x03,0x04,0x05},i;8 ]& r+ E7 q. w' z
- uart_init(115200);
2 z* Z/ ~1 {8 l$ Q - delay_init();
9 z" ^) B9 l# [2 T; g5 Y) } - program_led_init();
3 Y' r, S3 d p% f/ q - 3 ?9 v4 R- p) k K: ]9 B& r
- eeprom_wp=1;
, K- ~- }. d, U5 S: M) w - eeprom_init();
- f) \9 b9 O$ R9 u7 G% R. @ - eeprom_write_buf(0x0000,buf,sizeof(buf));
4 E d9 S$ d) T: e# `, G4 h6 f - // eeprom_write_byte(0x0000,0x08);
: R8 @; p4 f( t7 ]+ R& g' G - memset(buf,0x00,sizeof(buf));6 r- V1 f M$ x- \4 S
- eeprom_wp=0;$ c& S( O) W7 b/ ~# V/ L. i3 ^
- while(1)
0 n# g# [4 i6 r, I8 t - {
4 U& k" `$ P* \5 q -
9 v0 f; u% z/ R - eeprom_read_buf(0x0000,buf,sizeof(buf));
# Z6 N' ]" Z. y- s0 z - // buf[0]=eeprom_read_byte(0x0001);4 G) M" x2 k9 r% Q& ^1 t
- for(i=0;i<sizeof(buf);i++)
# z) j: {7 z5 J) O. s% S8 C - printf("0x%02x ",buf<i>);3 o' F3 X$ a8 \$ j
- printf("\r\n");
, l1 O Y a! B/ F - memset(buf,0x00,sizeof(buf));' L- R6 P8 \7 f" U% k2 z4 |
- 4 H% X$ e+ A6 E% H% n, I" E
- program_led_data(0x10,0x10,0x10);
; x2 D# x; X- b3 n/ W - delay_ms(500);
2 h3 p- M$ a" }; d' u" W
, R7 Y5 G# ~5 g& ^3 f9 s/ Z- G- program_led_data(0x00,0x00,0x00);
% }8 W* C* `5 e8 a - delay_ms(500);
8 x5 [' S. R( d. o3 O -
% u* Z/ {' h0 d8 @& c" j -
5 W9 Y/ g% P9 |2 p( i3 w - }
9 d) P5 u3 p: Q: B6 J) o, N - }& P& X$ t2 B$ K9 L7 w; {) n) I
' F8 k/ U( A2 b- I2 p! M& f) v
4 `8 s9 D& \( W, g6 H- u' D- </i>
复制代码
* K( Z, w% ~/ q- K( f |