Файл: Programming Microcontrollers in C, 2-nd edit (Ted Van Sickle, 2001).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 15.06.2025
Просмотров: 4070
Скачиваний: 1
Microcontroller Memory 159
Programming EEPROM
EEPROM is read like any other memory in the microcontroller. Two different types of EEPROM can be found on a microcontroller: program memory and data storage memory. Program memory usu ally cannot be programmed without the aid of an externally applied programming voltage. Data storage memory can be programmed from within the program and requires no externally applied programming voltage. In the case of the M68HC805B6, there are 5888 bytes of program EEPROM and 255 bytes of data storage EEPROM. Other than the reduced size of the data storage memory, this memory is no different from the program memory. It is possible to write code to the data storage EEPROM and execute this code.
One additional byte of data storage EEPROM exists and is called the OPTION register. This register content is saved in EEPROM which is read into a latched register during the initialization of the microcontroller. The address of this register is 0x100. The bits in this register control the security option of the part and control a block protect region in the data storage EEPROM that will prevent acci dental writing of data into the protected memory area. A description of these bits follows:
Options Reg |
Bit 7 |
Bit 6 |
Bit 5 |
Bit 4 |
Bit 3 |
Bit 2 |
Bit 1 |
Bit 0 |
||
0x0100 |
EE1P |
SEC |
||||||||
SEC |
Bit 0 |
Security Bit. When the SEC bit is programmed to |
||||||||
zero, the contents of the EPROM are secured by |
||||||||||
preventing access to the test mode. The only way |
||||||||||
to erase the SEC bit to a one state is to enter the |
||||||||||
self-check mode. In this event, the data on |
||||||||||
EEPROM will all be erased. When the SEC bit is |
||||||||||
changed, its new value will have no effect until |
||||||||||
after the next chip reset. |
||||||||||
EE1P |
Bit 1 |
EEPROM Block Protect Bit. The EEPROM is in |
||||||||
two parts: 0x101 to 0x11f is part 1 and 0x120 to |
||||||||||
0x1ff is part 2. The EE1P bit allows part 2 to be |
||||||||||
protected. If this bit is in the erased state, (1), part 2 of the EEPROM will be protected. This memory area can be read as usual, but any attempt to write to this area will fail. The protection remains in
160 Chapter 4 Small 8-Bit Systems
effect after this bit is erased until after the next chip reset.
Control of the EEPROM programming is through the EEPROMCTL register found at address 0x07. The bits in this register are as follows:
EEPCTL/CLK |
Bit 7 |
Bit 6 |
Bit 5 |
Bit 4 |
Bit 3 |
Bit 2 |
Bit 1 |
Bit 0 |
||
0x07 |
0 |
0 |
0 |
0 |
ECLK |
E1ERA |
E1LAT |
E1PGM |
||
E1PGM |
Bit 0 |
EEPROM Program Bit. This bit turns the internal |
||||||||
Vpp charge pump on and off. When this bit is 0, |
||||||||||
the charge pump is turned off, and when it is at 1, |
||||||||||
the charge pump is turned on. The charge pump |
||||||||||
voltage can be measured on the pin Vpp1. This bit |
||||||||||
cannot be set until after the program data are latched |
||||||||||
in place by asserting the E1LAT bit. Resetting the |
||||||||||
E1LAT bit will also reset the E1PGM bit. |
||||||||||
E1LAT |
Bit 1 |
EEPROM Data/Address Latch. When this bit is re |
||||||||
set to zero, both the E1PGM bit and the E1ERA bit |
||||||||||
are reset to zero. When the E1LAT bit is reset, data |
||||||||||
can be read from the EEPROM. The first data write |
||||||||||
to the EEPROM array after this bit is set is latched |
||||||||||
until the E1LAT bit is reset. Data can be latched |
||||||||||
only when the E1PGM bit is reset to zero. This op |
||||||||||
eration allows programming of the EEPROM. |
||||||||||
E1LAT is automatically reset when the chip is reset |
||||||||||
or when the STOP instruction is executed. |
||||||||||
E1ERA |
Bit 2 |
EEPROM Erase Bit. If the bit E1ERA is reset to |
||||||||
zero when E1LAT and E1PGM are set to one, data |
||||||||||
are programmed into the EEPROM. Otherwise, |
||||||||||
if E1ERA is set to one and E1LAT and E1PGM |
||||||||||
are set to one, the specified address in the |
||||||||||
EEPROM will be erased. E1ERA cannot be set |
||||||||||
before E1LAT, and resetting E1LAT to zero will |
||||||||||
cause E1ERA to be reset. |
||||||||||
Let us now examine a possible sequence of code that can be used to program and erase locations in EEPROM. First, several macro definitions should be used to define the various parameters used.
Microcontroller Memory 161
/* pragmas to identify EEPROM control registers */
#pragma portrw EEPROM_CTL @ 0x07; #pragma portrw OPTIONS @ 0x100;
.
.
.
/* EEPROM programming specific defines */
#define E1PGM 0 #define E1LAT 1 #define E1ERA 2 #define PROG_TIME 10
.
.
/* some function prototypes */
void delay(unsigned long); void program(int ,int); void erase(int );
.
.
.
int EEPROM[0xff] @ 0x101; /* Identify the EEPROM */ void program(int address,int value)
{
EEPROM_CTL.E1LAT=1; /* set the E1LAT bit */ EEPROM[address]=value;/* put the data and address
in place */
EEPROM_CTL.E1PGM=1; /* turn on the charge pump */ delay(PROG_TIME); /* delay programming time */ EEPROM_CTL.E1LAT=0; /* reset the E1LAT also
resets the E1PGM bit */
}/* return when done */
void erase(int x)
{
162 Chapter 4 Small 8-Bit Systems
EEPROM_CTL.E1LAT=1; /* set the E1LAT bit */ EEPROM_CTL.E1ERA=1; /* set the E1ERA erase bit */ EEPROM[x]=0; /* select the address */ EEPROM_CTL.E1PGM=1; /* turn on the charge pump*/ delay(PROG_TIME); /* wait the appropriate time*/ EEPROM_CTL.E1LAT=0; /* reset the E1LAT bit turns
off both E1PGM and E1ERA bits */
}/* return when done */
The above program sequences are compiled and listed below. The function delay is not included or linked into this program.
To handle this type of problem, the registers are set up for the func tion call, and the instruction JSR $**** is executed. A later linking will replace the unknown function address with the correct value. An appropriate delay() function will be written in the timer section. The instructions for this function call are found at addresses 0x80c to 0x80f in the following listing.
0020 0030 #pragma memory ROMPAGE0 [48] @ 32;
0800 1700 #pragma memory ROMPROG [5888] @ 2048;
0050 00B0 #pragma memory RAMPAGE0 [176] @ 80;
0100 0100 #pragma memory RAMPROG [256] @ 256;
/* pragmas to identify EEPROM control registers */
0007 #pragma portrw EEPROM_CTL @ 0x07;
0100 #pragma portrw OPTIONS @ 0x100;
/* EEPROM programming specific defines */
0000 #define E1PGM 0
0001 #define E1LAT 1
0002 #define E1ERA 2
000A #define PROG_TIME 10
/* some function prototypes */
void delay(long);
Microcontroller Memory 163
void program(int,int ); void erase(int );
0101 |
0101 00FF int EEPROM[0xff] @0x101; |
||
void program(int address, int value) |
|||
0050 |
0051 { |
||
0801 |
BF 50 STX $50 |
||
0803 |
B7 |
51 |
STA $51 |
0805 |
12 |
07 |
BSET 1,$07 EEPROM_CTL.E1LAT=1; |
0807 |
D7 |
01 |
01 STA $0101,X EEPROM[address]=value; |
080A |
10 |
07 |
BSET 0,$07 EEPROM_CTL.E1PGM=1; |
080C |
5F |
CLRX delay(PROG_TIME); |
|
080D |
A6 |
0A |
LDA #$0A |
080F |
CD 00 00 JSR $**** |
||
0812 |
13 |
07 |
BCLR 1,$07 EEPROM_CTL.E1LAT=0; |
0814 |
81 |
RTS } |
|
void erase(int x) |
|||
0052 |
{ |
||
0815 |
B7 |
52 |
STA $52 |
0817 |
12 |
07 |
BSET 1,$07 EEPROM_CTL.E1LAT=1; |
0819 |
14 |
07 |
BSET 2,$07 EEPROM_CTL.E1ERA=1; |
081B |
97 |
TAX EEPROM[x]=0; |
|
081C |
4F |
CLRA |
|
081D |
D7 |
01 |
01 STA $0101,X |
0820 |
10 |
07 |
BSET 0,$07 EEPROM_CTL.E1PGM=1; |
0822 |
5F |
CLRX delay(PROG_TIME); |
|
0823 |
A6 |
0A |
LDA #$0A |
0825 |
CD 00 00 JSR $**** |
||
0828 |
13 |
07 |
BCLR 1,$07 EEPROM_CTL.E1LAT=0; |
082A |
81 |
RTS } |
|
The function program() requires 20 bytes and the function erase requires 22. This is a good point to explore some of the C programming practices that can lead to poor M68HC05 family com
164 Chapter 4 Small 8-Bit Systems
piled code. The M68HC05 family is a family of 8-bit machines. There has been no discussion of the programmers’ register model of these devices. Programmer models of the larger microcontrollers will be discussed because knowledge of the programmers’ model might help in crafting good C code. For these small machines, the watchword is 8-bit. The internal structure of the system is all 8-bit. The width of the single index register is 8 bits, and the width of the accumulator is also 8 bits. The program counter is more than 8 bits in most cases, but it is wide enough to address only the range of the internal com puter memory. In fact, the width of the stack pointer in the M68HC05Bx family is only 6 bits. There is no luxury of spare bits in any register.
Therefore, when writing code for the M68HC05 family, keep fore most in your mind that you are dealing with an 8-bit device. If at all possible, avoid 16-bit operations because they will always result in larger memory and/or code usage. The following code demonstrates an ex ample of the careless use of 16-bit implied code in an 8-bit machine.
Consider the erase() routine from above. This function could have been written as follows:
void erase(int *x)
{
EEPROM_CTL.E1LAT=1; /* set the E1LAT bit */ EEPROM_CTL.E1ERA=1; /* set the E1ERA erase bit */ *x=0; /* select the address */ EEPROM_CTL.E1PGM=1; /* turn on the charge pump*/ delay(PROG_TIME); /* wait the appropriate time*/ EEPROM_CTL.E1LAT=0; /* reset the E1LAT bit turns
off both E1PGM and E1ERA bits */
}/* return when done */
The only change in this version is to pass the integer *x to the function by reference. Remember, since all addresses in the M68HC05 family of parts are greater than 8 bits, the compiler must handle the transfer of the pointer x as a 16-bit number. The statement *x=0; compiles into an inline function at the address range 0x81d to 0x82c in the compiled version of the code shown below. This function creates a subroutine that does an indexed store with a 16-bit offset. First, the value to be programmed is placed in the accumulator. Then the op
Microcontroller Memory 165
code, 0xd7, to do a store the accumulator indexed with a 16-bit offset is created at the location 0x56 in memory. The 16-bit offset is the address passed to the function in the combination of the x register and the accumulator. This address is placed in the memory locations 0x58 and 0x57, completing the store instruction. At the address 0x59, a re turn from subroutine instruction, 0x81, is placed to complete the function. The index register is cleared, and this two-instruction sub routine is executed to store the appropriate data prior to the program setting the latch bit.
void erase(int* x)
0052 |
{ |
||
0815 |
BF 52 STX $52 |
||
0817 |
B7 |
53 |
STA $53 |
0819 |
12 |
07 |
BSET 1,$07 EEPROM_CTL.E1LAT=1; |
081B |
14 |
07 |
BSET 2,$07 EEPROM_CTL.E1ERA=1; |
081D |
B7 |
58 |
STA $58 *x=0; |
081F |
9F |
TXA |
|
0820 |
B7 |
57 |
STA $57 |
0822 |
4F |
CLRA |
|
0823 |
AE D7 LDX #$D7 |
||
0825 |
BF 56 STX $56 |
||
0827 |
AE 81 LDX #$81 |
||
0829 |
BF 59 STX $59 |
||
082B |
5F |
CLRX |
|
082C |
BD 56 JSR $56 |
||
082E |
10 |
07 |
BSET 0,$07 EEPROM_CTL.E1PGM=1; |
0830 |
5F |
CLRX delay(PROG_TIME); |
|
0831 |
A6 |
0A |
LDA #$0A |
0833 |
CD 00 00 JSR $**** |
||
0836 |
13 |
07 |
BCLR 1,$07 EEPROM_CTL.E1LAT=0; |
0838 |
81 |
RTS } |
|
This code sequence requires 36 bytes, plus 4 bytes of uncommit ted RAM space, to accomplish what required 22 bytes in the earlier example of the same operation.
You must not avoid the use of pointers because of this one ex ample. There are cases when proper pointer usage will provide the best code that you can generate. When writing code for microcontrollers, use many relatively small functions that you can