- #include "eeprom.h"- I' E+ P" X1 D3 ^- x4 m
- ) j- D4 [3 ?5 M5 I0 \$ c
0 ]# G) k G/ z! z! M9 l% r# _. P- void eeprom_init(): b. w- m- T8 ~; |3 P& k
- {
0 P" V; Q" E6 v - GPIO_InitTypeDef GPIO_InitStructure;
0 U% u! a$ P- L5 M, J" J) ` - SPI_InitTypeDef SPI_InitStructure;" V' S. g2 |3 m( V! ]! v7 e
- 7 _4 s4 C8 X* N
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOB时钟
6 i" @; M3 j' Y( U: r - RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI1时钟' O$ W3 f( h( n& V" m
% m6 U0 R. e1 g8 a4 p( | P- //GPIOFB3,4,5初始化设置
/ A' t) g3 x S' N9 ]( F0 r% k - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;//PB3~5复用功能输出
8 W% O8 ]$ w) ?0 H# [% H b - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能2 S p2 A# t8 I1 i! E, t% [
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
' x- l I' d Y1 U: \1 z/ |) V3 d: u - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
, i, q3 u8 w% _: |" p - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
. V, b+ J" l' f; N! b$ E4 F - GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化7 x( J5 _+ k+ q& e* Y1 c' [
-
; Y* {$ P C$ r1 A4 n# ?5 K# O0 W - //GPIOFB3,4,5初始化设置
. F6 P, i8 E0 _% y! L - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PB3~5复用功能输出 : w9 o- j& b$ P
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能& M- a; g/ d/ X( U3 U8 Z0 V
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
6 q% _1 Y: a9 L9 P - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz! \* N3 B1 Z. ?8 B* \( {% `
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉4 {& T( ?, P- |# \! \; `; _
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 : n" g- l/ `% |7 M. r7 S& T
-
9 W8 K6 F7 |9 H - //GPIOFB3,4,5初始化设置
# @1 a: s P9 D. h2 g- _ h - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;//PB3~5复用功能输出
A0 R% b' g3 F% { - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//复用功能
, N0 B& x9 d; ^7 M& c1 d( F - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出2 a; T1 ~7 ~+ N# N
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
4 ]. `1 F v3 t- a' ~$ ~ - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉: f( f1 n! U0 ]* n8 \
- GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
8 e; O, l( s2 o) K - GPIO_SetBits(GPIOE,GPIO_Pin_2|GPIO_Pin_3); / r% Z1 z8 k7 l5 X; V4 i
- ! d/ n! Z$ M! d+ g
- GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_SPI2); //PB3复用为 SPI1
. L0 I* t, D* t4 w* V - GPIO_PinAFConfig(GPIOC,GPIO_PinSource2,GPIO_AF_SPI2); //PB4复用为 SPI1
6 q' }: a# x+ s7 Y _/ I - GPIO_PinAFConfig(GPIOC,GPIO_PinSource3,GPIO_AF_SPI2); //PB5复用为 SPI1
2 [1 v" B C( _+ B1 \6 w
; C" g" P( _9 l# `4 Q" t- //这里只针对SPI口初始化" J' A$ Z' F7 ?2 R+ B8 N8 ~4 Q
- RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);//复位SPI1
- b0 _+ S; T* p8 T. ] - RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);//停止复位SPI1
( g+ x* e% }7 z/ x
8 J- V. `. V" s- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
$ u5 M& J% H" g1 H* _/ A - SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
, O+ A7 E5 @7 W7 C' t - SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
0 n2 B3 u% Q! X; F/ F, ? - SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
3 f7 s _8 S1 {. M1 O3 n ^- Q - SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
8 V$ c* R7 h+ @' q' d - SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
! v' ^* w z$ L4 C) d3 a - SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256* r8 _* w3 @* N6 o/ w% j
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
4 L1 v* ]$ ]2 N3 `: {# z6 J - SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
* U( z) t- u( S* X - SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器$ ^5 S- J1 y) o4 T
- ( a1 F; ~ Q1 W# V4 g7 ]; A" u$ s
- SPI_Cmd(SPI2, ENABLE); //使能SPI外设- N' s$ }4 r }2 p
- + }7 S8 ~0 J' B! |! \# l
- /// eeprom_read_write_byte(0xff);//启动传输
/ z4 |; e/ }7 _. w% m - }* C% Q) z" W3 g8 G6 ^
- //SPI 速度设置函数* O$ _8 W/ J \! C0 e
- //SpeedSet:
! c9 ?. E/ G( M# x! `9 W; K - //SPI_BaudRatePrescaler_2 2分频 - x+ A3 m& w5 L: J& S: Q$ F
- //SPI_BaudRatePrescaler_8 8分频 " H4 e4 R" a& [% a, R7 E% C: S
- //SPI_BaudRatePrescaler_16 16分频
! W7 P! [) J% o5 ? - //SPI_BaudRatePrescaler_256 256分频
1 _& U3 w, O" }' X- M0 E
% U, e# g- ^% ^1 S7 F3 N% W* z- void eeprom_set_speed(u8 SPI_BaudRatePrescaler)1 Z x# [1 M9 J @+ y
- {
* s6 @$ T8 n6 P j/ J( r2 v - assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
7 l5 q5 w8 i. b/ W - SPI2->CR1&=0XFFC7;//位3-5清零,用来设置波特率 X. F4 {% s. l2 d
- SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI1速度
" t. q) Q5 r! [1 t$ | - SPI_Cmd(SPI2,ENABLE); //使能SPI1
7 B8 L/ s; ^' d$ m5 \: u" Q - 5 ^ i! e0 Y+ I' C0 t8 e, N
- } * R3 l+ f$ s" M) E6 g
- + o' ~& q7 S+ S0 @$ V
- //SPIx 读写一个字节
- Q8 C: J8 U3 x9 `4 J5 s$ r - //TxData:要写入的字节# j- I+ P% E/ P. Y& \
- //返回值:读取到的字节
0 B2 r* Z8 W, s - u8 eeprom_read_write_byte(u8 TxData)+ k& ?( g8 Q7 z# ]% K8 L
- {
& o/ U) b1 `2 m6 K) X7 o" W - while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空
; A; R; S2 H$ Q1 V$ W7 m7 z
' M5 g# O: [+ J5 W! }: G8 D& o9 S& u- SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个byte 数据& a1 `+ Q- i2 h
- + o4 E6 C5 M0 G* K$ y3 M3 L
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个byte
! A, B# J, X; N( ?0 X6 P2 K
0 D+ j* F. \: e# Y9 I E; D6 {& I) R- return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据 # O" x. T' o8 q: J
- }
! x$ W. t# O$ y+ @7 C
8 p' J+ [5 g+ W, L- //==============================================================================
2 Z1 n- o' u* j/ ^5 X! }% s$ Z - // 描述: 在AT25读状态寄存器$ c# h1 D# e- t" X. }5 r8 L
- // 输入: 无
3 b" o0 T/ ^! T$ A - // 返回: unsigned char dat 状态寄存器数据
( [; c7 ]( \- |% K6 @ - //==============================================================================
+ x' N2 S% Q& {4 H& T
% W% Z( e% i* P5 N) x) m$ r5 D: P- ) C+ w3 b( `5 \- A4 G
- u8 eeprom_read_sr(void)& T7 k( R7 f/ F& e( C3 Z0 t
- { ( N' t2 v" L Z. T
- u8 dat; ) ?3 R( `* C" s4 \9 @( U
- eeprom_cs=0; ' H1 l2 F% R& C6 W7 T+ p2 E
- eeprom_read_write_byte(RDSR); // 定入指令0x051 P# X1 I+ O3 F' C- J6 y) B
- dat = eeprom_read_write_byte(0xff); // 读回数据7 c1 ~/ o7 h; `. y* h+ e- C6 [7 W
- eeprom_cs=1;
; Z+ } r+ r0 J- M: U$ O - return dat; p0 Z H% l! y! b7 o
- }
" G9 h8 W+ y) E0 @0 O - . D% f0 b; W9 N: M% _
- //==============================================================================0 Q W" T# f/ {' }" c
- // 描述: 向AT25写入一个数据
' W& b' T! ]) r" [6 e4 h - // 输入: unsigned char Dat 字符数据7 B8 n' T$ P7 ~+ @! k! A5 M
- // unsigned int addr 写入的地址6 a8 |$ }* \: ?& A
- // 返回: 无
A- n7 A4 X& y! X/ K8 D8 H - //==============================================================================
0 z4 z7 Y6 E' J( N) U5 m/ k - void eeprom_write_byte(u16 addr,u8 Dat)6 f% ^9 K/ }6 l# J2 `
- {
& L! ?' g Q. \% @0 a - unsigned char Add; - `5 {+ E: N' l2 {8 K9 K& \
- while(eeprom_read_sr()&RDY); // 读状态寄存器
{( }- Y5 k# k' ` - $ g0 Y; i2 R% V: J( ~
- eeprom_cs=0;2 g! a: V1 N8 y2 G
- eeprom_read_write_byte(WREN); // 写使能锁存
& y N8 h- y* u3 S; { - eeprom_cs=1;
, b6 g1 ~: L$ S - 3 ]" _1 D, }) S
- eeprom_cs=0; // 芯片使能 * e7 y$ T4 y9 H* l2 L- |2 z
- // 写入写操作指令 + S, H2 ^$ e3 y& F; o
- if(addr>0x00ff)
0 G$ Z7 l; r* p( |3 K - eeprom_read_write_byte((WRITE|0x08)); // 地址大于255# U4 G& Q' z* G! d
- else9 U0 x% k; I1 I
- eeprom_read_write_byte(WRITE); // 地址小于255
' L; Q; R% J6 ` N9 O8 i( \* E - " ]6 R" S8 K6 Y" l- R
- // 写入地址
6 ]* _3 e) G1 v L+ I9 i, \ - Add = (unsigned char)(addr & 0xff); // 将地址换成8位
, H, O/ M" M+ s3 n% a% D$ X4 J5 V5 I - eeprom_read_write_byte(Add); 1 d+ Z' Q; r4 e i6 m
6 ?5 M/ A. ~2 m. X' u: l* d q- // 写入数据
! H( O8 P4 \' z3 n5 ^8 i2 q - eeprom_read_write_byte(Dat);5 H9 o4 G _, D
- eeprom_cs=1; // 芯片关闭
3 M$ k) }1 m' g1 u. ?9 m& \ - }+ }9 D8 p z0 o$ Q8 i
- //==============================================================================
~3 ~7 T. n( H! D - // 描述: 在AT25读一个字节操作
. N$ G8 p5 H9 ^/ ~ - // 输入: 无/ v1 V7 K1 F' U: T4 H
- // 返回: unsigned char dat 读出一个字符数据" a+ D; ^& s* I4 @ L8 \" G3 _- P
- //==============================================================================
5 l3 j8 O5 g: C4 ?# i) P) X' p5 W$ H - u8 eeprom_read_byte(u16 addr)6 d! S7 A+ s$ [8 v$ U1 r
- { 3 o$ ~5 G! X c* ^- g Q8 n# S) t
- u8 dat,add;/ }2 r' L1 H' B- n$ A! O
- while(eeprom_read_sr()&RDY); // 读状态寄存器 8 m0 Y0 K; x+ {( `& X! w
- eeprom_cs=0;
- o1 u3 J. I' ~9 ]) B* U; Z3 I - // 写入写操作指令 7 P7 q' m0 h, ]3 D. u
- if(addr>0x00ff)8 q3 t6 I7 ]* u. C( B. C
- eeprom_read_write_byte((READ | 0x08)); // 地址大于255
. ]% ^) U1 u$ Y8 e4 o - else' m, D9 U9 e/ b8 y: M
- eeprom_read_write_byte(READ); // 地址小于2557 A$ }8 A1 f& N
- , f# V5 i8 i4 D/ `) {
- // 写入地址
3 R# o$ J/ [" J - add = (unsigned char)(addr & 0xff); // 将地址换成8位
7 f# A/ K, S, L- Y- ]% N - eeprom_read_write_byte(add);
8 _6 R0 c9 X; h0 R - & T) q7 q2 d8 l9 G
- // 读出一个数据
% t3 |. Z/ c6 H2 E. \- x# E! D/ x( n - dat=eeprom_read_write_byte(0xff);( J9 N4 y& l1 M8 V: `
- eeprom_cs=1;
2 B3 i1 \( q$ U) O) _ - return dat;
- m0 e6 T. S. F! T: m1 ^ - }# s1 H4 z4 J( N# K
- //==============================================================================
4 ?$ o% F. }! J6 h/ i, b4 f6 R - // 描述: 向AT25连续写入数据; e& k0 A5 L) E
- // 输入: unsigned char *PC 写入数据指针; ?) z6 n4 K, C5 g& n: `% A
- // unsigned int count 写入数量计数 ! h& }. n' H! p* [) p f4 J" k! {
- // unsigned int SatAddr 写入起始地址. o# _/ N7 Q: p7 A2 f* B4 J
- // 返回: 无, A2 X. g! u4 P+ g/ ?: y# s
- //==============================================================================
+ c( x( ^8 p- l6 x - void eeprom_write_buf(u16 startAddr,u8 *buf,u16 count)
6 K Y# Y$ B, | - {
) k6 k. _( x" x4 M" a0 J - u16 i;: d8 W# G5 q5 x% w1 K
- while(eeprom_read_sr()&RDY); // 读状态寄存器
" ]- z" Q, i6 x( b
- v/ J4 {; O$ F5 `+ a- eeprom_cs=0;0 P$ D, b6 n' g7 A
- eeprom_read_write_byte(WREN); // 写使能锁存! i b. F- g9 O9 ^* n
- eeprom_cs=1;5 d8 D# B! X. t3 D! N" H
- eeprom_cs=0;
/ [9 P: u, k- b -
) C+ ~+ x' O0 |3 k* I4 K1 X - eeprom_read_write_byte(WRITE); // 写入写操作指令
' |( k( h5 O( f% A6 ^$ `& Q% ^ - eeprom_read_write_byte(startAddr>>8); // 写入地址1 |' S+ q6 m4 s9 ?% d* f
- eeprom_read_write_byte(startAddr); - [) L: z- Y8 U0 ^# q6 r# G% B' c
: T3 \0 A5 L: \5 E8 [6 E- for(i=0;i<count;i++)// 写入数据
y* L R* x. w1 N S8 { - {
: {. q" k% Z6 ?1 _ - eeprom_read_write_byte(*buf++);
. k2 E8 i- E0 P3 P N9 g - }
9 s* K, t2 [( h" h& o7 D - eeprom_cs=1; // 芯片关闭
, r: b, q4 l7 a# F% `' Z8 Q+ X* T) d; N# f - }' g; F5 C; j8 w( o2 q; \2 I
- //==============================================================================4 P) w# ^% j2 B6 E1 u: _8 Z/ Q
- // 描述: 向AT25连续写入n字节的数据
1 |' F# x# U% ~/ T$ {+ D+ p) c5 k - // 输入: unsigned char *PC 写入数据指针! `% c( c* W/ Q" }; t L! c' ~
- // unsigned int count 写入数量计数
% N) V l9 u& p0 O! ~1 I* c6 I - // unsigned int SatAddr 写入起始地址
6 _% O1 h% \( s( O! T: t3 P - // 返回: 无
, B) `" t3 z7 ~0 n' ?! V- I4 } - //==============================================================================
4 d! g' `8 H" n/ c. [# h: e8 T - void eeprom_write_nbyte(u16 startAddr,u8 *buf,u16 count)( W4 b, W. ^ w% \) g
- {) N* w- E$ y1 O [7 o3 [! ]
- u16 pageTotal=count/64;/ B7 X1 k! V3 g& _ c
- u16 pageResidue=count%64;2 E% l, B$ C: P! i
- u16 i;
+ O, L7 G. i' f3 Q g: S: |4 G/ I3 f6 I - u16 pageCnt=0;
/ R3 ?$ S' r7 U) \$ ]8 a. n) b -
( E1 O" P) H1 d - for(i=0;i<pageTotal;i++)
" c4 W% I# p8 Z7 r( _9 v1 W3 t - {
0 Y7 ]1 w$ ]4 z - eeprom_write_buf(startAddr+pageCnt,&buf[pageCnt],64);& u$ |6 S/ e) u
- pageCnt+=64;0 R5 u% r8 S @# X5 ]8 D
- }6 J$ F: \4 b; u
- eeprom_write_buf(startAddr+pageCnt,&buf[pageCnt],pageResidue); //写入剩余的4 r" }' N) |" A9 _" V) t5 E
- }
* Z5 r1 w( F" x+ n8 w" W
$ r' s$ z2 P; k C& T- + [! Q. i. y5 P {5 F
- //==============================================================================
" L# h# [# ^+ u( S5 R - // 描述: 在AT25连续读数据
' h2 z9 n. V1 j" O* q& \3 z - // 输入: unsigned char *PC 读出数据指针: y% U6 B1 G/ f% ^5 C
- // unsigned int count 读出数量计数
7 g6 I; v/ _( ~0 M - // unsigned int SatAddr 读出起始地址
1 n( l) x' U' u o - // 返回: 无1 B7 k# I, O _/ \% R- H9 b7 [! q
- //==============================================================================
: E3 H Z9 ]; i4 j* B! W/ i - void eeprom_read_buf(u16 startAddr,u8 *buf,u16 count) g8 y2 m. t1 ?2 t) [
- { % n. X) O; L: Q8 ^% e/ T" P' X% n# a
- unsigned int i;1 k( H; r# }, t
- while(eeprom_read_sr()&RDY); // 读状态寄存器 # J) f( w% K1 q, h0 s/ t
- eeprom_cs=0;
( n% m2 z! p' a ?7 K - 5 L% {' }: ?1 K0 E- v2 K. w' f+ ?0 U
- eeprom_read_write_byte(READ); // 写入读操作指令 2 C4 s$ p: n- A+ ?$ U
- // 写入地址+ l9 d% y7 C/ i8 ?
- eeprom_read_write_byte(startAddr>>8);
: u' `$ r* t0 B - eeprom_read_write_byte(startAddr);
' y. q( |, U4 n7 f4 r# u - 5 n9 a# o4 X9 N
- // 读出n个数据
# d) x+ r8 ^& I+ s/ @# @" f' e! a - for(i=0;i<count;i++)
$ ]) y' s5 A ?# @" E& u - {( O9 u$ Q* W. K, m0 o4 _
- *buf++ = eeprom_read_write_byte(0xff);
: d9 i( \5 ]" ^: s; Z - }$ |$ q8 @9 ?& U! @3 v {
- eeprom_cs=1;' V, F* x2 J; A, t
- }
* x6 b- n( c+ r* r( \/ N7 z! W7 s
! x" V/ b/ h7 m7 u" L1 z0 D- ' [; W' U4 S: [; Y8 T N
复制代码 / u ]$ K. y0 W) {- X0 l
|