- #include "eeprom.h"
: p; N: Q. i( |
) G! y4 _( v i$ ?- Z! L- ) t3 x' Y2 L5 N, C) H; K
- void eeprom_init()
& m1 p2 O; \; ^" e - {
8 P; w% F ~9 G& E3 m9 D - GPIO_InitTypeDef GPIO_InitStructure;
w; Y! |( J% N' s+ m* z( }: C - SPI_InitTypeDef SPI_InitStructure;
. l, b5 o/ v6 T1 | - $ `+ L" K+ O4 L) B* p, R7 E
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOB时钟
' b% E, b u! O; K8 X$ H, w# K/ S - RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI1时钟! n; a$ O. o, ~8 J
6 h8 X5 @- k2 x& d4 f! S- //GPIOFB3,4,5初始化设置2 k+ X; T& ?$ n- I
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;//PB3~5复用功能输出 W" ~9 B" n% D2 I. S1 h
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
: G; v$ W; Q6 H, Q# X - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
3 o5 j1 i+ c, O( }1 @1 H - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz3 p, O5 q* n P$ p
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉6 ^8 a9 _$ O5 O7 m: g
- GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化
! j4 p3 Q, ^: v9 ?* _ -
5 P: J* J# K4 _- T) V - //GPIOFB3,4,5初始化设置
3 C$ B c/ e- I2 R, I- Z) i - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PB3~5复用功能输出 * R6 J# u1 }1 f
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能9 u8 R0 k! A3 T! P0 S. d$ c$ C( g
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
+ t/ u$ Z1 j6 } - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
p' t& `6 ]4 Q8 D - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉) P( h* E0 |1 |% c+ u! J2 O0 ?3 e, p
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
$ k) I* {& U; |1 S0 a7 x" m5 F6 T5 v - 3 \; }; l4 t1 L' C8 [$ }
- //GPIOFB3,4,5初始化设置
- A+ ~$ R$ I4 [$ W# ^0 ] - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;//PB3~5复用功能输出 # n. B3 c, ]. F# ~8 c5 |7 h
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//复用功能* y/ z, A( [; G
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
& z' _5 `$ n7 ]( [ - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
& g' {$ N7 _, q0 d& v - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉/ w0 D: W& p2 M1 L6 F2 [" c
- GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
2 k8 T+ L6 p" v8 c& C, z# d - GPIO_SetBits(GPIOE,GPIO_Pin_2|GPIO_Pin_3); ; ^* B% L% W7 l$ ?1 ]: I
- - z$ n1 a8 g' T {" q" n
- GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_SPI2); //PB3复用为 SPI1
5 ?6 I; Y) N, T% |, [/ s - GPIO_PinAFConfig(GPIOC,GPIO_PinSource2,GPIO_AF_SPI2); //PB4复用为 SPI1" }8 y8 \/ ^0 o6 Z/ H+ d
- GPIO_PinAFConfig(GPIOC,GPIO_PinSource3,GPIO_AF_SPI2); //PB5复用为 SPI1
% W4 d7 Q" \4 \: x5 y - 9 R* ]6 p8 c- z4 X7 O4 B
- //这里只针对SPI口初始化: P7 `# k5 a- x, m* \5 p. X
- RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);//复位SPI1( i+ P9 g, u& t1 E X
- RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);//停止复位SPI1
0 ]. l; o' _% O: Q" J* w3 M/ y/ v7 f
, K! k Z( N& r; n: s) e, _- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工- M% n# H7 w9 F! s+ p' U* Q. X; Y/ @
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI+ U3 `7 ^6 }6 V; K
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
- ^7 h4 `& T X3 F) } - SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平( r3 J4 x: X7 ^: E) f m
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
( R6 j, Z$ S1 c2 i5 X - SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
7 _5 T+ _. W: `3 R' `% n4 q - SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为2563 d% W [+ C. G( o
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始1 s6 i0 ]5 s5 H# k2 l( _
- SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
4 S$ n/ [& q% A d" ] - SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器8 V( V$ u7 x( j P# z9 X) z
( z+ E' C2 d# `. w- SPI_Cmd(SPI2, ENABLE); //使能SPI外设 a9 u$ S) o; O5 m. v
0 E) p; v! C& }2 H- /// eeprom_read_write_byte(0xff);//启动传输
7 x0 n2 E1 p9 a: W4 q4 i" m - }
; d z3 x2 U) ?5 G - //SPI 速度设置函数* l4 M( w% J" U Z* _2 r
- //SpeedSet:& d* ]6 _$ U$ G* C y
- //SPI_BaudRatePrescaler_2 2分频 ; \; t( I) m- i% y1 S% d
- //SPI_BaudRatePrescaler_8 8分频
6 ^0 f8 z. P! z; c) f2 H! j - //SPI_BaudRatePrescaler_16 16分频
" r* v `$ A- U& z% v" Y {& _/ J - //SPI_BaudRatePrescaler_256 256分频 - C6 y6 E1 j3 ~7 p" J
- 4 ~7 Y5 R0 r) `' D; U
- void eeprom_set_speed(u8 SPI_BaudRatePrescaler)+ m: m) u- o" f/ E
- {
5 R _- W7 E. ~% I4 u - assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性; g( N: s( U/ m
- SPI2->CR1&=0XFFC7;//位3-5清零,用来设置波特率 [# q4 x- `& {/ x. R9 L' n$ g, W
- SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI1速度
/ Y# l3 f4 w; [: {/ x - SPI_Cmd(SPI2,ENABLE); //使能SPI11 f4 q5 f2 C, s4 z# P( ?
0 ]- b7 S, \5 y+ b1 z- } , J9 W* x4 I" c2 n# H/ m7 v
- % N) Q1 D7 x5 G7 h/ M7 N
- //SPIx 读写一个字节+ d! {6 |) m) O: M& W
- //TxData:要写入的字节& k" P1 t& g1 s* u; }; D9 Q
- //返回值:读取到的字节
# J$ L" ]! U* Y% y% m - u8 eeprom_read_write_byte(u8 TxData)
: c: t" R+ p- N, q2 K7 O - { ( D P+ ?2 C6 Q" }# q! Y
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空 2 j% S+ k+ p4 T& g6 s3 f+ K8 H
+ P, Q/ g8 x1 E- SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个byte 数据" W, f4 i5 ?6 D4 x+ O
; ]0 x6 A; `; s) L3 i- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个byte
/ C( g2 M) M3 U" k8 p
4 Z$ j! r9 b; A0 e2 l/ m) y- return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据 . U8 w2 s% ]& t' W: V
- }* d8 H8 c* U; g
5 n) P9 e6 |# e% x2 A* U; u. V; ?- //==============================================================================: L/ X# Q5 Q5 E2 ^* o
- // 描述: 在AT25读状态寄存器( V2 V# h# t$ V8 S/ C8 A, t
- // 输入: 无 q: ?+ z8 M6 |$ f/ n7 y1 Q
- // 返回: unsigned char dat 状态寄存器数据0 Y, X+ z0 L) D5 V5 g7 h7 Y U
- //==============================================================================$ m: w+ v( w9 [! O7 M/ O' W) y
8 ?* s7 ]% E% T
5 r, i* O' j$ V- u8 eeprom_read_sr(void)8 n+ F, i9 g! r$ A
- { ) ]: n9 Y) D. q$ H8 U0 {- e6 }4 {% _
- u8 dat; % p# \: e, A7 a. S$ l
- eeprom_cs=0; , r+ \4 b" ^6 }4 `% N
- eeprom_read_write_byte(RDSR); // 定入指令0x05
* z/ o9 A1 B$ N( x) G# v - dat = eeprom_read_write_byte(0xff); // 读回数据
, A; z# D8 L0 V8 ~1 T0 { - eeprom_cs=1;
' B) E/ U; f. N4 u6 G - return dat;
9 |1 I, m7 l2 V4 i5 ^ - }
& i, E( r. q# M( N: Y: j2 w - 4 }! m: Q5 k1 N
- //==============================================================================
2 k' r/ q' ?% |1 M - // 描述: 向AT25写入一个数据
' j% r2 V) w* N4 n - // 输入: unsigned char Dat 字符数据+ x0 V! C) [8 K. l. C m0 A
- // unsigned int addr 写入的地址& w# P4 I- h: Q9 l6 r) V' A
- // 返回: 无
. | m- s. |/ C' Y/ }5 U) W - //============================================================================== D2 b. z: I4 ?
- void eeprom_write_byte(u16 addr,u8 Dat)
3 J8 o/ ^) s2 { - { + N, T( U" h/ a G, D
- unsigned char Add;
8 ^# a2 \! V! Q: K$ u8 D H% q6 V - while(eeprom_read_sr()&RDY); // 读状态寄存器+ w8 E9 x R# A% `* c
- : m$ C6 }& q% |- d; o e
- eeprom_cs=0;
& J8 m0 E8 A3 S3 v) C* p7 O; L - eeprom_read_write_byte(WREN); // 写使能锁存. ?. H V$ R1 S# P
- eeprom_cs=1;6 G' |- \4 [3 A" j
-
3 W R; U l9 C8 p - eeprom_cs=0; // 芯片使能
; Z" E$ b7 z) M; v' D: u - // 写入写操作指令 . _4 G" f. x- F' Y& w
- if(addr>0x00ff)
* g' u( b0 f; F* G1 c - eeprom_read_write_byte((WRITE|0x08)); // 地址大于255- N2 G4 [% d& @+ ]! {
- else# o5 I+ l$ e( @) [
- eeprom_read_write_byte(WRITE); // 地址小于2553 o' y( ~$ f3 W$ X' K$ x( n1 r' ?
- 8 U& ?/ z! p$ B# u
- // 写入地址
$ Z# r4 t' q! E {0 M) N ? - Add = (unsigned char)(addr & 0xff); // 将地址换成8位
3 \% o/ D8 |3 j$ m% A% ~ - eeprom_read_write_byte(Add);
& K3 M* }# A1 T) \9 O - & p# G/ x' t( L1 T
- // 写入数据
0 p# X; R7 M0 M/ F! I9 E$ g+ F" O - eeprom_read_write_byte(Dat);# `, M. }# D" G* a5 B
- eeprom_cs=1; // 芯片关闭 0 i4 v3 K( B! V4 x, y
- }1 b; F6 X7 y# B3 `1 g( D
- //==============================================================================
0 E# H. P* x" Z* c3 D$ { - // 描述: 在AT25读一个字节操作
( O3 b+ b) s3 s1 s# r p - // 输入: 无
) v8 N1 M4 I0 c5 N - // 返回: unsigned char dat 读出一个字符数据
4 c, V. B& W' P7 x4 Q j" S - //==============================================================================
6 R- h% |7 `- R$ s - u8 eeprom_read_byte(u16 addr)+ ^8 O1 w6 q2 b' T8 z" s2 B- S
- { 6 K7 k5 p/ Y' n4 A
- u8 dat,add;* }9 }2 J. \% E2 v
- while(eeprom_read_sr()&RDY); // 读状态寄存器 * X% a$ w* C9 g' e$ j
- eeprom_cs=0;
: ]3 E( @* X- H9 R4 E1 i# ` - // 写入写操作指令 / u4 u% v" Z8 {. j# s
- if(addr>0x00ff)4 Q$ Q( j/ h) Y; ]# A2 H* q5 M
- eeprom_read_write_byte((READ | 0x08)); // 地址大于255
' o/ Q3 R1 _: _- C5 F - else
/ |8 Q, a% e E* v/ S - eeprom_read_write_byte(READ); // 地址小于255
' O. v- }1 ?" a - ; m1 @3 X) @% q/ M5 d/ C- [2 X
- // 写入地址3 b: h( N) N' P1 T; c' Z7 S
- add = (unsigned char)(addr & 0xff); // 将地址换成8位& {+ v$ U" ~2 e! J. Z' B& s7 t
- eeprom_read_write_byte(add);
. ~ s: K" Q( q$ | - ! ^( ]1 z+ u7 S( O/ O) a
- // 读出一个数据
5 U2 f2 \ K: U6 F& C - dat=eeprom_read_write_byte(0xff);- J! h; C* i6 A3 c7 w
- eeprom_cs=1;/ I5 n9 X5 O: r3 H4 r) |
- return dat;9 d& D" M; k! y: Z4 z0 H
- }8 N& C( c; }5 Z. j6 M% L
- //==============================================================================
1 b7 `- L& i* H - // 描述: 向AT25连续写入数据0 v. {- a2 z5 o8 h A& T7 A
- // 输入: unsigned char *PC 写入数据指针
8 V* C& S4 }) m' d5 W - // unsigned int count 写入数量计数 M* w% {) B. G% K
- // unsigned int SatAddr 写入起始地址. V5 w/ s- I' L1 [
- // 返回: 无
2 w9 M: ]6 q* B( ^& a' i - //==============================================================================
% z) X) p* n Q0 Y - void eeprom_write_buf(u16 startAddr,u8 *buf,u16 count)
& n1 l+ R2 }6 S5 l, o9 Z2 F- Y - { 1 m" s- W$ a! f9 o a3 }
- u16 i;
0 y8 Z) a! W! [" c8 e; Q& P - while(eeprom_read_sr()&RDY); // 读状态寄存器
- T0 }' i( x4 _$ ]. a# g2 J" p; r
7 g) e3 l3 S2 _6 {% z' E- eeprom_cs=0;: y' {1 I( w1 N* Z* h) m. f! q
- eeprom_read_write_byte(WREN); // 写使能锁存5 g# Y, R/ P* a8 W! Z v/ Y
- eeprom_cs=1;
7 w, S+ q. s/ T3 U - eeprom_cs=0;/ d8 I' L2 K/ w$ V' O, o5 _
- - F4 W, N# O! w. e- e5 _! S S2 f
- eeprom_read_write_byte(WRITE); // 写入写操作指令
/ d$ H) d7 S8 o4 Y* h - eeprom_read_write_byte(startAddr>>8); // 写入地址
/ P% i' `. j5 e, _ - eeprom_read_write_byte(startAddr); ) f/ v$ M O* J% N/ G- M
- w( Q! o5 `8 F1 Q% z8 h! ?& H
- for(i=0;i<count;i++)// 写入数据
( C3 R( j5 E8 H: f& Y3 f - { ) m2 y m; g& p6 I0 K9 _9 q
- eeprom_read_write_byte(*buf++);" y& X4 I3 W- Z' e5 _& _
- }
! j$ O v, X5 ~& l - eeprom_cs=1; // 芯片关闭
2 o7 `$ P" t% m+ ?, d5 F& ` - }
! c9 @" r* X5 f$ v - //==============================================================================$ C) O3 h# W3 [( k/ h' b9 Y& z
- // 描述: 向AT25连续写入n字节的数据
. u9 ?* S0 k( q6 w - // 输入: unsigned char *PC 写入数据指针) U8 i, I: [$ _+ c4 q" h; ?
- // unsigned int count 写入数量计数
6 @8 M7 m" l4 |. n C. c; o. w - // unsigned int SatAddr 写入起始地址 ~/ _2 b. q6 g+ b% O
- // 返回: 无) m- F1 I0 l$ `3 p" E& x
- //==============================================================================1 ?1 i v# g% D. _6 o) y+ G
- void eeprom_write_nbyte(u16 startAddr,u8 *buf,u16 count)
) {" s5 _- Q: O0 s- Y8 g7 Q3 {6 g - {& p9 w1 r# e M( ?! x$ p
- u16 pageTotal=count/64;
7 x/ b3 g3 Z \! x& u: r1 T) ] G8 c - u16 pageResidue=count%64;
2 P* ]7 I7 e! Y7 _8 p- ? - u16 i;
/ d1 O v! w' w7 W7 @$ y - u16 pageCnt=0;% K# ]" x5 _, C8 I9 {
-
* R: T8 W; P J4 b7 @ - for(i=0;i<pageTotal;i++)
' E9 e, O" b; w. j - {
) \" ^% z/ }0 c) {" h& l" e$ X - eeprom_write_buf(startAddr+pageCnt,&buf[pageCnt],64);
, a1 S2 ^$ H# W5 _+ W, r - pageCnt+=64;4 t: g5 ]" i% ]# f3 b1 m9 w h8 T
- }
\2 q4 U% A e5 e* l2 A9 y( o - eeprom_write_buf(startAddr+pageCnt,&buf[pageCnt],pageResidue); //写入剩余的
& ?8 [2 ]5 F$ q( M2 p, Q - }7 z* ?/ b8 W2 d% z
! R# ^! }1 X/ m4 O3 C u2 W F& m
( d j+ @! F$ q/ m0 ?/ H- //==============================================================================3 h9 j* J6 Q. l
- // 描述: 在AT25连续读数据4 O: c" f& `7 P2 t" a5 [2 n
- // 输入: unsigned char *PC 读出数据指针. }8 I6 v3 ~5 a9 U
- // unsigned int count 读出数量计数 * C; f/ ^ M- e+ ?. o5 ~
- // unsigned int SatAddr 读出起始地址
' i( P ^" I8 K, } - // 返回: 无 f: @6 C8 ?) m' r9 n4 j
- //==============================================================================3 \& [: S% J. L% m0 }! y3 y
- void eeprom_read_buf(u16 startAddr,u8 *buf,u16 count)
% T$ H1 i+ ^( B6 \8 Y% j - {
% g2 f6 j4 g) p6 k1 R% u) b* u* N( d0 i - unsigned int i;2 w! L( K" K" X l
- while(eeprom_read_sr()&RDY); // 读状态寄存器
) x$ b; t) k: N5 M2 { - eeprom_cs=0; Z3 K$ _( w8 c* k0 o. Z
-
+ ?3 V- I9 I& Y2 F- \& C1 U$ i - eeprom_read_write_byte(READ); // 写入读操作指令
2 E$ h6 ?( f( M' o! I6 M - // 写入地址" n6 [0 y) }; t# d- v
- eeprom_read_write_byte(startAddr>>8); " d: {3 h" A" V$ s) P8 g
- eeprom_read_write_byte(startAddr); 5 X: K- j( A' T7 r
- ! @- u! p2 s$ [/ l( ~5 Y
- // 读出n个数据) g+ M* Z2 G) ]3 h+ X1 \6 G
- for(i=0;i<count;i++)
4 j# ^+ J% L+ `$ E% L' N - {
7 z% ]+ }0 k6 j% y# O - *buf++ = eeprom_read_write_byte(0xff);/ j! T r4 t9 {, `" g0 o( @
- }. g# c9 s6 V- z) `3 |9 g
- eeprom_cs=1;) O' c4 ]) t: l7 \9 ?& q- j
- }
# o" M. t& H- U6 V
9 Q2 r7 X/ y& c* O) U
( K4 S. Y4 z' u. w, w* w- b0 M
复制代码 6 _) y* H# S; a0 n( H( o
|