- #include "eeprom.h"$ c7 U u" ]* p$ b9 ~6 ?
1 m; c6 Y1 I4 @. \- ' F% @% B$ m) @8 V% z
- void eeprom_init()2 }4 w+ w5 H+ B& B! T% s; N0 H
- {
8 ^" g6 a0 d1 L4 X: S: H5 G - GPIO_InitTypeDef GPIO_InitStructure;
# s9 J4 |* T/ U5 w5 s2 _ - SPI_InitTypeDef SPI_InitStructure;
2 H% `* m3 b* e - + d7 \+ {+ h. q: G. ~8 h
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOB时钟
1 _ G6 D- p" D; j$ T1 d# m- T# [ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI1时钟
! Y6 P* P- A x/ k% f6 u
$ Q2 ]; ^; r1 ~( ^5 f- //GPIOFB3,4,5初始化设置- q0 d% ^. ^" m0 ^& H4 j
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;//PB3~5复用功能输出 % C/ e- X1 [9 k7 g$ @2 ^
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能7 r1 E) f$ {2 _: U4 B6 D. C
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出% h: v p5 {' F/ a
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz5 ^% q1 P3 ~0 @# @/ ], M& w
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉5 W* N3 s7 p+ F
- GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化4 F1 P7 k8 }3 f3 F6 S7 j. s6 g
-
2 I1 N& t9 D& o3 D - //GPIOFB3,4,5初始化设置
7 T; b9 A1 _ ]6 T0 k2 v% B - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PB3~5复用功能输出
# g z& l V/ C4 }" n7 Q - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
1 {) [$ R/ g# u6 k% v r - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
% ?& R# l) u4 D( O O - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz- ? j3 m7 x* E- K9 z# q t+ z
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 M4 p# M* j1 v' g8 M `' I8 L: Y
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
" p. j( z" O" B& j$ U - 2 J- h) K/ d4 d' m* m! T
- //GPIOFB3,4,5初始化设置8 R/ x8 _3 H1 _
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;//PB3~5复用功能输出
$ n: o6 y) T# X# w) P8 } - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//复用功能8 X0 O/ B; `) [* {% t# P4 r
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
j, z! y- U1 \& a4 c - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
+ o5 _9 z ]. Z7 N" }; A" B - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
/ t% I9 y! [6 n( @0 P* \: e - GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化 1 S$ n6 F8 x+ s% A4 M, z$ q4 \" y
- GPIO_SetBits(GPIOE,GPIO_Pin_2|GPIO_Pin_3);
# U1 f# F" a% e/ G- ? - " }# J! K8 o2 ^
- GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_SPI2); //PB3复用为 SPI1$ j" v( l: L! M, |! X# l* z6 p
- GPIO_PinAFConfig(GPIOC,GPIO_PinSource2,GPIO_AF_SPI2); //PB4复用为 SPI1+ d+ K) W0 g8 K; k1 p
- GPIO_PinAFConfig(GPIOC,GPIO_PinSource3,GPIO_AF_SPI2); //PB5复用为 SPI1# ?* K: b Y8 U+ }( r0 E3 Q
- ; N6 k8 D T& n6 Q" f" ?0 H
- //这里只针对SPI口初始化$ _: C$ G: A4 h5 `, \7 O* g: K
- RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);//复位SPI1+ Y# R$ Q9 @ ^4 e) S; O ]/ t8 U. x
- RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);//停止复位SPI1
% {7 T8 e ^, @7 G! J i( W - % i+ r* T1 V# F
- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工( a* e# b) c$ _! N% t5 Y
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
2 S, Q5 O8 g* q% o8 l, G - SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构2 j9 o5 E9 S0 Y& t2 R1 [
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
# C+ ~" n- _& h# B - SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
6 o4 }7 @ J) j) H6 f2 M5 Q' ] - SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
8 s9 V2 M7 C0 u1 P; p7 r G - SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256# G2 ^& e( H4 }/ g2 Z
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
/ v! q5 C4 J0 ~# E - SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式9 J' G8 I P8 |0 P1 T* {
- SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
: A W8 S/ |& h; W- I$ \0 d - - m3 Z! K, P$ n1 ]: t5 a3 k
- SPI_Cmd(SPI2, ENABLE); //使能SPI外设& \ K: g. T- E
! G9 q, @$ Z) H$ W! Y9 Y" O- /// eeprom_read_write_byte(0xff);//启动传输 0 c2 c! s, c) D5 C) m& L5 a8 m: q
- }
9 A; `' @ [& h. ]8 u! ]9 E - //SPI 速度设置函数; y# M5 z: X- [ Y
- //SpeedSet:! H6 c9 ^ n! Z i, X; u
- //SPI_BaudRatePrescaler_2 2分频
3 H4 k) C% w4 X" ^! b/ a+ O1 x - //SPI_BaudRatePrescaler_8 8分频
9 N$ v3 h$ ~8 Y - //SPI_BaudRatePrescaler_16 16分频
; \6 B9 R% Z3 j& x0 v' } - //SPI_BaudRatePrescaler_256 256分频 / e' M% U' Y# c' V2 L
o4 d& \, o8 c- void eeprom_set_speed(u8 SPI_BaudRatePrescaler)
0 U' L4 n3 W# `# T y - {8 g" P2 a1 W& u3 P
- assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性, I/ M) ]: u% z- V6 r. v( P' S+ I' i
- SPI2->CR1&=0XFFC7;//位3-5清零,用来设置波特率
5 e" D8 c }! d# b/ v! v1 ~7 }8 ~% a - SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI1速度
! P0 s5 P2 ]' z7 B" @- r" } - SPI_Cmd(SPI2,ENABLE); //使能SPI18 T$ M3 N1 C- M! b+ E7 l* k
- 2 ~! u+ {+ ^/ D$ S0 s
- }
: q+ `6 |8 l5 G3 |3 Y2 k
2 m& h4 s0 A8 ? k/ A& Y+ U- //SPIx 读写一个字节
: |2 h* |( B% ]# J - //TxData:要写入的字节: W! P* k3 ^6 r# J
- //返回值:读取到的字节
+ o6 T& q' S4 C) x! z! B- A - u8 eeprom_read_write_byte(u8 TxData)
: a7 n5 h6 @4 k+ b* i - {
$ P1 U- z+ X* _ - while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空 + I3 y" V! @9 z3 h s: e
- % [4 |" x3 v8 b% G- _
- SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个byte 数据
) F* _/ \* J/ }0 `. X
' F' Z* X' Z/ M! Y/ g- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个byte # G7 R4 [9 H+ M s, O
- 3 u6 l! z( Z8 X4 U6 A) g: k
- return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据 ; _' L" H2 T+ j2 h5 y! r H
- }8 I# ^* a8 l. w: ^$ ^
- 2 i" [" C3 g1 M
- //==============================================================================
`1 L4 g; h9 g' A8 T9 x - // 描述: 在AT25读状态寄存器9 s2 _0 u7 ~3 ^6 @! U
- // 输入: 无+ d A& _# {" t. L. D" @9 b
- // 返回: unsigned char dat 状态寄存器数据3 P$ f0 c0 }4 F
- //==============================================================================: y5 L0 q4 f& F& [* W0 }- ?
" j9 G2 K% |) y5 c
& \8 K& C. l8 Q0 o0 g# i- u8 eeprom_read_sr(void)4 K! V& W- n% P' C: w& v
- { ! J8 d0 N- Y- G# b
- u8 dat;
V! y) E# S; j1 e! D- g - eeprom_cs=0;
6 p v2 l$ v8 z$ s; {, T5 | - eeprom_read_write_byte(RDSR); // 定入指令0x051 }# E! [9 A- S7 S- t
- dat = eeprom_read_write_byte(0xff); // 读回数据
! M* q+ p" V2 x- y7 o+ G4 r - eeprom_cs=1;# X6 t# u9 \- q7 U7 I0 c ^
- return dat;" f5 F& U: V7 s# ?2 k+ \- N
- }
( f0 F5 p0 P K1 | b5 `
) T1 b% r3 o! x! [* X5 O! [9 D- |- _- //==============================================================================. p9 }; }8 I6 G, h7 T& v
- // 描述: 向AT25写入一个数据
4 O; L c) N4 c0 ` - // 输入: unsigned char Dat 字符数据
( p# S7 X* x% m# E5 x& W - // unsigned int addr 写入的地址& n# q6 s+ O4 e' ~
- // 返回: 无! F+ }3 G4 O7 ~. E1 C W4 h
- //==============================================================================0 x/ S i# Y6 m
- void eeprom_write_byte(u16 addr,u8 Dat)
0 u5 _! j$ m; R, G2 U# {2 Q - { 3 \. Q, m* R! D J# H
- unsigned char Add; % O, W+ y" ~# A3 y+ G3 \" _- \ \
- while(eeprom_read_sr()&RDY); // 读状态寄存器
* @* x2 ^) n8 d; H( H - 0 F( @6 y# N# v" y1 ]* N
- eeprom_cs=0;. Z8 i8 {' ~+ b5 d, K
- eeprom_read_write_byte(WREN); // 写使能锁存
' U5 z4 Q# i+ X - eeprom_cs=1;
: ?$ i, l. C8 k0 y z& `2 |9 N - " u7 }$ k. {& O0 m( m. Q
- eeprom_cs=0; // 芯片使能
# ~8 I& K$ T; w5 Z. G* b! a1 N& i - // 写入写操作指令 - G2 X' ]: y! a- J+ H6 I
- if(addr>0x00ff)
( a9 y5 s8 o! N - eeprom_read_write_byte((WRITE|0x08)); // 地址大于255% d ?% O8 J9 l. }8 Z
- else7 A+ _. U6 s6 Y
- eeprom_read_write_byte(WRITE); // 地址小于2557 {% u7 ^ V* }7 N0 g
- ' e$ A) n, Q8 T8 H& I# w
- // 写入地址* `7 {; h8 Z0 s% O
- Add = (unsigned char)(addr & 0xff); // 将地址换成8位
) s( ^% Y) N4 W# x' P# Y - eeprom_read_write_byte(Add);
7 _1 Y5 s# Y/ r2 n# q3 K( X# p - : O7 f/ y4 ?& u* A4 h" U
- // 写入数据, f: [ i0 \$ u" |
- eeprom_read_write_byte(Dat);, g% h0 x! S0 u: l) n
- eeprom_cs=1; // 芯片关闭 ) H) q0 W5 H; k4 `: `; Z4 b$ Q) g% G
- }
b. p' f" J: M- ?! T s T - //==============================================================================
( G; S4 | B G9 n8 ^5 N - // 描述: 在AT25读一个字节操作: F/ m0 Z' D) b- r7 g' `) G3 U, [
- // 输入: 无
3 o. z+ S5 G. C# `' E3 M - // 返回: unsigned char dat 读出一个字符数据
) B- q$ X1 j" }9 u* X - //==============================================================================
' j% X0 D6 i* [; U5 { - u8 eeprom_read_byte(u16 addr)8 B( r' d% J* M) W# m
- {
) ]( S/ T% O( C O1 D* e - u8 dat,add;
. y! @' l2 }) q2 P: Y - while(eeprom_read_sr()&RDY); // 读状态寄存器 $ u6 ?- ]- a! G& R
- eeprom_cs=0;2 L( e2 I* @2 o5 U* r
- // 写入写操作指令 9 }: d6 O x3 x3 a
- if(addr>0x00ff)4 f$ {7 ]0 z8 }" [' C
- eeprom_read_write_byte((READ | 0x08)); // 地址大于255
3 c& S+ t+ \- C% ^# Q+ ]3 f2 O* o - else
4 `- Y) M# ?; Z5 E+ z" Q0 j - eeprom_read_write_byte(READ); // 地址小于255, g8 m% F( I/ p `9 ~
- % h6 x. e3 e- `7 ^+ o
- // 写入地址
! U7 V+ C# r }+ U6 J - add = (unsigned char)(addr & 0xff); // 将地址换成8位
0 \2 E8 G9 w9 N" u: W - eeprom_read_write_byte(add);
' ^5 L5 N2 w0 } - - _ T; V2 e! A; W3 j! k1 `
- // 读出一个数据, a$ r' q& J; W9 ^: q
- dat=eeprom_read_write_byte(0xff);
- y9 ~# l* u a" T - eeprom_cs=1;
% f! K7 [1 }1 z* p9 | - return dat;. e( O% j5 A" Y: N, t
- }( Z1 O# D3 P. E! u8 |' ~# [3 G
- //==============================================================================9 r! K# b$ F' r" q) o; c8 A" k6 g& _9 ^2 s& q
- // 描述: 向AT25连续写入数据
% s8 E+ Y" P/ o2 m o) o( v - // 输入: unsigned char *PC 写入数据指针2 e2 g8 g: E9 C' p5 Z
- // unsigned int count 写入数量计数 ( M8 D4 }" ?, W0 I/ C5 r
- // unsigned int SatAddr 写入起始地址
v% g/ S% { l) O# v! o% e. b* G - // 返回: 无
" c1 v1 M. R4 d4 y - //==============================================================================
8 u! D7 ^( V2 L; f& H0 S4 } - void eeprom_write_buf(u16 startAddr,u8 *buf,u16 count)4 u2 Y+ A9 [: }
- {
. `7 e! J, _' m4 q' Z0 t4 y2 b - u16 i;4 H/ @' p h7 a% v+ S! s+ }* ~
- while(eeprom_read_sr()&RDY); // 读状态寄存器
9 \/ _: I2 g4 V( Q* z - + v1 w8 \. g$ K- I9 [) Z3 {
- eeprom_cs=0;% L! ?' r# U4 C5 W$ W# s2 y; i
- eeprom_read_write_byte(WREN); // 写使能锁存; ~" p F* K+ ^0 A
- eeprom_cs=1;8 Q& [6 ?* L! ~
- eeprom_cs=0;1 Q6 q1 e3 Z. U/ a! L; `/ U
- . r/ f: Z6 X: [$ y9 s/ s' [
- eeprom_read_write_byte(WRITE); // 写入写操作指令 8 |$ Z1 h, x& u' S: b+ D
- eeprom_read_write_byte(startAddr>>8); // 写入地址' J' S3 m+ J, ]( T" T
- eeprom_read_write_byte(startAddr); + g% M5 a9 u6 b) }% V9 I0 a
- 4 ?9 `8 T+ W Y+ x5 R
- for(i=0;i<count;i++)// 写入数据
2 N) H. n8 ~. p& ~& t - { 2 c/ p- F, b3 A/ w8 N
- eeprom_read_write_byte(*buf++);
9 d7 ]( \) k& y' |5 P; | K4 Y - } _; f; [* r& `3 X/ B7 ]; \& u
- eeprom_cs=1; // 芯片关闭 * m' M+ U: S& W3 T/ ^7 [
- }9 c2 C& L: V9 I8 U1 K* z
- //==============================================================================: E+ |3 d, f0 R2 }, m0 T7 |) v* c% [
- // 描述: 向AT25连续写入n字节的数据& D& ?# p+ \" `! w
- // 输入: unsigned char *PC 写入数据指针* p' Z ]; [$ c, u) R
- // unsigned int count 写入数量计数
# u# n4 j$ u' ^7 E. {$ a - // unsigned int SatAddr 写入起始地址3 J9 V+ E; V& \% v4 S
- // 返回: 无! N: S4 T& X& |, t! I8 q; N. h% ^
- //==============================================================================7 b. y& U) ]- }" ~9 R4 s" \
- void eeprom_write_nbyte(u16 startAddr,u8 *buf,u16 count)
9 X4 `4 N' ~1 a# O! }! J - {
7 b2 \) ^: }$ B8 Z) W/ d - u16 pageTotal=count/64;) q- @ H# |# j! c
- u16 pageResidue=count%64;4 x" |8 Q+ P9 i; a
- u16 i;& C$ N/ [: X, l1 L* m, O) E
- u16 pageCnt=0;
$ G( }5 l7 a1 O: J - % E l. p. s; P5 x9 ?. o0 \' p
- for(i=0;i<pageTotal;i++)* d6 A0 u$ l0 [/ s" \5 |
- {
' w! J8 M6 B2 M$ @6 v - eeprom_write_buf(startAddr+pageCnt,&buf[pageCnt],64);
# f+ w \; _" W5 T: H+ W - pageCnt+=64;% n4 V& z: j: M" k/ X
- }
$ g1 N' h( h% B: P/ w P# {" U$ R - eeprom_write_buf(startAddr+pageCnt,&buf[pageCnt],pageResidue); //写入剩余的2 l; H0 @1 L1 x/ p* L! Z, Y4 B) }& g
- }
/ R# z% K( Y; T+ K1 B' P
: [) _1 z. B* s* g$ a, ]
9 a# z2 d6 k6 n' E' M0 A- //==============================================================================8 B1 g* S3 n2 U5 D
- // 描述: 在AT25连续读数据: b1 o& \ U$ t. P+ B/ |
- // 输入: unsigned char *PC 读出数据指针, S; T% m3 t+ U
- // unsigned int count 读出数量计数
. _0 Z: v B4 X - // unsigned int SatAddr 读出起始地址3 R0 `- i/ h6 d5 a
- // 返回: 无
. t5 r0 U4 F5 `+ d* y/ X. r - //==============================================================================9 K( v$ a1 ` U. B' E; s4 G
- void eeprom_read_buf(u16 startAddr,u8 *buf,u16 count)9 C3 p3 n) f& S8 w0 k9 `8 M2 C! H% u
- { 4 D1 v W. u# p% ?
- unsigned int i;
: {- n) G; l0 f4 n - while(eeprom_read_sr()&RDY); // 读状态寄存器
! w+ N! A2 q! L5 P% e - eeprom_cs=0;8 y8 H+ t! W$ K f. D, i
-
4 _9 a4 b. F q" w4 r, O - eeprom_read_write_byte(READ); // 写入读操作指令 5 o5 r* A8 M: p* ?
- // 写入地址
( n7 j+ m5 {: d0 M* D% A+ k3 v - eeprom_read_write_byte(startAddr>>8);
' {9 }5 u# F$ u& @! b+ H3 A; u - eeprom_read_write_byte(startAddr); ' E5 X& ~3 j9 _
1 ?& h8 l7 Y9 U9 a& U z1 j! X- // 读出n个数据. T, i, e, y% s2 ~
- for(i=0;i<count;i++)1 V$ p- b8 e. I: @% [5 s. m' |1 y; J
- {/ g" ~3 ` i6 ]; q+ m" a/ [$ t
- *buf++ = eeprom_read_write_byte(0xff);
+ H( `/ J# v1 c/ b( m3 j$ _/ i - }6 @$ P1 `9 |, Q& p8 P: `& l( r
- eeprom_cs=1;
% S7 i- U" u5 o' y& N - }
" P2 ~4 v' P+ I ^% k0 [: f - . ~. x1 B" k* s. r$ E) C4 U
- . u" d8 N7 Z3 M1 S
复制代码
5 P' X& l- @2 G6 O. _' z |