一、源代码
) }! e$ v6 F+ h( J% O% U* T' J5 X7 ?" w& Y$ t/ R
- void eeprom_init()5 ?# [. ^! |/ E5 k% }5 z
- {
. Y: U# S4 X7 D; y" w# { - GPIO_InitTypeDef GPIO_InitStructure;* f& G; Y- @9 a; R
- SPI_InitTypeDef SPI_InitStructure;
h; b5 g; b' ]; K$ v: v% u8 } - RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能
6 e- S0 P8 y) B; Z8 I1 } - 3 c, X L( J/ ]+ f
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12; // PB12 推挽 & Q. s1 ?7 \: V# c' Q
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
; H; r3 U& j1 u* A! p* X - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;- }+ x8 a8 G7 ?4 A
- GPIO_Init(GPIOB, &GPIO_InitStructure);
3 i/ }. L* }& Z# @ - GPIO_SetBits(GPIOB,GPIO_Pin_11|GPIO_Pin_12);
1 [& N2 j7 {, f1 F: _1 S - 5 v0 ?. r2 M; [% U6 n2 A
* [' @* o# E5 i D+ `2 B
5 `0 o6 o8 d: r1 ~- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能
/ R- T% b( [& x- [ - RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2时钟使能 " n3 j# A0 d( q( \7 s5 ]: Z
- 9 G( e9 X6 S X: c8 M! e- g
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;. y! K3 _7 I( O- |) e" @0 E# q
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15复用推挽输出
3 @9 k* g6 Z( D, _) g4 Z) Z - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; c V6 z, L0 L+ ^! s
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
3 b6 }4 t+ Q9 ^# F2 I7 J; c
2 S5 `; ?4 {& v- GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15上拉
% y* i( \ Z5 T! j6 Q/ z) C- f
+ U! J0 G( s2 T: C# J9 G, }; \- SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
! b- ]/ f9 S# W9 g+ F! H3 D - SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
5 B4 S; U! {9 k7 y# v1 G$ } - SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构; G0 j: |( Y' E2 p
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平+ B7 I+ @* q" ^$ |
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
D8 g3 G4 _; B( n' R" j - SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
5 ]! M: Y' [7 a3 ^& Y& s - SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256! @# D+ K) ?: [/ \
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始7 W0 I" Z6 @& G' g2 I
- SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式8 L0 E0 ^8 I% e$ v; H& R
- SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
, b0 A7 q4 d1 ]1 d( {, ?6 y) Q3 h
4 o9 ]' A- Y9 Q0 [/ d- `7 f- SPI_Cmd(SPI2, ENABLE); //使能SPI外设
7 B5 j% U# n0 J& r s7 T& G: q -
1 {( S6 t+ W7 U7 S- `5 p# H - eeprom_read_write_byte(0xff);//启动传输
7 B/ ], X5 n8 y8 t3 r/ Q - }- `7 V2 o! q* t# a5 U
- //SPI 速度设置函数
' O' w8 A6 V- c+ @6 @- [4 p - //SpeedSet:
- V' D2 w/ m, d- g9 l' \. X - //SPI_BaudRatePrescaler_2 2分频
0 w0 |* p) H" A - //SPI_BaudRatePrescaler_8 8分频
( |6 _4 e. C6 y" t - //SPI_BaudRatePrescaler_16 16分频
& y1 }$ x9 u$ c' L4 ~ - //SPI_BaudRatePrescaler_256 256分频 , K$ w; t# j9 i
- C- w N0 _ I1 F0 ~* E3 }- void eeprom_set_speed(u8 SPI_BaudRatePrescaler)
0 @% K. `% H( C& H" E2 }/ I& z- x3 S - {
! Y% c* _; {8 G6 u - assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));& }8 [+ |$ g/ ~1 u8 U( }2 ~& G# V
- SPI2->CR1&=0XFFC7;
$ }8 `/ j6 G/ p( d - SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI2速度
! }5 r9 d" v) W* O - SPI_Cmd(SPI2,ENABLE); " H( U" q' O6 P7 Z2 n2 Y
- % t$ t/ ^1 {& }
- }
复制代码- //SPIx 读写一个字节4 C( A& E) H, E
- //TxData:要写入的字节3 l- E$ e0 Q1 H' C. a4 s# \
- //返回值:读取到的字节! R/ _7 p4 }! l9 X9 b* f* F4 F
- u8 eeprom_read_write_byte(u8 TxData); W0 V1 ~- } ?( r
- { & r/ _: C Q. J
- u8 retry=0;
$ w( F |; |0 A0 \( Y- i$ T$ N - while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
) Y1 @% H" D1 V, G - {) Y. F7 n. _) M
- retry++;' y: [, R7 s$ `8 Z" t2 V4 ~0 J
- if(retry>200)return 0;/ u$ Z: ^5 n0 T" J
- } h4 d* F$ Q1 i0 w$ X
- SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
% n) d- s% s3 ` - retry=0;
1 M9 [7 N2 {. D
: y& n3 D- [, Z8 g# g1 z( h' W0 N" g- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
; p# H; o( a9 g! J, ~. z - {
/ x0 C7 l8 P5 _, S- b. j6 I - retry++;
/ j2 F: |6 r# o# | - if(retry>200)return 0;
! v1 y4 ]. [! b7 P - } `, \) i7 _9 O/ d8 O
- return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据 + b/ K6 J/ ]. L0 {4 l7 y
- }
复制代码- //==============================================================================
% l% l0 e. H$ ^8 V/ \ - // 描述: 在AT25读状态寄存器
+ H$ y1 d$ e8 m1 R - // 输入: 无
+ P, @2 D/ f+ c0 z6 S2 K# ^8 y - // 返回: unsigned char dat 状态寄存器数据% S$ y/ n: E; u" I0 Q
- //==============================================================================
' f" X5 c& L$ c7 N1 X$ t - % a2 D% \0 V8 M/ F Q/ x! _" J
+ h/ Y/ o. D6 d3 n- u8 eeprom_read_sr(void)
+ K3 O0 h5 ?. j0 Z& \7 ? - { & q/ ^$ e( E6 _6 _
- u8 dat; . \0 O; S1 J( M7 D
- eeprom_cs=0;
# ]) J- ^& ]6 Q9 L1 }; { - eeprom_read_write_byte(RDSR); // 定入指令0x05
8 k' B& @' m+ U/ g( E4 p3 } - dat = eeprom_read_write_byte(0xff); // 读回数据. N; |* W% @0 Z/ I( p" {. \
- eeprom_cs=1;
3 f' }! W1 z1 @. w. G; Y) O! i - return dat;
9 {4 k7 W! h1 b) n! ?4 Z - }
0 a* @( ^1 S, C& m1 Y - . ?6 x7 {, {8 v) W/ e
- //==============================================================================5 F3 L, r. L; J- d: M1 a
- // 描述: 向AT25写入一个数据
8 H, e& w# `9 Y - // 输入: unsigned char Dat 字符数据
+ F* A8 P( {8 U - // unsigned int addr 写入的地址, c K8 G& b) b/ Q0 i3 W g
- // 返回: 无
: I. m, u9 c8 Z4 e - //==============================================================================7 S# r- y6 W0 g- o
- void eeprom_write_byte(u16 addr,u8 Dat)
5 Y1 u' R5 r5 [* B9 ]/ s - {
# {! u( V) _5 P. j" Q, q) v - unsigned char Add;
( S6 \; D* j7 E6 e; x - while(eeprom_read_sr()&RDY); // 读状态寄存器
( [8 Z: L8 V' B, f - 1 s$ Q0 |+ p/ _3 f) l5 G
- eeprom_cs=0;; f$ F6 a: g% ]1 B2 X. X7 x- I' {) ]
- eeprom_read_write_byte(WREN); // 写使能锁存
3 ]) b: b/ ^/ @) G( { - eeprom_cs=1;. M' e1 |( R4 f
- 2 f3 U$ i" ?: X1 q! D0 J! U
- eeprom_cs=0; // 芯片使能 2 Q \7 R B7 N8 |& c* L, p
- // 写入写操作指令
4 T" J' Z0 ]1 x+ y - if(addr>0x00ff)
7 `' f8 l* L/ Z - eeprom_read_write_byte((WRITE|0x08)); // 地址大于255
. P4 _+ }! w8 Y8 x6 T - else
q' Y5 W g' ]) p7 Z" } - eeprom_read_write_byte(WRITE); // 地址小于255
. W7 c: t; I1 \* a5 z4 g2 o
& r9 g' y$ o$ C, E) f0 y- // 写入地址& e6 z6 Z: A6 Q- n
- Add = (unsigned char)(addr & 0xff); // 将地址换成8位
4 U3 w/ m1 z9 X- i7 n/ @ - eeprom_read_write_byte(Add);
$ t3 v. A% a7 a$ f
7 c% W6 B" G' p4 x- // 写入数据
, _/ F6 Z6 W0 ?+ l - eeprom_read_write_byte(Dat);& L, r$ {, _+ {, J' ^
- eeprom_cs=1; // 芯片关闭 ; Z" X. Y- V1 i5 ?6 {
- }
! X6 q& m7 F) ^3 n" p" H9 a - //==============================================================================
! A' R; Z2 J: `! N( x3 E" k9 N, p" ] - // 描述: 在AT25读一个字节操作" d5 a' R) q6 f0 S% c5 R. X, H3 {
- // 输入: 无
& S! n: c9 R2 S; [ - // 返回: unsigned char dat 读出一个字符数据- k( }4 {0 L+ E2 Y$ B
- //==============================================================================6 w! l4 H) Z ~4 [1 t$ @
- u8 eeprom_read_byte(u16 addr)3 l; C* I9 r% b' f& y
- { 6 F* W9 d0 v! X0 m, L
- u8 dat,add;
# j! I) F. O* m/ i) Y/ W - while(eeprom_read_sr()&RDY); // 读状态寄存器
% s* X3 H; F% O5 c5 f - eeprom_cs=0;$ c: m4 S% P% y7 y9 f
- // 写入写操作指令 2 c- `9 A) s6 ^' h E
- if(addr>0x00ff) X! U$ p% ?8 O, P+ \6 `
- eeprom_read_write_byte((READ | 0x08)); // 地址大于255
7 G% r: i$ ^9 k; Z - else( }! J1 W2 f9 }0 P- C! g& G
- eeprom_read_write_byte(READ); // 地址小于255
7 q7 \7 b* P& q+ X2 ?5 Z/ W
7 ^5 v3 Y- b9 @, `* M- // 写入地址! M% o X0 v) X& E1 p
- add = (unsigned char)(addr & 0xff); // 将地址换成8位$ i, M, x, e: R X
- eeprom_read_write_byte(add);
* X5 }- S0 ]4 d! Z3 G - 5 w' Q( r/ x' }3 i% b
- // 读出一个数据2 f- f. |8 Y3 A r% B5 Y. r r
- dat=eeprom_read_write_byte(0xff);
/ r+ N4 \9 n4 C1 e3 o. D' ` - eeprom_cs=1;
5 S" v; H0 d% {' C! _) ? - return dat;7 O& i# t. s% O& U. P, h! H6 T
- }
* z# k, Z' l# p7 A - //==============================================================================# u; {8 ?9 c) _* N K0 J) m
- // 描述: 向AT25连续写入数据' G" @. V- f3 d& j1 ~( V9 W
- // 输入: unsigned char *PC 写入数据指针+ r) O+ p( x, H9 G- j' t
- // unsigned int count 写入数量计数 7 M* p ?& i7 d7 ]& O
- // unsigned int SatAddr 写入起始地址! F5 h) [# S4 g1 b5 a) ` G6 T
- // 返回: 无- Q* R) C+ j) m4 i$ B
- //==============================================================================( _+ r. }: v0 a9 [
- void eeprom_write_buf(u16 startAddr,u8 *buf,u16 count): m( J3 y, Y; T1 I6 z9 q! E) a0 L
- { 2 z- d) L+ ^. Q' d3 N2 A) {
- u8 Add; ' j0 Y$ e: i: k+ Y
- u16 i;
$ r5 D9 k1 ^- c% g - while(eeprom_read_sr()&RDY); // 读状态寄存器
3 S( Z* z7 B3 ^8 G - , M/ W% w9 S! f8 H3 N: u
- eeprom_cs=0;# G1 }8 S: t8 Z" e: {' P- ^1 d+ A
- eeprom_read_write_byte(WREN); // 写使能锁存7 N. O7 }0 @* K( J4 U
- eeprom_cs=1;+ y, j' i( }0 t1 O/ k" W* {5 V
- eeprom_cs=0;
3 Z" m$ o. \- S5 { - // 写入写操作指令
2 n# ]5 m8 J; x9 [5 V- H - if(startAddr>0x00ff)+ ?0 h3 L" v6 I; k; d+ ]
- eeprom_read_write_byte((WRITE|0x08)); // 地址大于255) j: @6 `' r* j8 V5 f
- else5 `: g" U1 @+ U) H: Z
- eeprom_read_write_byte(WRITE); // 地址小于255
# c# D5 g s R/ k: w - , j5 I3 ~1 p- A, [! E
- // 写入地址2 W2 n5 U* j# w( P8 l% E
- Add = (unsigned char)(startAddr & 0xff); // 将地址换成8位* e+ ]. q S- ~5 a% X
- eeprom_read_write_byte(Add); 0 l' l) S3 k6 e: V/ N* G: c
( Z' A7 z0 j* d5 h4 }- for(i=0;i<count;i++)// 写入数据# U5 T/ u) D. k% S4 I
- { + H; {2 K- w1 n
- eeprom_read_write_byte(*buf++);
& D3 e5 n$ ~' P* E5 I% H: b' L - }; s! ^; t, b O/ `
- eeprom_cs=1; // 芯片关闭
; p. q, z2 u* b0 Y0 k - }+ U" L* Z7 [. T2 k& R* r1 _5 X0 |
- //==============================================================================
! E. x# g! p$ p" E* d - // 描述: 在AT25连续读数据# F9 l6 R! W5 f8 F: K1 X: d
- // 输入: unsigned char *PC 读出数据指针
' p0 @% l V7 h) p9 R) h - // unsigned int count 读出数量计数 `+ W) o! E+ t$ e* H" K7 K2 q
- // unsigned int SatAddr 读出起始地址
8 M, w* r+ M1 f4 [ - // 返回: 无
5 @) [: x9 p- D9 [ - //==============================================================================; q1 `8 s5 W( l- d8 j$ ?$ T
- void eeprom_read_buf(u16 startAddr,u8 *buf,u16 count)
, v( H0 k0 d) h+ W - {
0 K5 `! z6 D2 B0 Q - unsigned char Add; , W% Q9 z R4 d m
- unsigned int i;6 |( ^) p, o7 x+ E: u
- while(eeprom_read_sr()&RDY); // 读状态寄存器 ; ?% T* E, |! x0 H
- eeprom_cs=0;! a9 b' w- T3 U2 {- d# Z
- // 写入写操作指令 ; q4 f4 d# j' a" R! {9 B1 E
- if(startAddr>0x00ff)
8 Y/ ]5 g# V, l! w0 s9 H3 a - eeprom_read_write_byte((READ | 0x08)); // 地址大于2553 K: p+ j% K; j0 ?, a* i, u
- else% b6 @/ Y# N- |2 l
- eeprom_read_write_byte(READ); // 地址小于2554 b2 e7 e+ Z; X H' f! i
0 h& t3 a$ U" c$ R: p6 p& n: ~- // 写入地址
- M, U$ m. [5 l1 _ - Add = (unsigned char)(startAddr & 0xff); // 将地址换成8位* W5 b: ?# L6 ~* a# V- C
- eeprom_read_write_byte(Add); # K- ~0 b7 h1 S, g) v5 V
, I+ W7 J. m: ^8 V2 ~ _- ? x" P- A1 d0 ~& m- // 读出n个数据+ y/ {4 |0 U, n' `5 q/ U0 j2 \
- for(i=0;i<count;i++)4 g2 Y* @9 ?1 V+ [% h
- {
+ @ O/ \3 Q2 T( d2 J. P - *buf++ = eeprom_read_write_byte(0xff);
3 z l# m* t2 t6 l - }8 z. Q" p& t- g/ N
- eeprom_cs=1;
c4 g. n' u" ]9 l, j6 l& \ - }
复制代码
% A" @& [+ L/ Z j. N: @; q二、测试
( v# D! q, m: }+ ]4 V( y i- A: h6 x# m
- int main(void)
0 M" n* y3 i8 E" L$ [ - { 2 M1 D* Z- b& \( m
- u8 buf[5]={0x01,0x02,0x03,0x04,0x05},i;. C7 R; i+ j/ Q4 Z: O' ?) R
- uart_init(115200);
7 @ y! p- y* V- g3 g5 g - delay_init(); - {7 P0 v5 o5 J+ y
- program_led_init(); , k) M. j+ s# j$ d, v( i! B( T2 o* ~
- # v1 J+ h$ t5 m5 k' P! m' b
- eeprom_wp=1;
D& S2 j9 @ w" s3 R$ Q( K - eeprom_init();
7 Z" F' E" ]; B - eeprom_write_buf(0x0000,buf,sizeof(buf));3 k- i& H- p% k( n( J
- // eeprom_write_byte(0x0000,0x08);2 v/ V$ @" H2 V2 J0 C5 X
- memset(buf,0x00,sizeof(buf));
R+ A5 d/ c/ f3 L* l8 k - eeprom_wp=0;
2 b- c# _* k4 ^1 { d+ h - while(1)
/ x. s5 ^$ G+ ]$ o" a - {
. m3 S$ [$ W0 B K8 D7 Y( E5 P -
3 {6 k; ? z, |" ~. R3 a% O9 N/ q - eeprom_read_buf(0x0000,buf,sizeof(buf));
2 u+ Z- D3 T& i - // buf[0]=eeprom_read_byte(0x0001);+ S6 p9 G/ b3 b
- for(i=0;i<sizeof(buf);i++)
- V" K9 D0 ?, y. u - printf("0x%02x ",buf<i>);/ T; w$ v) I2 m8 W- f, W% ?+ R
- printf("\r\n");4 r& w% N) v1 L6 |
- memset(buf,0x00,sizeof(buf));
! Y. J" E% J5 N4 g }) d -
/ S3 r( H4 W: P D5 v% K9 h" ] - program_led_data(0x10,0x10,0x10);
4 o) O W- V& L: w - delay_ms(500);
: v n3 Q+ g' Q# t, L1 A5 J$ ~
, |( L+ e3 D! Q7 G- program_led_data(0x00,0x00,0x00);( G8 W2 m, ?# B' \: J
- delay_ms(500); 6 K& h' z) p9 K5 m
- & v3 j1 A* l9 b7 ^: J9 _
- ) U( J2 N4 D5 u4 q# _) V5 `% T3 ]! p; r
- }; A1 I8 V6 } k" S+ W6 {- H& M5 `# }) a
- }: g; e1 J- ]' ?0 |- }. H
- 3 m+ a1 |# `# K7 {+ I4 k
- 1 r) \& O( A. _
- </i>
复制代码
2 u" g* n$ Z4 J6 o% Q. u |