一、源代码
y2 X* k, U8 a9 c& d" L
2 g/ I: u* i; R* a- void eeprom_init()( A) Z: F. n3 I# E' F
- {3 l& Z+ i2 X# G, E" c
- GPIO_InitTypeDef GPIO_InitStructure;! K9 Y: h' Z' G$ c; @$ F
- SPI_InitTypeDef SPI_InitStructure;+ \6 g) ]3 d: x. `& K0 h
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能
) h0 @- }* ]" m6 O( k/ z9 o
, n9 W( a& _( n. U/ N; E. S- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12; // PB12 推挽 , S* @4 J$ S$ O4 J
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
) c! j% \" e8 z' ?" C - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;( r- s7 X2 F! R( D
- GPIO_Init(GPIOB, &GPIO_InitStructure);
9 `. c3 H0 Z8 |; T# u1 M: q5 l - GPIO_SetBits(GPIOB,GPIO_Pin_11|GPIO_Pin_12);% v5 o- B; y5 S* U# r; f
/ r* u% q6 Z* L% }# P- # C t8 _ }9 B- f
- * P" M6 X! s1 r R7 o6 U/ D6 J
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 0 ?1 W$ P' E2 b Y0 p! t7 ~6 u! L
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能 3 R" d% d: ~# f7 H9 y4 f
8 i4 z: f: V2 B8 \. e$ G+ J- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
4 X7 T2 q) ?( ]/ f& C - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出
! T8 L# T- ]* u7 Z - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;6 A* v2 Y3 E; g
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
$ l$ E) l; c0 B
+ r* b0 E- S5 c- J1 n- GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉
, Q+ S+ g& S' `/ q
' [( x( i1 V& y3 Q5 H1 C- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
5 Z2 V$ m5 g3 b/ Q+ v% D - SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
, @% z% Z+ f6 ^4 l! f - SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
1 @. ?; h' M8 T$ F7 W. y: a) s - SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
# A" b8 e" |+ @, \ - SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
8 d% Q- ]. l3 Y# b1 G. n" X. O - SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
/ _. ~3 P# E* O- {2 p - SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
8 @; m5 b9 X. `5 C. X - SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始, H! g/ U; Z' Q7 |% v
- SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
3 F0 r5 u* `- w, m9 U9 L - SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
3 |- E( Y: V0 f3 {% [
' b8 w; g5 B/ \3 S9 v# T- SPI_Cmd(SPI2, ENABLE); //使能SPI外设/ x' y$ W, }9 [9 z
-
% C% K9 @, N, G: s4 S3 G% T( F1 n - eeprom_read_write_byte(0xff);//启动传输
+ {4 ~+ b5 G+ o7 E/ m - }' e6 Z5 m# N: M7 P; R
- //SPI 速度设置函数# _- u% Q: U6 `: {+ H
- //SpeedSet:
T7 Y/ G p5 a5 D# Y' k, ]5 D1 { - //SPI_BaudRatePrescaler_2 2分频
3 {9 y, X; c2 |9 p( I- b" h ]8 f0 { - //SPI_BaudRatePrescaler_8 8分频 : ^6 n( V. F8 a( A+ Z
- //SPI_BaudRatePrescaler_16 16分频
+ t: c3 j9 s: { - //SPI_BaudRatePrescaler_256 256分频 % B+ @! D: e) x3 Y1 A0 {
* z4 t4 _6 ]. U- void eeprom_set_speed(u8 SPI_BaudRatePrescaler)
/ v8 K6 b' i# `4 f* z& _" k Z# o - {
0 ^) o6 u* T+ C/ U. O - assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
& w2 o7 }2 ?# }3 Y% n - SPI2->CR1&=0XFFC7;) m: _& K a/ W; c# g$ X* V
- SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI2速度
, Q3 \6 Q- _$ o1 | - SPI_Cmd(SPI2,ENABLE); 4 Z8 _* J- }; }* ?' d
- 1 N" [- w- g2 Z$ N! i
- }
复制代码- //SPIx 读写一个字节9 p, \4 x z& ~# E' I# ~+ v5 E6 f
- //TxData:要写入的字节, I+ L/ x7 \; [* N& J# Q& h" |) o
- //返回值:读取到的字节$ E: h- L1 V6 n6 }0 n
- u8 eeprom_read_write_byte(u8 TxData)
6 u0 M4 b" S5 p% m: C - { 7 n+ \4 ^4 l" |, `' Q# Y
- u8 retry=0;
2 ^) @* f9 ?$ K! S - while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
& \+ H3 C1 P$ D; F d - {
) v s8 E8 o! p, | - retry++;0 ^( R- C$ ^9 N& X/ v% _
- if(retry>200)return 0;
% x5 [+ v4 ]4 C - }
' U+ l9 u5 g% `; |. x" h - SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据; v; W6 H4 z# B* ]
- retry=0;9 ^: \- Z- L q4 Z3 P0 @+ a1 l
: F' o; y7 v2 a, M; a) J- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位8 y, [) `( [+ p4 n' M" K/ |
- {7 G) o; [8 s U+ B8 i, g
- retry++;
& G1 `# ?$ j' m5 I7 j/ e/ F - if(retry>200)return 0;! C$ d% `# r3 m, H. n
- }
% B3 p s4 ^( {4 G. k, T - return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据
# S- O- Q5 G6 p& s - }
复制代码- //==============================================================================
r2 L& i I; U. F+ b$ ]6 B - // 描述: 在AT25读状态寄存器, A5 U7 j3 g. ]
- // 输入: 无- Z( s, e. M) y/ I# Q5 e1 T6 t4 f
- // 返回: unsigned char dat 状态寄存器数据1 H# A1 X2 c! N! _( ?
- //==============================================================================. b) V: S$ O8 N8 `6 l* }0 O
K7 n6 u& Y! h! A) {
5 e8 J1 M3 e: y5 n% M- u8 eeprom_read_sr(void)
6 {# L: S. x. X- l) ]% \% \' P# v - { & P5 z* { T4 B
- u8 dat;
9 i9 F9 h: [2 C/ w2 D% l - eeprom_cs=0;
4 A) X2 g6 }( ?+ @) P( ] - eeprom_read_write_byte(RDSR); // 定入指令0x05. S3 }7 r. |2 j7 Y. Q; }1 f9 p
- dat = eeprom_read_write_byte(0xff); // 读回数据
8 \' A. C% V+ Z3 h3 ~ - eeprom_cs=1;
& i; a" y7 e- ?+ v' V - return dat;; g4 @: s; Q D5 B. `2 n& u
- }
c, V7 m# e# t L
/ k& e1 _, l! B& Z6 P& |- //==============================================================================1 B) d0 q" w# [" a- l7 u0 j
- // 描述: 向AT25写入一个数据, {8 N% j+ H2 w& k: M- I
- // 输入: unsigned char Dat 字符数据
- N5 J& H4 I5 ` I! X- j - // unsigned int addr 写入的地址8 N: e! m: Z+ q# y) A" l( T
- // 返回: 无5 [; T, J* G6 y2 z* U% ?) I: e! Y$ I
- //==============================================================================
7 k# b7 ?3 [$ ^ - void eeprom_write_byte(u16 addr,u8 Dat)
+ Z5 v8 t+ i; B3 O- d' T - { * c i/ {8 h( u. b. p" ^% `
- unsigned char Add; % i, w0 r4 F3 c" {2 r1 M
- while(eeprom_read_sr()&RDY); // 读状态寄存器+ }$ o( X4 J( _- f1 F5 S: `4 _+ M% U( A
- & a. I" a! f. f8 |2 P/ X
- eeprom_cs=0;
9 X# s. S$ Q% L3 P0 A: w) g; Z - eeprom_read_write_byte(WREN); // 写使能锁存' m! n' B4 b9 Z
- eeprom_cs=1;+ P3 ~! Z+ y! q, y
-
7 b6 \0 Y1 [! C* l: Q - eeprom_cs=0; // 芯片使能
( V" q/ Y# x' {! y) t - // 写入写操作指令
0 K6 V! v6 u+ G8 R4 b {* i1 N4 t - if(addr>0x00ff): l& h* X7 \- ]+ A. k A
- eeprom_read_write_byte((WRITE|0x08)); // 地址大于255
1 M! @5 ]% e E( J+ i$ [, Q - else+ @' r6 p9 x7 J, w& v+ T9 l
- eeprom_read_write_byte(WRITE); // 地址小于255% _; c- b/ }3 U$ c' L! ?
! v: G: C2 ^7 @7 V- // 写入地址- ]7 }8 d) q9 T. T9 P) J7 f
- Add = (unsigned char)(addr & 0xff); // 将地址换成8位
" F: W5 P+ _( h+ x" k( L- | - eeprom_read_write_byte(Add);
6 ^1 t0 f: p8 x0 I" r - % b; z4 C' z' C$ v
- // 写入数据
1 b j# f/ Q3 V - eeprom_read_write_byte(Dat);3 {) w+ K- c( V
- eeprom_cs=1; // 芯片关闭
' s, R6 X: G) Z4 r# Z - }' `& v" o$ \3 d5 {5 i# _
- //==============================================================================1 B( L5 y! s4 o# H
- // 描述: 在AT25读一个字节操作
/ m* Y& }3 X6 R% ] - // 输入: 无
' ?# p4 ?6 A2 U* i) U - // 返回: unsigned char dat 读出一个字符数据! c" D) @" m |: M/ @
- //==============================================================================. d# I0 B- Z5 p) J
- u8 eeprom_read_byte(u16 addr)
& Z3 _! ` @3 V - { ( N& O0 y. m2 {8 I6 u
- u8 dat,add;
! a6 n/ @5 z! G2 c - while(eeprom_read_sr()&RDY); // 读状态寄存器 ) c3 a. _* k* \- S/ \1 x# G
- eeprom_cs=0;
' z* @ a8 t4 t- m - // 写入写操作指令
3 N) q, D7 w$ Q/ e* M2 w - if(addr>0x00ff)' Q3 ?0 p1 z% T( R1 r
- eeprom_read_write_byte((READ | 0x08)); // 地址大于255
5 P( {2 x" [5 S1 A3 q - else
0 _9 f) A8 m) k. q: M, S - eeprom_read_write_byte(READ); // 地址小于255
" I/ ^) B/ S3 a! N; E+ @) h. ?
h: A# ?& i0 A- // 写入地址
: C2 j! u' [3 k! s - add = (unsigned char)(addr & 0xff); // 将地址换成8位
: |" a4 y& `# |; R - eeprom_read_write_byte(add); ! Z& h2 I) A! _
5 l6 ~; R- p; h5 j' [- g- // 读出一个数据
6 X" a8 h( l# H# Q5 I - dat=eeprom_read_write_byte(0xff);
/ M B6 s6 M+ R1 F7 V! _4 n; ?% C - eeprom_cs=1;8 o# ^2 O; @* ^ c7 I
- return dat;5 V8 t" k9 Q2 G. J2 x
- }7 I; T) o) g* C( q
- //==============================================================================6 N4 {6 F6 L9 f, i& O8 g
- // 描述: 向AT25连续写入数据
+ {) q) {# K4 ?- _' { - // 输入: unsigned char *PC 写入数据指针/ o' D9 M) T: e: c2 w
- // unsigned int count 写入数量计数 & N! {( T; N7 `( P# ]% m: B) r+ k
- // unsigned int SatAddr 写入起始地址3 ^0 @# A8 U! L7 V6 W; f( `/ a
- // 返回: 无
# k- s) ?8 V) d+ u9 k - //==============================================================================" T8 A" v* I- J9 S. y" i- y
- void eeprom_write_buf(u16 startAddr,u8 *buf,u16 count)
1 `, ]. }. m. m - { " G- b' Y1 t3 D6 ^
- u8 Add;
$ x) \2 j, H8 @. V. G6 p; m - u16 i;
# [5 l! F4 C& `* c - while(eeprom_read_sr()&RDY); // 读状态寄存器
2 V" o0 W8 u1 K; U% [* ]
V4 u5 Y+ P! X- ] D; A) E: G- eeprom_cs=0;
( z. i( F, W. Z* u9 E - eeprom_read_write_byte(WREN); // 写使能锁存 J; \; C8 g6 R8 |3 n
- eeprom_cs=1;' C* s d# s( X% a, I( S% b
- eeprom_cs=0;
5 z6 S' ^1 G; R3 Z/ n+ l7 x3 n - // 写入写操作指令 0 R4 y7 V [9 E- U+ Z% h
- if(startAddr>0x00ff)
: ^& t6 E/ m v. F% @6 o; N - eeprom_read_write_byte((WRITE|0x08)); // 地址大于255
' Y9 N6 \* G) y, t8 |. p/ m - else! k) M6 \, m6 ?
- eeprom_read_write_byte(WRITE); // 地址小于255
. d6 f0 v; J) c4 l% J# G
; `2 N9 W3 Z% K- // 写入地址
7 A* v# q/ ?+ v8 f - Add = (unsigned char)(startAddr & 0xff); // 将地址换成8位+ f3 x: ^9 j: Z: a2 y6 [
- eeprom_read_write_byte(Add); + I p2 v: r2 l0 e& n
& o% ]3 s! c4 H4 h- for(i=0;i<count;i++)// 写入数据
l- j6 Y3 q/ ?+ E - {
: m0 L6 [; P$ o, I - eeprom_read_write_byte(*buf++);" C3 \6 i/ s4 q8 W2 F' L
- }
9 v! \! g. M+ A% D( n - eeprom_cs=1; // 芯片关闭 / D ] Y) {6 F0 |
- }4 w0 ~6 V6 {( {/ [7 ^5 ~
- //==============================================================================
$ M$ C, m. \) M4 z - // 描述: 在AT25连续读数据- v: T& s3 b0 T
- // 输入: unsigned char *PC 读出数据指针7 r! V* }! e+ F x+ A, t0 H+ q4 [
- // unsigned int count 读出数量计数 ' K' U: z) I; H1 p0 _
- // unsigned int SatAddr 读出起始地址
7 }3 V3 `; X7 m7 S8 h3 v7 | - // 返回: 无! [6 }+ }3 V& W1 j- Q1 x
- //==============================================================================
0 Q7 d, y& V+ a" m$ c; p- C - void eeprom_read_buf(u16 startAddr,u8 *buf,u16 count): T1 x4 O% R9 g6 C
- {
, Q' j1 T* }" ~+ F$ a - unsigned char Add; ! p/ Y; r$ w6 {
- unsigned int i;
% k5 n* H1 D% [( f7 n/ | - while(eeprom_read_sr()&RDY); // 读状态寄存器 + T9 ?" r6 C" a+ h
- eeprom_cs=0;: W# `3 o. R0 o$ r- c0 }' X2 L
- // 写入写操作指令
( _5 E8 Q+ C- c/ c$ @) S6 C - if(startAddr>0x00ff)7 K) J! I/ Q2 q* C+ f% `
- eeprom_read_write_byte((READ | 0x08)); // 地址大于2552 F6 _0 D9 @ Y3 J. `! Z4 a. I+ S
- else
/ F& l9 ]6 \6 o - eeprom_read_write_byte(READ); // 地址小于255
; j: X3 N- Z o+ k4 N4 `
+ K- G# `* ?: }2 a' @- // 写入地址
( ^% D4 O( L1 K2 L - Add = (unsigned char)(startAddr & 0xff); // 将地址换成8位1 @* t: ]6 u+ W6 G
- eeprom_read_write_byte(Add); - m' ]3 W! d5 v. V* L
4 B6 F6 x, ]; p( D, _ ]2 O- // 读出n个数据2 P p8 J# r4 r- G$ _4 Z. m, R6 K
- for(i=0;i<count;i++)4 m! c& p7 u! X1 h& s# w" |; B" C9 U
- {
) L) m) e8 l+ H$ { - *buf++ = eeprom_read_write_byte(0xff);' z f6 u$ V4 T# W- `
- }
2 r a- c2 ?7 }) U8 }' l - eeprom_cs=1;1 y" l& q7 {0 q" ?, Z* k2 Y
- }
复制代码 " o/ `# n/ k3 P* Z4 I" Y4 E
二、测试' l/ Z5 a/ A+ T6 }8 g. r* z1 |! G% E
7 @ l( r* `' n8 \- l
- int main(void)5 S5 K4 U2 G+ }
- {
/ e. w6 ^5 t# g - u8 buf[5]={0x01,0x02,0x03,0x04,0x05},i;2 U9 J2 Q- M# w& c
- uart_init(115200);
6 _5 ~8 M: d1 b4 e0 P5 K4 W - delay_init(); , H/ Q6 u( C: T- @, m" {
- program_led_init(); 5 |9 W7 @2 t9 X9 p7 B! _6 H
- & v# _/ f$ ~- s# Q7 J: @
- eeprom_wp=1;
$ t/ j6 ?2 s- W/ ]4 l - eeprom_init();
) s' t& C: o1 c+ B - eeprom_write_buf(0x0000,buf,sizeof(buf));
, v* s6 R2 _& {9 G - // eeprom_write_byte(0x0000,0x08);
' ^; n( p) r, o& w- W - memset(buf,0x00,sizeof(buf));
: G0 x( T" j. f. Z - eeprom_wp=0;3 M: U3 v8 W+ B" v
- while(1)6 q$ G' G) w5 h" Z2 B7 H# U8 w
- { - A8 Q2 f! N) c6 v
-
, h6 \+ c G$ a - eeprom_read_buf(0x0000,buf,sizeof(buf));0 S4 u- g) u; I9 _; E, K0 }+ @
- // buf[0]=eeprom_read_byte(0x0001);" v O- R. d/ U) y' p
- for(i=0;i<sizeof(buf);i++)% ]" @7 G/ S" U) b1 a; c
- printf("0x%02x ",buf<i>);! ^8 e$ Q" w2 ^% V- @0 n
- printf("\r\n");
( O# C" o- [* R$ s - memset(buf,0x00,sizeof(buf));
X; M. ^8 X2 V# m& P -
1 c: a& g2 N5 F5 D# o" V - program_led_data(0x10,0x10,0x10);
7 q: n2 J/ x; `6 _- m9 v - delay_ms(500);* B, M9 t2 Y& v/ ^1 X: j
- 7 J/ V( o/ p3 [
- program_led_data(0x00,0x00,0x00);& b' F8 `/ _: m H. A0 O5 _
- delay_ms(500); " C; l. m9 s/ n! ?6 s
-
0 k) }. q7 B9 p3 {$ i$ ` -
4 I9 O) T) H( f# @& E8 ]0 s7 q, C0 W9 Z - }5 [: h2 n* ~' Y! E- ?& B
- }5 ]" {) l; F) F" ?4 `
/ y4 k4 D4 c$ t6 P& g
! `( _8 D7 t7 \0 g6 o- </i>
复制代码
p8 L2 g- l* g$ I9 l; B |