- #include "eeprom.h"
. q" h4 _& {6 Q5 S8 M- E# V' |
3 Y( C+ t& |, p) O: ~
% b" U& J# @6 u, R- void eeprom_init()
6 S, e* t9 i# w. B% V) y - {3 q" s3 W7 }6 n9 P
- GPIO_InitTypeDef GPIO_InitStructure;
( {) m) m$ h' @) G - SPI_InitTypeDef SPI_InitStructure;5 H% H: k) k. Y1 d; L
- ) G, \7 d ^, E) p$ M
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOB时钟
' b# I) D! g! c; N& x - RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI1时钟
" j; M. f/ y! X% K
+ z# S4 }: f& _" b5 z' W4 u1 T- //GPIOFB3,4,5初始化设置
6 V `% k7 h+ n" @# `. u( P - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;//PB3~5复用功能输出 # t3 N# M- A/ J+ `
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
& h$ V5 n+ I6 R1 U/ k5 b \$ { - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出* f3 N! a- @" [4 B S7 E5 g
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
n N9 E, J$ a2 |+ t S3 t* p - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
# N2 J/ ~( M5 Z2 p Y+ L7 Q - GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化
/ T( b) G9 F" f -
( q! t* {1 t* F! T! f8 o - //GPIOFB3,4,5初始化设置, e+ \, o+ Y6 s
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PB3~5复用功能输出
/ i) V5 N- R$ P+ @0 A4 g2 } - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能7 c# {7 B# V2 P! d% n
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出: Y) y) N: ^) Z) f& q
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
& O8 W+ H, l" o - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉# h$ P4 j5 U: o" L4 \+ |; R( k& d
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 - H8 u* [8 v' i8 s
-
/ |8 k7 l* O! x% r - //GPIOFB3,4,5初始化设置
2 X; h1 Z. l4 ^$ q# S9 w6 s6 g - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;//PB3~5复用功能输出 , a0 z2 r: m4 g6 K& X; g8 L
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//复用功能- k8 A: j2 i% B9 W& f4 d
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出4 Z' ]! ?9 K, f5 i- l* d2 h
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
; }; P( z1 a6 S. d) i - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉7 D" b# Q3 `/ i
- GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化 : D7 N" G6 f8 h) x2 O
- GPIO_SetBits(GPIOE,GPIO_Pin_2|GPIO_Pin_3);
0 v" h5 D! Y& W# r - 7 x- E+ b$ ^9 D
- GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_SPI2); //PB3复用为 SPI14 x" r& T. ~! _7 n* X' F" a
- GPIO_PinAFConfig(GPIOC,GPIO_PinSource2,GPIO_AF_SPI2); //PB4复用为 SPI1$ _6 V8 w5 x6 S
- GPIO_PinAFConfig(GPIOC,GPIO_PinSource3,GPIO_AF_SPI2); //PB5复用为 SPI1; K1 D! Y: o3 ~0 G
. r: X, F8 i5 a! s( w/ c- //这里只针对SPI口初始化* q( {5 `9 [2 v) h! F \" y
- RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);//复位SPI1 n( c# ^' y( y
- RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);//停止复位SPI16 ^6 G$ `& x" }" n! W c9 G
- * o; R% Y& p k
- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工) ?5 b0 V1 E" Z4 t7 D
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
# C: O0 X `( S7 |# Q - SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构$ x. H4 Q0 L! [3 y/ I% c
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平& c9 }8 |) `- c) Z3 u& C
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
* S) g4 _' u! ]; t x - SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制* g3 w' l) |' e. @) {" R) U
- SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
a1 o! P6 i( E) ^$ e - SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始1 V K! R6 j8 i* f" `1 W
- SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
/ B" u1 q) L- Z/ T5 r) U - SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
6 f" m0 s1 E- ^, b7 R* a! D" V
4 X& e. z# a% }) U5 q, h; x; |1 q- SPI_Cmd(SPI2, ENABLE); //使能SPI外设
4 E! |$ h9 s5 t9 b' D - % [8 E3 ^. J2 P8 m* `; G. B
- /// eeprom_read_write_byte(0xff);//启动传输 % g4 B( r/ L4 m, E. d
- }. t3 Q& V3 I" ?, a' g/ r
- //SPI 速度设置函数7 c( n# S6 R F# F2 {6 V+ f
- //SpeedSet:
( V8 H8 U1 P% H, O - //SPI_BaudRatePrescaler_2 2分频
* l3 o* u+ [3 f1 a8 u( c- ` - //SPI_BaudRatePrescaler_8 8分频 ) H3 s# g$ P' x6 E
- //SPI_BaudRatePrescaler_16 16分频 / _, y3 N8 @) ~2 Y
- //SPI_BaudRatePrescaler_256 256分频
" H+ C: I5 R7 ^8 b: f- k! f! g" M
) Y* H; N4 Y/ Z- void eeprom_set_speed(u8 SPI_BaudRatePrescaler)
: H5 g( h: M& \6 r) l - {
* H) N* p$ ~) I/ I9 V* F - assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
5 d% b! \; i8 _! Q - SPI2->CR1&=0XFFC7;//位3-5清零,用来设置波特率7 y: I4 U0 q/ X" P$ p
- SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI1速度 7 a( N1 Q m! ?- C v4 R
- SPI_Cmd(SPI2,ENABLE); //使能SPI1
* A3 H# k* v/ y# E( ]! J - 6 K. u1 s) c. Y! i) s3 t' s* l
- }
) G$ y) G8 V7 ?* t+ Y
' s- g: S! f. g- //SPIx 读写一个字节' j- O) w& T" H `. ^5 l
- //TxData:要写入的字节" c- y- I: p ~
- //返回值:读取到的字节
; z* V0 I* y9 _6 ^* ] - u8 eeprom_read_write_byte(u8 TxData)
5 Z" @2 a* E' [; t - {
7 c) V) y2 {. \& J8 f0 A: I - while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空
. \& ]& c7 K* B1 v2 }/ D7 ? - ! P- W9 P& z. k) l @
- SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个byte 数据! Z6 P7 `2 k2 \- H( k; y
- 8 o/ }, O$ g I/ |6 f1 w
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个byte
: X& w6 {( J4 d7 K, v5 ` - ; ?2 X! Q1 t9 R# ]* Z6 c
- return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据
3 Q6 L+ z3 {2 o9 q4 G: M; b; C - }
2 [8 |/ c& D0 \1 t+ h' ?9 {
; c' F% F5 t: g6 l- R: l# a/ y; U- //==============================================================================6 P$ g6 z( \; k( f- ?9 g# Q
- // 描述: 在AT25读状态寄存器
! m1 H5 l0 D! e0 b% w/ b/ t {* e9 f6 s - // 输入: 无
/ V4 ?5 d& ^7 }) n# K- S. @ - // 返回: unsigned char dat 状态寄存器数据2 O$ B' S: A: A- y. ~" O
- //==============================================================================/ x/ E# O9 R' K0 \: b/ D# n, T. ^; q% _" p
; e! M8 h9 a" ~- p7 Z7 f+ ^- 2 @3 |; {' S" {
- u8 eeprom_read_sr(void) m! u& k% M6 Q& c! q; p
- { 9 g# |5 R& D; E
- u8 dat;
: \- s9 q" b. C0 f" f5 X* A* s5 X - eeprom_cs=0;
$ l7 S% T' b( Z! H - eeprom_read_write_byte(RDSR); // 定入指令0x051 l, V; }+ F/ { Z; f& d M5 @
- dat = eeprom_read_write_byte(0xff); // 读回数据
7 h! v9 z P3 k7 u5 |9 V9 z - eeprom_cs=1;6 H3 l' i* k6 H3 e% e. q; y
- return dat;
5 d, i0 }+ w0 f1 `( k( Y - }
, I/ y0 A# m0 I- t* y
. d; [# _+ v7 Q& `9 E2 B- //==============================================================================$ e$ K$ \0 `1 O" `. l
- // 描述: 向AT25写入一个数据
1 t1 }: p4 E: e0 a! ^ - // 输入: unsigned char Dat 字符数据9 p6 b5 |: U0 l* d. X
- // unsigned int addr 写入的地址2 s- K5 I* B& h: w# Y
- // 返回: 无3 p$ M1 @" }) x; u2 m/ G
- //==============================================================================
4 y2 [; u3 W2 V/ {4 @ - void eeprom_write_byte(u16 addr,u8 Dat)) A# O; [- y3 `, K. d. S" X; O3 v
- { * c7 m: n5 P# h! ?9 @% L
- unsigned char Add; . n, ~" l* u1 T7 V U& v/ ?" |
- while(eeprom_read_sr()&RDY); // 读状态寄存器
$ m" Q* j+ E- p9 l/ ? -
' I4 S- d; E& c3 B' g7 | - eeprom_cs=0;
: ~6 y0 ~: f1 u9 u1 L, T# v - eeprom_read_write_byte(WREN); // 写使能锁存
6 z% m) {: v5 v - eeprom_cs=1;
6 C6 S `# ~2 }) {6 l7 x5 v - 6 ^( b; v" s, [! {& ]# @
- eeprom_cs=0; // 芯片使能 1 @9 g, v# e5 }1 q1 u j7 M* d
- // 写入写操作指令
4 [' }5 {% Z5 o - if(addr>0x00ff)
% X) }5 e" @, F; f) ~ - eeprom_read_write_byte((WRITE|0x08)); // 地址大于255
# u' _3 X" G4 ]8 ^( A8 d$ A - else* Q3 f/ O* L0 t" q2 p$ Z; o* O% x9 W8 w
- eeprom_read_write_byte(WRITE); // 地址小于255% m3 e9 P7 B, s6 x L) K5 s# E( \7 o
) d8 ]: B( o: }2 G9 d3 `! o- // 写入地址
2 a- \# P) ^$ k - Add = (unsigned char)(addr & 0xff); // 将地址换成8位" m( ]4 t8 M3 M1 k2 Z3 g2 \( Y
- eeprom_read_write_byte(Add);
" a) q4 i8 d5 f z4 c8 | - ) w! O* h( @( A# L
- // 写入数据' p4 {6 ]) O( p F0 x# h+ I
- eeprom_read_write_byte(Dat);
; Z- ~& S# i0 V' m0 O' x$ Z - eeprom_cs=1; // 芯片关闭
' w% A0 L5 ~* u/ [8 u$ z2 H' c - }* K, C4 C' _5 Y9 ]# N. B; [
- //==============================================================================
; l8 Y# y5 y, O& r, c& j - // 描述: 在AT25读一个字节操作
3 ?* E1 p2 Q/ p) Q# Z, t- o5 Q6 q - // 输入: 无: n7 ]% [1 }+ l P
- // 返回: unsigned char dat 读出一个字符数据8 T& Q; a2 |8 B4 Z3 G3 u ^2 ]! T% c/ g
- //==============================================================================
9 C& o3 s5 b$ H9 U+ u - u8 eeprom_read_byte(u16 addr)
3 b( H/ M, M D# g E7 W- j6 A% r, v - { / q$ I0 h8 f1 m" _8 W
- u8 dat,add;) E# p; n9 d; }7 T
- while(eeprom_read_sr()&RDY); // 读状态寄存器
9 E! O2 |3 H+ ~& L - eeprom_cs=0;8 G$ S; m& |' U0 N
- // 写入写操作指令 9 _/ q/ h, ~) ?0 T- c9 ~ F
- if(addr>0x00ff)
3 L6 `+ I. p- S - eeprom_read_write_byte((READ | 0x08)); // 地址大于255+ n: Q, p6 K7 V& h9 H6 Q3 F3 j
- else
/ R) P1 r& m- ]3 c, e8 P5 J& u- e - eeprom_read_write_byte(READ); // 地址小于255
. v2 ]5 H1 }6 T2 H# |/ f
% J- _8 f( Y; d! l" h/ K- // 写入地址
4 I( i ?0 C; ^- ? - add = (unsigned char)(addr & 0xff); // 将地址换成8位; q- ]5 _" P# f/ D/ E
- eeprom_read_write_byte(add);
$ Z+ R7 W$ {! ]# J' `5 g' O: x- v - # l& e/ _. l9 \$ M Q! f
- // 读出一个数据
) c: P3 J( V2 `9 w - dat=eeprom_read_write_byte(0xff);
5 \4 p2 R4 u/ S9 l4 O; t, A - eeprom_cs=1;
* Y3 j J( z9 v t! C4 f# Q - return dat;
6 k1 t6 D, Y0 y% N+ Z& |% e, w - }# y- x. z3 d A2 p6 I/ E
- //==============================================================================
; m: B& O, q3 {1 j - // 描述: 向AT25连续写入数据6 }3 x/ M+ P' k& C4 }% a
- // 输入: unsigned char *PC 写入数据指针$ w: r1 d0 A* ?! E _; P U) t
- // unsigned int count 写入数量计数 ' M5 I5 k+ W2 f6 o0 ]# s) U
- // unsigned int SatAddr 写入起始地址7 c5 t: e% H% m
- // 返回: 无
; N$ P5 [( L# x) f8 O8 I! g - //==============================================================================- k8 u9 r/ T- E6 B* k
- void eeprom_write_buf(u16 startAddr,u8 *buf,u16 count)
/ s7 i, }& f# @0 ^, |6 a( W - { ) s0 P+ g) i7 P5 {6 a/ T2 N8 A
- u16 i;
$ ^ s* y. A$ k n% k - while(eeprom_read_sr()&RDY); // 读状态寄存器6 u. m4 k ~/ O9 A; U
0 C' B" |, V' B4 o& L* T4 Y- eeprom_cs=0;7 t: B& d0 |& j' x9 `9 @) _
- eeprom_read_write_byte(WREN); // 写使能锁存
5 @9 |% p! J) k0 D; c - eeprom_cs=1;4 [6 V: O0 ~0 _; q; `
- eeprom_cs=0;
2 Z4 F' m9 }2 i& |% H: ^ -
, e7 s+ e* V" V# p/ {5 O# z - eeprom_read_write_byte(WRITE); // 写入写操作指令
8 f: |" D1 M/ T, {7 c - eeprom_read_write_byte(startAddr>>8); // 写入地址) d4 E* K$ h- G- e7 d8 b
- eeprom_read_write_byte(startAddr);
$ k! | L5 m+ A, f8 Z
5 f3 s4 A/ s3 p* f$ n, Q4 G. A1 I- for(i=0;i<count;i++)// 写入数据
8 C$ @1 G" ]8 Z/ u6 g0 M v( Q z - { ! t1 M8 v( H, s) m' K5 t
- eeprom_read_write_byte(*buf++);3 I2 ]# |1 Z4 A4 a/ z
- }
2 X# p. @; W# _" F; A - eeprom_cs=1; // 芯片关闭 ) E1 ? v! Z0 B# w
- }- L7 H$ u( t+ u5 V; L
- //==============================================================================$ y" Z5 I2 o1 f
- // 描述: 向AT25连续写入n字节的数据
0 `! r; u( K6 y3 J! k - // 输入: unsigned char *PC 写入数据指针
p( l5 r* X3 m# Z1 d - // unsigned int count 写入数量计数 5 p9 I1 B3 l# v2 S) p
- // unsigned int SatAddr 写入起始地址
! C. U3 ~; l0 K& f. H/ k5 m: t - // 返回: 无1 ]: y+ C' O2 O0 n+ J% u+ U
- //==============================================================================
& ^1 u I; i" d3 [+ \) J; M, c - void eeprom_write_nbyte(u16 startAddr,u8 *buf,u16 count)
' X8 K5 Q* t- {" L% U4 T: o - {- b z9 q2 e8 q3 m
- u16 pageTotal=count/64;# G" N( H, f# h6 k% m) P0 C
- u16 pageResidue=count%64;
& t8 B* \8 C4 U6 }# o - u16 i;" d% @# o# o6 ~/ x a0 h
- u16 pageCnt=0;6 K( U- S8 p1 z) D+ [
-
. c4 ^4 R+ G* Y) J4 O8 C - for(i=0;i<pageTotal;i++)
; O4 L/ x4 C1 u9 a' e; K- k - {
. q# Q. N Y8 C: _5 I; h" r/ y - eeprom_write_buf(startAddr+pageCnt,&buf[pageCnt],64);* G* ^: Z1 d* |2 v" Y. n
- pageCnt+=64;, Y. s: y q1 o! \
- } L) s8 V7 d; j l, K. P8 D4 U3 f
- eeprom_write_buf(startAddr+pageCnt,&buf[pageCnt],pageResidue); //写入剩余的6 b" n; O/ k3 i5 I+ y
- }
" c b. p$ r' o
+ J0 i+ C7 m4 t# M b
/ M6 m+ f$ o, D) N& H- //==============================================================================; e+ x2 K- V9 z7 @4 z" E
- // 描述: 在AT25连续读数据9 s' I- \6 a D) i z |
- // 输入: unsigned char *PC 读出数据指针$ R- a0 a0 j$ H
- // unsigned int count 读出数量计数 . T: {- }7 N, T1 B" q
- // unsigned int SatAddr 读出起始地址5 w! _* t) i* T- ^, C' y: S1 s+ Y- S3 f
- // 返回: 无
7 G2 ]! B1 K! J# t$ A! B - //==============================================================================1 p! c. Q* s: W! O
- void eeprom_read_buf(u16 startAddr,u8 *buf,u16 count)! k: \" L' l2 d5 U
- {
0 }: I6 e6 A% L- N: v: D7 b - unsigned int i;
- p# P4 n, Q' e) |' ?! a! Q - while(eeprom_read_sr()&RDY); // 读状态寄存器 ( G2 j$ U$ W" B$ `' o
- eeprom_cs=0;
6 C2 j% q* r0 L - : G- r: L) Z8 t" s: ]7 f
- eeprom_read_write_byte(READ); // 写入读操作指令 4 H" L' ?6 d9 H/ B1 H
- // 写入地址$ B" D' H% R; J6 b# ^. [
- eeprom_read_write_byte(startAddr>>8);
* ~ t- w% r: T. ? - eeprom_read_write_byte(startAddr);
7 E9 N) z) q e5 X8 \. s n& b
+ t6 e% O7 v5 m5 `# w! e- // 读出n个数据8 O' G+ O1 e$ f/ ^
- for(i=0;i<count;i++)
* c8 J" N$ ^3 M4 V6 E4 |- G' W - {$ T/ ]9 n4 Y0 A1 J- t' V) e' T
- *buf++ = eeprom_read_write_byte(0xff);. L8 g& z! `7 h; l4 Y K( z
- }
9 L0 c Q5 W7 M3 D% u: o$ w) q( H% N - eeprom_cs=1;
1 ^' d, o% b6 x - }
- D0 }1 t& q% K; ^5 ]5 h6 f) R+ | - 5 i0 i2 ?, n: e+ y9 S/ E7 Y
. o1 p7 Y N' Q5 }( j. G
复制代码
- B0 j" P+ l; w2 t l o# R7 l$ L |