版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
楼主 |
发表于 2013-10-12 14:30
|
显示全部楼层
C8051F MCU应 用 笔 记7 d- |- s* }4 }/ @$ T
4 V( S6 C. x6 s: {" j/ iAN009 — 从应用程序写 FLASH a- R4 p6 O: g5 H+ P
6 Y, ~8 S* [( [. X2 a' ^1 Z
相关器件
6 r& }: b7 O7 X" y2 Z9 k: I本应用笔记适用于下列器件:
3 J4 T- |' A7 uC8051F000、C8051F001、C8051F002、C8051F005、C8051F006、C8051F007、C8051F010、
6 m( [ U( s# |C8051F011 和 C8051F012。
& l7 o7 }' u/ g0 i1 \引言
& M3 m4 }, A# s* \" S6 E本应用笔记的目的是说明如何从应用程序写FLASH。在应用编程允许将FLASH用于非易失性
, g0 J) ~: z0 t, g6 B; V7 l信息的存储(例如配置参数),还可以允许采用JTAG接口之外的另一种接口(例如UART)进行在
* _: T5 K- t( O5 Y; w$ d* p- r系统引导装载。本笔记的最后给出了如何读和写FLASH的‘C’代码。 " r1 N2 N: [( P5 c a0 t
关键点
* q5 M7 J3 K8 h) B Q; |, P 在应用编程允许将FLASH用于非易失性信息的存储,这一点与EEPROM类似。
d/ S4 M# F' b3 {# i FLASH写/擦除寿命在 – 40 ~ + 85℃的工业温度范围内保证在 10000 次以上。 : @4 Z1 U) q" F3 Z. _* U
FLASH存储器用 MOVC指令读取(MOVC a, @A+DPTR)。 ( M) d- C( _7 d
FLASH存储器用 MOVX 指令写入(MOVX @A+DPTR, a)。
5 I+ w0 z/ G- ?6 D FLASH页以 512 字节分界(0200h, 0400h, 依此类推)。
3 L0 c: X2 g. h- N9 C- E FLASH写操作只能写入 0。因此在写一个 FLASH字节之前,包含该字节的页必须首先被擦除
@' X. u" {8 W9 d(使该页中的所有位都为 1)。 5 u* z( B7 J! x: s* c2 S* y0 ]$ C
在进行 FLASH写或擦除之前,必须根据当前的系统时钟设置 FLSCL 中的 FLASCL 位。
/ ~+ {: {6 G5 Q- z$ e 在进行 FLASH写之前,必须将 PSWE 置 1。
4 T% q* A: a- y, ^; J# v$ Z 在进行 FLASH擦除之前,必须将 PSWE 和 PSEE 置 1。 : P/ ]$ [7 A4 j f4 h/ n( @2 A
FLASH页的擦除操作是将PSWE和PSEE置1并向该页512字节中的任一字节进行写操作。 + c7 r$ t- U7 s8 {$ y" L+ y5 Y
含有读锁定字节和写/擦除锁定字节的 FLASH页不能由用户软件擦除(但是,该页可以由用户
V+ F0 }# x, m4 b& X软件写入)。该页只能通过 JTAG 接口擦除。 6 ]2 c3 b5 R4 V3 [% t( M H
过程
2 m/ l F0 L$ NFLASH 是按一系列 512 字节的页组织的。另外还有一个 128 字节的页,该页位于 FLASH 的
' b% H2 |4 }& r1 |. W+ @顶部,起始地址为 0x8000。由于写一个 FLASH字节只能对各位写入 0,因此在写一个 FLASH字! C+ H/ I/ ?7 q& n4 [- s$ ?( ^
节之前,该字节必须被初始化为 0xFF。一个 FLASH擦除操作将一页内的所有字节初始化为 0xFF。 3 ]' [+ ~+ G/ V6 y/ U7 l4 V/ u
擦除一个 FLASH 页
( w" y" y% w$ l8 H- {. k8 F一个 FLASH 页可以通过下述过程擦除:
% v% y; y2 Q) S! Z' N1 Q9 x1.根据当前系统时钟频率值按 C8051F000 数据表的说明设置 FLSCL(当使用缺省的 2MHz
8 V, R5 S* Q" Q- d! }内部振荡器时,FLSCL=0x86)。
0 j- f3 ?4 U7 b+ k% e5 u" a; c W' W. E4 q6 ^4 q# y$ N
Silicon Laboratories Inc. 新华龙电子有限公司 - _7 o3 W* {6 T( A& I! W4 n
4635 Boston Lane 深圳市福田区华强北路现代之窗大厦A座13F C室(518013) ! G. Q) R5 N8 X
Austin, TX 78735 电话:0755-83645240 83645242 83645244 83645251 . L/ M/ t# K: [! R$ A
Email: mcuinfo@silabs.com (版权所有) 电邮:shenzhen@xhl.com.cn
. ]+ y# d- V o+ M+ ~6 a1 vInternet: www.silabs.com 网址:www.xhl.com.cn , n5 q# R" d# a: v2 z) D
5 {9 h1 G; _# ~; p! T' I
0 Y8 x+ P% n$ H1 o8 j6 ]- W/ AAN009 — 从应用程序写 FLASH ! W% L& I, V# y; c9 {$ C1 ]
" L( x; w9 x3 j3 \
2. 通过向 PSCTL写入 03h 使 PSWE 和 PSEE 置 1。
0 a$ w/ D" P y/ y+ B3. 向待擦除页内的任一字节写入任意值:
8 P& F; C4 q+ p7 A ; 初始化 DPTR,使其指向待擦除页内的地址 . W! Y% s7 ]1 P' l+ u3 m) c
mov DPTR, #address
4 j/ N7 t% c% ?/ \ ; 启动擦除过程
+ t- x( d8 ~: \4 @; G: D movx @DPTR, a ; v% H1 S( K: x& C- T& l7 A* f
4.如果不再进行擦除操作,将 PSEE 设置为‘0’。
$ t+ S; C+ K4 J3 t+ V# X擦除每个页需要 10到 20ms 的时间。注意:CPU内核在 FLASH擦除过程中停止工作,但外4 J: h& y# x ~# q
设(象 ADC、UART、SMBus 和定时器)仍然工作。在擦除过程中产生的任何中断都将被挂起,
( m0 B: ~9 }3 P. z3 ` U直到该过程结束。在写一个 FLASH字节期间 CPU的工作情况与此相同。
; G/ w1 ]% H* s写一个 FLASH 字节
9 d& q4 y6 q0 n7 l下述过程用于写一个 FLASH字节:
( l! u- j' J0 i! q4 g5 D! A1. 根据当前系统时钟频率值按 C8051F000 数据表的说明设置 FLSCL(当使用缺省的 2MHz9 j; P) t: l2 h
内部振荡器时,FLSCL=0x86)。
/ d) r" b N( R* D" P2. 通过向 PSCTL写入 01h 使 PSWE 置 1(PSEE 必须为‘0’)。
; E4 o; n& M+ g! K6 O# `# p3. 写入字节数据。
1 [# ^& a$ y# A* \% ]8 ^9 r! f: ] ; 初始化 DPTR,使其指向待写字节的地址
4 i/ o' h3 s( G2 X9 c0 s: q mov DPTR, #address
7 ^& \; I9 i1 Y/ i* j2 A- R ; 将待写字节装入 acc
) k2 c* r8 C9 w& ^) ^ mov a, #value 6 w! K# C: h, v* X- E- z* I6 z7 ^
; 启动写操作 ) R% s4 O8 S; k
movx @DPTR, a
3 E* Q) O6 f& @& p$ x0 I- T1 k* {4. 如果不再进行写操作,将 PSWE 设置为‘0’。 4 k$ e1 K$ d* P4 e/ P
每个 FLASH字节的写操作需要 20到 40μs 的时间。 8 f) s0 K+ R# q4 @8 {% k5 U: H2 j1 [
更新 FLASH中的数据 " H6 b1 n' {8 M7 M; y
当保存一组配置信息时,经常需要在一组字节中单独改变某个字节的数值。单独更新某个字节" f+ t; O& d* m- ~9 Y- d2 _
(或字节子集)的一般过程如下: . L8 q8 a ?. P2 C: V$ I+ S4 P
1. 将 FLASH页拷贝到一个临时存储区(RAM 或一个已被擦除的‘临时’FLASH页)。
* J! w( ?9 N8 ]9 g2. 擦除 FLASH页的数据。 % T6 W9 V, `$ n3 ^6 G; H
3. 将前面存储在临时存储区的内容复制到 FLASH页中。 : [2 K+ A( }+ m: S& ~ G7 p4 N
用‘C’代码访问 FLASH - Z+ J) o8 _/ V% Y; {
所附的示例代码说明了如何用‘C’程序擦除、写和读 FLASH 内容。由于 FLASH 读操作是
[! |; s; D, J2 N# T/ T用 MOVC 指令实现的,因此用于读操作的 FLASH 指针必须是 CODE 类型。由于 FLASH 写操作3 b: Y. |9 k6 O, c/ s
是用 MOVX 指令实现的,所以用于写(或擦除)操作的 FLASH指针必须是 XDATA 类型。 4 q/ s( n! x6 |' u9 Q( |1 d0 a2 x
1 }$ e6 V$ v9 N0 \3 Z: q
2 AN009-1.0 JAN01 , |0 |" r. p$ \. Z0 M+ b7 T
! F5 I3 H8 }- A( U4 i* n, l i: u5 m$ `! L4 s4 [. i
S- B' g9 c! o; y2 e
AN009 — 从应用程序写 FLASH / F; E, r8 C+ d) `+ B* a2 z1 B
, T2 c3 `8 \- ^: X4 X软件示例 F- l- Y! E) C, Z! F Y9 j
//-----------------------------------------------------------------------------------------------------------------------
, |+ _# ? D: U, a: e3 d7 Z// FLASH_1.c
$ @; h( R5 e* W8 v8 G# n/ U//----------------------------------------------------------------------------------------------------------------------- . Y: @* p9 A" t) k. e
//
: r5 g/ b$ D. R `; i; i' m9 {& B1 N* ~// 作者:BW
1 i. _# s. d. U2 S1 Z+ ~8 G//
' f1 t# U! o, R// 本示例程序给出了用‘C’程序擦除、写和读 FLASH存储器的例子。
, n+ o# x5 x8 p5 f! O// 5 }1 i; ^8 R, w6 [
// 目标器件:C8051F000 或 C8051F010 & \) u6 u& X& \9 H! B; D9 h, T
// 开发工具:KEIL C51
. b! X8 ~5 U, s3 g. ?( W z//
( y( P) P; C1 ]" n, K# Q
3 X7 c- s' X1 O5 b( H//-----------------------------------------------------------------------------
& w; t) j, [4 U// 包含文件
( y- r) r/ j8 C/ R7 _) \- v//-----------------------------------------------------------------------------
8 }4 s7 n# y- \8 l5 G7 F0 ]8 s: |' _2 }% \
#include <c8051f000.h> // SFR 声明
1 C O0 m6 U& \0 g# |. |: `#include <stdio.h> + [1 p( ]+ B5 J4 D8 E
% h% F2 ^' ^ U! p: `/ U& ?//-----------------------------------------------------------------------------
' Z& R. s k+ ]& b, M! [// Function PROTOTYPES / q8 d9 L) U, J5 ?% [
//-----------------------------------------------------------------------------
0 ^, c4 s$ B( t; u! U7 G" Y! k- I$ K$ v3 e
void main (void);
6 A5 d; h# a: ?8 w* c& o% j' l5 ]6 S# s3 f3 V
//----------------------------------------------------------------------------- , W h0 o- t$ Q$ A
// MAIN Routine
) a' F f8 e0 ]//-----------------------------------------------------------------------------
, N* F2 S# w; J+ i: }3 Y- v) H& `! Y, U5 U6 F
void main (void) {
% |( U1 }+ i2 q" j* S q/ ]' a6 k0 J- z5 q e; e% K
unsigned char test_string[ ] = "Howdy!"; // 将被拷贝到 FLASH中的字符串
$ T7 Z. u0 i% O, t6 O( x. t" T( d) b
unsigned char xdata *pwrite; // 程序存储器空间的指针(FLASH),指向待写地址 y/ w) V" C5 Z- Y0 ~
unsigned char code *pread; // 程序存储器空间的指针(FLASH),指向待读地址 ; k! [- T* m$ Y4 i$ ]6 {' b5 g
unsigned char *pgen; // 一般指针 - t( Q l/ f7 u W x* M7 i
char test; // 测试字符 . N( }6 _ ?9 G: i, v" y
& S! v& h! A o# l1 f AN009-1.0 JAN01 3 4 T( N. l9 r+ k9 C, p
; Y+ K5 H& C0 P; d) D/ N$ e* F
+ X5 H% ?2 r( {. `9 a5 ?2 J0 t' \) h8 G1 \/ J
AN009 — 从应用程序写 FLASH
. S6 E% H0 I( o3 l; j7 b
# j% a- C. F" _3 y ] // 禁止看门狗定时器 6 F5 ?7 |( S0 n! l* l3 m0 k/ p
WDTCN = 0xde;
! R# N+ M, E, q$ d9 p1 D WDTCN = 0xad;
1 ^8 K( s" Z. E" K- k // 擦除 128 字节的信息页(位于 0x8000) # t+ x* Q8 ]. L! A4 J1 b6 Y! i: R
FLSCL = 0x86; // 设置 FLASH标度寄存器(对 2MHz 系统时钟) ) `, p: \4 N: T3 y' Y- H7 Q/ m
PSCTL = 0x03; // 将 PSWE 和 PSEE 置‘1’(MOVX 指令对应 6 D. _& |% i4 E; g3 D, h
// 的 FLASH页 0 s) M' j5 ~( q& b* @
pwrite = 0x8000; // 将指针指向待擦除页
* x$ X1 e, ]+ A *pwrite = 0; // 启动擦除过程
* C4 x/ J" i* S$ R8 n PSCTL = 0x01; // 清除 PSEE,PSWE 仍然置 1
2 O5 J4 K' I# P& d @" [ // MOVX 指令将写到对应的地址
2 c; g' ?8 I% A; i1 M9 Z6 O# w3 ^2 J: V+ v5 s& l
// 现在我们要拷贝字符串 <test_string> 的内容到 FLASH页,从地址 0x8000 开始。 , M/ B. t# g3 ~7 b9 `! i: s, ]
) t9 E3 e% G5 c7 d r1 V8 Y# E7 A
pgen = test_string; // pgen 指向源字符串 " b; T: o( h0 [3 t( J/ N
do {
3 P5 M) I: ^2 u* b, O8 m; o, n+ V *pwrite++ = *pgen++; // 拷贝字节
+ b1 N' R0 c- Y } while (*pgen != '\0'); // 直到 NULL 结束符
) \* F7 v) L% H+ B/ a! p( d- [$ g& l# [+ z' i$ S" @' q* x: V
*pwrite = NULL; // 用 NULL 结束目的字符串
: B, d7 Z0 Y9 e% E8 l" f& {! b
8 m+ V9 S# ^: R ]- x" A- e PSCTL = 0; // 禁止 FLASH写 3 ]& U8 B; L4 N) v7 a: B/ O2 O/ a
FLSCL = 0x8f; // 禁止 FLASH写 $ u. V x0 I" e. t! q; Z8 _" f) S
+ w) g+ C: c4 J0 K // 现在我们读写入的字符串
1 N8 L- k# Y2 O1 ]7 F
; m2 a5 O% X% L1 y5 ?* p& b pread = 0x8000; // 初始化 CODE 读指针为字符串起始地址
$ F) m! U6 f2 w4 x
6 i3 Z9 s& D5 Z H" M* c, W1 Z& U8 ?) m test = 0x5a; 3 b! L, M% }, H5 z' g: M8 z
do {
! R' \1 l) v) W2 {* f test = *pread++;
$ F1 M1 ^: P8 `' G! l4 i( f } while (test != '\0'); 2 p( P$ b* \( {9 ^; o. V! t( ~
! a5 h; R! W6 C$ V- A; q2 V, J while (1) { // 原地循环 5 e5 X& a' t( \2 p0 l! d: T" J
} " W" G5 z" e/ `* t: {) _$ o5 k
}
# C# D z& p8 Q8 V
4 X& n* ]0 m& ?4 AN0
+ o; b' ^3 p- e h- ^; i$ j
+ k8 w: x! I- ]9 v5 D% Z, ? |
|