版主
主题
帖子
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
楼主 |
发表于 2013-10-12 14:30
|
显示全部楼层
C8051F MCU应 用 笔 记6 \3 h5 q6 D9 r
* N$ s9 ]" l+ U6 X' B* @AN009 — 从应用程序写 FLASH
0 x8 s$ ~7 k/ @6 ^3 u4 H( z, o; T+ p$ q
相关器件 ! J; v2 A+ }) P
本应用笔记适用于下列器件:
# i/ E; s' R1 E y" FC8051F000、C8051F001、C8051F002、C8051F005、C8051F006、C8051F007、C8051F010、/ J' F6 @6 V7 W2 p* B% }) G$ J# q
C8051F011 和 C8051F012。 7 m0 s7 A+ f' _" Z3 b
引言 - _( d) m* _% t* B$ D
本应用笔记的目的是说明如何从应用程序写FLASH。在应用编程允许将FLASH用于非易失性
6 K% W' u: V$ @7 c信息的存储(例如配置参数),还可以允许采用JTAG接口之外的另一种接口(例如UART)进行在
, @( b# m# Q1 H/ N0 b0 {1 ]系统引导装载。本笔记的最后给出了如何读和写FLASH的‘C’代码。 * t' B0 v# K) J: E; G; L9 f1 k) o5 W
关键点 ( q' Y1 Q, f: h2 ]
在应用编程允许将FLASH用于非易失性信息的存储,这一点与EEPROM类似。 - r0 w2 e) b, B2 S4 g
FLASH写/擦除寿命在 – 40 ~ + 85℃的工业温度范围内保证在 10000 次以上。
. a7 d3 M' I! N( C8 b FLASH存储器用 MOVC指令读取(MOVC a, @A+DPTR)。 0 _# o/ e. n9 J5 a
FLASH存储器用 MOVX 指令写入(MOVX @A+DPTR, a)。
7 O0 t3 c/ x7 p4 _8 g) z2 E* t FLASH页以 512 字节分界(0200h, 0400h, 依此类推)。
* G+ l, D9 b9 }( ]* f1 v! I8 u- z7 x FLASH写操作只能写入 0。因此在写一个 FLASH字节之前,包含该字节的页必须首先被擦除2 T% A4 W& }/ r7 o: b# x
(使该页中的所有位都为 1)。 : @7 B5 p( x$ j0 y& R$ o0 |
在进行 FLASH写或擦除之前,必须根据当前的系统时钟设置 FLSCL 中的 FLASCL 位。 1 G& _$ ]- i: w2 d; u4 p: F
在进行 FLASH写之前,必须将 PSWE 置 1。 B; p/ J+ p3 }4 X3 S
在进行 FLASH擦除之前,必须将 PSWE 和 PSEE 置 1。 # H2 y# G6 X: h; M) z9 l% p+ V
FLASH页的擦除操作是将PSWE和PSEE置1并向该页512字节中的任一字节进行写操作。 / \; D: `8 b6 P/ `, J/ X
含有读锁定字节和写/擦除锁定字节的 FLASH页不能由用户软件擦除(但是,该页可以由用户
" A4 q y2 w2 C5 |* y! G3 r, M软件写入)。该页只能通过 JTAG 接口擦除。
" B6 v/ Z! p7 }! s! p+ A* f过程
3 w' p H! O. X( S# _& }FLASH 是按一系列 512 字节的页组织的。另外还有一个 128 字节的页,该页位于 FLASH 的; p1 l; h1 F9 P$ D4 |. ]" a
顶部,起始地址为 0x8000。由于写一个 FLASH字节只能对各位写入 0,因此在写一个 FLASH字
% f8 R8 D, T- m/ ]3 ?) i' O节之前,该字节必须被初始化为 0xFF。一个 FLASH擦除操作将一页内的所有字节初始化为 0xFF。 $ h1 P/ b- ^1 G4 [& G4 a
擦除一个 FLASH 页 . H" b! d' `, c& z
一个 FLASH 页可以通过下述过程擦除:
& {2 l6 B8 v, ? j/ t4 N1 z1.根据当前系统时钟频率值按 C8051F000 数据表的说明设置 FLSCL(当使用缺省的 2MHz
. E1 r+ M6 a y5 |内部振荡器时,FLSCL=0x86)。
' t- B( Z; s3 r, f0 g5 ?2 W+ E7 k; m6 Y& B% W4 ~& n2 z
Silicon Laboratories Inc. 新华龙电子有限公司
o/ s- t; K! u* V. R" F# b4635 Boston Lane 深圳市福田区华强北路现代之窗大厦A座13F C室(518013)
6 |5 Y% e' J# jAustin, TX 78735 电话:0755-83645240 83645242 83645244 83645251 & u+ G1 z1 G6 T6 p8 }5 I. o1 H
Email: mcuinfo@silabs.com (版权所有) 电邮:shenzhen@xhl.com.cn
, w/ e( p" V0 p% P' \( zInternet: www.silabs.com 网址:www.xhl.com.cn $ ?( `0 I5 n+ q* o3 Y0 r
! u) @0 c4 t3 y9 U- }: m
" _/ q: D# z* V" TAN009 — 从应用程序写 FLASH 4 x0 M! \) `. W/ h7 |, ]
# l1 @, W* H. J1 I: T# o2. 通过向 PSCTL写入 03h 使 PSWE 和 PSEE 置 1。 4 N& I* [2 t/ q) \
3. 向待擦除页内的任一字节写入任意值: 1 ?: B( p. L3 g/ S" F5 ?
; 初始化 DPTR,使其指向待擦除页内的地址 ' f! U! Y/ a& c- Y" v6 X" X) X9 ]
mov DPTR, #address
* e* M/ T+ q5 i ; 启动擦除过程
5 w1 X" _! U$ N6 N movx @DPTR, a & L3 F+ t& S9 d7 _8 o
4.如果不再进行擦除操作,将 PSEE 设置为‘0’。 [/ W1 N! c- a! p! X0 `5 o
擦除每个页需要 10到 20ms 的时间。注意:CPU内核在 FLASH擦除过程中停止工作,但外
/ a9 L5 k5 y1 U) b K; a$ P设(象 ADC、UART、SMBus 和定时器)仍然工作。在擦除过程中产生的任何中断都将被挂起,# s5 Y9 Y* G. U9 M
直到该过程结束。在写一个 FLASH字节期间 CPU的工作情况与此相同。 0 A( I: n0 f- f% u( |- v9 i
写一个 FLASH 字节 , G z& L" w; C- L
下述过程用于写一个 FLASH字节:
. M: {% [+ D7 C! K, C0 s- C7 M+ G$ f1. 根据当前系统时钟频率值按 C8051F000 数据表的说明设置 FLSCL(当使用缺省的 2MHz
' i w4 I& ?) O内部振荡器时,FLSCL=0x86)。 8 H& N/ A6 N, G6 `
2. 通过向 PSCTL写入 01h 使 PSWE 置 1(PSEE 必须为‘0’)。 9 ?9 Q* X& I9 ~, T- ?& p
3. 写入字节数据。
6 N, }$ z3 u6 N0 o ; 初始化 DPTR,使其指向待写字节的地址 . I" }: T# A/ T# v8 |
mov DPTR, #address
7 y; ?0 `/ {8 P! j: | ; 将待写字节装入 acc * }+ z m$ E0 o2 y2 @$ t
mov a, #value
% H- K1 f5 g; T: ?2 T; A9 L2 |. }+ j ; 启动写操作 + n/ S% z/ a$ {3 M5 M1 a" c$ K
movx @DPTR, a # ^. U" O7 U: `( Q9 X/ i1 P" n. c; f# ~
4. 如果不再进行写操作,将 PSWE 设置为‘0’。
1 b+ v) Y5 G9 m+ [每个 FLASH字节的写操作需要 20到 40μs 的时间。
( ]3 o V; B2 |9 d. ^更新 FLASH中的数据 ( o6 S9 N6 h# j! m9 S6 R
当保存一组配置信息时,经常需要在一组字节中单独改变某个字节的数值。单独更新某个字节9 ~3 t3 g% {( ?0 j# {( @7 m
(或字节子集)的一般过程如下:
6 Z8 H' G! i) n$ O1. 将 FLASH页拷贝到一个临时存储区(RAM 或一个已被擦除的‘临时’FLASH页)。 7 E, ^/ [- Z( j4 q$ e6 B. p- N
2. 擦除 FLASH页的数据。 6 h$ q( p' v$ \% S9 G O! z
3. 将前面存储在临时存储区的内容复制到 FLASH页中。
! @7 r) k- S. S6 ?/ ~+ w& _用‘C’代码访问 FLASH ) N- _2 R6 d' \) [- C
所附的示例代码说明了如何用‘C’程序擦除、写和读 FLASH 内容。由于 FLASH 读操作是
1 d8 @3 _$ V0 r2 n# T/ C7 [用 MOVC 指令实现的,因此用于读操作的 FLASH 指针必须是 CODE 类型。由于 FLASH 写操作/ c; I* g0 J/ F9 Z
是用 MOVX 指令实现的,所以用于写(或擦除)操作的 FLASH指针必须是 XDATA 类型。 # \# v% h7 j' u! q& c7 o5 |
2 V; ^4 n) n; n$ U3 H& ]
2 AN009-1.0 JAN01 4 h0 p7 L# o" a: J4 ]
' P- t k0 y$ G5 A! g! j" r; k
( N) ]# ~- \) z4 p- {6 b! E' \8 Q" |3 |$ Z4 z0 L2 T/ l
AN009 — 从应用程序写 FLASH
- z' |5 |$ P+ @! o( P' F& ]/ u# R
软件示例
: K0 F7 i( W. A//----------------------------------------------------------------------------------------------------------------------- 5 Z' x4 M& E; @8 ?! s. a: w
// FLASH_1.c 6 w& I3 F4 ?8 C1 a
//-----------------------------------------------------------------------------------------------------------------------
7 b% s2 c6 t1 A, C3 X9 B$ f5 U//
3 k- T# [# W r2 a& j1 V+ K: ~// 作者:BW
) ?# Q! N: q9 k9 k. u' I' Q// 6 t' E2 e2 q4 [9 S4 f
// 本示例程序给出了用‘C’程序擦除、写和读 FLASH存储器的例子。
2 K# v) ?9 m5 M/ y2 }1 l//
* J- i" ?2 I5 `. V5 E1 F6 z// 目标器件:C8051F000 或 C8051F010
3 N" F G7 \! W/ X# Z// 开发工具:KEIL C51
6 G4 I; w5 X; C( i% j// ( _) U, d5 E/ S9 ]( F
- x; g1 V7 P" ^: W4 D7 O; o/ h% Y//----------------------------------------------------------------------------- 1 L1 g% M/ z6 l% E4 k6 K
// 包含文件
- D+ Q- t& W; R' M6 p1 K//-----------------------------------------------------------------------------
9 ~* I. p; T' c& b. \* ]; X) v6 m+ O7 c+ n! q# l
#include <c8051f000.h> // SFR 声明 $ K, G0 E7 y5 C. r' {- M3 P( G, t
#include <stdio.h> 3 i$ Y5 }" h+ ?& n
- U, E7 X) a8 u9 a# _* ~) X' y" k
//----------------------------------------------------------------------------- # f7 g, X' [3 W* m
// Function PROTOTYPES
2 v# G9 s& B3 i4 C, X4 l//-----------------------------------------------------------------------------
/ y+ @ j: U: O" D3 W8 p: n% b( l, J
|, T% ]3 |# bvoid main (void); 2 [* |+ H( p" `/ ~3 d$ ~4 {
5 J/ N0 l. i/ f& F& V
//-----------------------------------------------------------------------------
# P5 n, {2 C0 @// MAIN Routine
" i# t4 B* m/ _$ q! ]$ b6 q//-----------------------------------------------------------------------------
0 E6 Y' w5 G& a# E1 E
4 `0 x* z2 P& Q/ \1 j1 Zvoid main (void) { , w) b7 T9 p2 o K ^1 Y
Q3 ?5 {% R1 O; E0 X
unsigned char test_string[ ] = "Howdy!"; // 将被拷贝到 FLASH中的字符串 - _: f2 n7 O9 y7 w0 j% |
& S* M1 c, @7 e- d& D
unsigned char xdata *pwrite; // 程序存储器空间的指针(FLASH),指向待写地址 - J) [' g1 O/ L4 ?+ { E2 }7 w
unsigned char code *pread; // 程序存储器空间的指针(FLASH),指向待读地址
/ m; Y! i5 B1 I. ^6 M unsigned char *pgen; // 一般指针
/ P( m" c& j5 `' P5 I! q char test; // 测试字符 ! C+ b# w; n) r" p" Z5 m0 }6 X
3 X1 {9 |4 t% B AN009-1.0 JAN01 3 # x# L6 U" t' O. y' C) R/ J6 ?; G
8 t( \* o6 }) q* f1 k
+ a5 F3 i b4 w% x8 i% w
1 @- Q7 k* {, P" z4 { b+ yAN009 — 从应用程序写 FLASH " ]3 D; R+ v+ H, [6 k W
! Y; c2 _2 J- l
// 禁止看门狗定时器 8 A% I X- f: b* N/ n( ]$ S' V
WDTCN = 0xde; , |# P/ P7 `( E& e& @$ W) q
WDTCN = 0xad;
; `8 S- ?1 a8 |: p; J$ l, Q6 B // 擦除 128 字节的信息页(位于 0x8000) 9 Q! \) D' S* A5 O; `- Q& \# ~# R/ E
FLSCL = 0x86; // 设置 FLASH标度寄存器(对 2MHz 系统时钟) - p+ c. F( x; C a
PSCTL = 0x03; // 将 PSWE 和 PSEE 置‘1’(MOVX 指令对应 4 t( Q! w8 {4 K8 y: j
// 的 FLASH页 6 j8 F9 _) `# j5 g% A9 e
pwrite = 0x8000; // 将指针指向待擦除页
2 U- w% q$ ^/ x* { *pwrite = 0; // 启动擦除过程 # g) [0 ^/ ]9 K: F
PSCTL = 0x01; // 清除 PSEE,PSWE 仍然置 1
+ @* }- D1 G! Z2 P4 b' t" E, ? // MOVX 指令将写到对应的地址
& t3 b s' ]: U' H
* l( H; X) c. Y. S1 z" B // 现在我们要拷贝字符串 <test_string> 的内容到 FLASH页,从地址 0x8000 开始。
5 u e" m2 V, Y5 S1 j; E! G! C& @+ b f
pgen = test_string; // pgen 指向源字符串 1 C. `. c; V/ v4 X. t
do {
0 e. f0 X/ x! D# `- n+ u# H *pwrite++ = *pgen++; // 拷贝字节
& s; t6 L7 w4 S v } while (*pgen != '\0'); // 直到 NULL 结束符
) T. K& X( ]9 Y) q) F
( M- q; T6 \# e *pwrite = NULL; // 用 NULL 结束目的字符串
9 P# a/ w" i9 }% [
4 X6 b& T) \4 i7 ]6 k PSCTL = 0; // 禁止 FLASH写 6 d0 p$ M, {% f! A& J' t8 r% L8 K" I7 v, P
FLSCL = 0x8f; // 禁止 FLASH写
; h! R% K; {; q# X+ n4 p8 `
2 N' ~, p; ~1 y3 O# f5 O // 现在我们读写入的字符串 8 b$ Y+ E' f6 s# ]. j
8 F. Q! q4 w3 O6 ?) A- M
pread = 0x8000; // 初始化 CODE 读指针为字符串起始地址 ( o7 ?7 T' I7 I0 {- x8 X5 h
% K! u" O9 d- z4 W8 R G/ b test = 0x5a; - Z4 ] v7 k9 h! I- |; q
do { 6 x0 T6 k. y& q3 L, w9 M
test = *pread++;
, J5 ]5 f- X1 |2 @0 H' ]& L+ \ } while (test != '\0'); : X) U( X/ v M" _
1 X! C" b" g5 o" W; H3 T while (1) { // 原地循环
1 Z! ~3 k* m1 T7 C }
* _6 o0 E' T, M% W e ~} 7 s+ v$ q! c7 f! A" `# ?* W
) U$ [' j' |6 H! y1 C! |
4 AN0
3 ?7 L" |2 L: _$ T3 x: ], h$ ?' g% {. d5 t5 a- }
|
|