EETS4K 模块应用笔记(1)
9S12 系列单片机的通常包含4KB 的EEPROM。Freescale 将EEPROM 模块称之为 EETS4K。实际上,这里所谓的 EEPROM 其实是FLASH,只不过Freescale 特意将这里Flash 的 sector 做的很小(4Bytes),使得用户用起来像是在用 EEPROM。
EEPROM 是直接映射到9S12 单片机的地址空间的,如果程序中只是读取 EEPROM 中的内容,而不涉及到对 EEPROM 中数据的修改。那就不需要特殊的编程。就像读取RAM数据那样直接访问就可以了。
只有当需要在程序中更新EEPROM 中内容时,才需要学习下面的内容。
初始化EETS4K
在向EETS4K写入数据或擦除数据前要先配置EETS4K的时钟。EETS4K的时钟频率必须在150KHz——200KHz之间,为此需要配置 ECLKDIV 寄存器。
ECLKDIV 寄存器(EEPROM Clock Divider Register)
图 1ECLKDIV 寄存器
PRDIV8是预分频位:当PRDIV8=1时输入时钟被预分频为1/8。
EDIV5——EDIV8为分频除数寄存器,最多可以产生1/64 的分频比。简单的计算可知,当输入时钟大于12.8MHz 时需要将 PRDIV8 置位。
经过PRDIV8和EDIV两级分频最多可将时钟频率分为1/512。
擦除和写入和读取
这里不详细介绍每一个寄存器的用法。只对需要注意的地方加以说明。
EETS4K 模块的最小擦除单位是4Bytes,EETS4K 模块提供了两条相关命令,一条是擦除一个 sector,也就是 4 字节,并且要求是字节对其的双字。另一条命令擦除全部EEPROM 空间。
每次编程(写入)单位为两个字节。并且这两个字节要是对其字。
当EETS4K 模块正在进行擦除或编程操作时是不能同时读取EEPROM中内容的。
有了这些介绍就够了。下面给出一个具体的例子。
- /*EETS4K.h*/
- #ifndef NVM_H
- #define NVM_H
- /*
- * CONSTANTS
- */
- #define NVM_NO_ERR (1)
- #define NVM_ODD_ACCESS_ERR (-1)
- #define NVM_ACCESS_ERR (-2)
- #define NVM_PROTECTION_ERR (-3)
- /*
- * FUNCTION PROTOTYPES
- */
- void EEPROM_Init(unsigned long sysclk);
- char EEPROM_Write_Word(unsigned int address, unsigned int data);
- char EEPROM_Erase_Sector(unsigned int address);
- char EEPROM_Erase_All (void);
- unsigned int EEPROM_Read_Word(unsigned int address);
- #endif /* End of file */
- /*EETS4K.C*/
- #include <hidef.h> /* common defines and macros */
- #include "derivative.h" /* derivative-specific definitions */
- #include "eets4k.h"
- /** @brief This function initializes the Non Volatile EEPROM control registers
- * and must be called before attempting to write or erase an EEPROM sector.
- *
- * @para sysclk the CPU clock frequency (SYSCLK) driven by the onboard oscillator or the PLL if enabled.
- */
- void EEPROM_Init (unsigned long sysclk)
- {
- unsigned char eclk_val;
- if (sysclk >= 12000) { /* If the SYSCLK is > 12MHz, then set FDIV8 bit */
- eclk_val = (sysclk / (8*200)) - 1; /* Compute the correct divider value */
- ECLKDIV |= ECLKDIV_PRDIV8_MASK | eclk_val; /* Write the ECLKDIV register with the correct settings */
- } else {
- eclk_val = (sysclk / 200) - 1; /* Compute the correct divider value */
- ECLKDIV |= eclk_val; /* Write the ECLKDIV register with the correct settings */
- }
- ESTAT |= (ESTAT_PVIOL_MASK | ESTAT_ACCERR_MASK); /* Clear any error flags */
- }
- /** @brief This function writes a 16-bit word to EEPROM
- * @param address, the destination EEPROM address to write the data
- * @param data, the data to write to argument address.
- * @return
- * NVM_NO_ERR - EEPROM Write Success
- * NVM_ODD_ACCESS_ERR - EEPROM Write Error, Address not on an even address boundry
- * NVM_ACCESS_ERR - EEPROM Write Error, Access Violation
- * NVM_PROTECTION_ERR - EEPROM Write Error, Attempted to write a protected sector
- */
- char EEPROM_Write_Word (unsigned int address, unsigned int data)
- {
- while (!ESTAT_CBEIF) { /* Wait for EEPROM access controller to become ready */
- ;
- }
- ESTAT = (ESTAT_ACCERR_MASK | ESTAT_PVIOL_MASK); /* Clear existing error flags */
- if (address & 0x0001) {
- return (NVM_ODD_ACCESS_ERR); /* Address is NOT aligned on an even boundry? */
- }
- (*(unsigned int *)address) = data; /* Write the data to the specified address */
- ECMD = ECMD_CMDB5_MASK; /* Store programming command in FCMD */
- ESTAT_CBEIF = 1; /* Execute the command */
- if (ESTAT_ACCERR) { /* Check if there has been an access error */
- return (NVM_ACCESS_ERR); /* Return an Access Error code */
- }
- if (ESTAT_PVIOL) { /* Check if there has been a protection error */
- return (NVM_PROTECTION_ERR); /* Return a Protection Error code */
- }
- return (NVM_NO_ERR); /* Return No Error */
- }
- /** @brief This function erases a 4-byte sector of EEPROM
- * @param address, the start of the 4-byte sector to address
- * @return
- * NVM_NO_ERR - EEPROM Write Success
- * NVM_ODD_ACCESS_ERR - EEPROM Write Error, Address not on an even address boundry
- * NVM_ACCESS_ERR - EEPROM Write Error, Access Violation
- * NVM_PROTECTION_ERR - EEPROM Write Error, Attempted to write a protected sector
- */
- char EEPROM_Erase_Sector (unsigned int address)
- {
- while (!ESTAT_CBEIF) { /* Wait for EEPROM access controller to become ready */
- ;
- }
- ESTAT = (ESTAT_ACCERR_MASK | ESTAT_PVIOL_MASK); /* Clear existing error flags */
- if (address & 0x0001) {
- return (NVM_ODD_ACCESS_ERR); /* Address is NOT aligned on an even boundry? */
- }
- (*(unsigned int *)address) = 0xFFFF; /* Write the data to the specified address */
- ECMD = ECMD_CMDB6_MASK; /* Store programming command in FCMD */
- ESTAT_CBEIF = 1; /* Execute the command */
- if (ESTAT_ACCERR) { /* Check if there has been an access error */
- return (NVM_ACCESS_ERR); /* Return an Access Error code */
- }
- if (ESTAT_PVIOL) { /* Check if there has been a protection error */
- return (NVM_PROTECTION_ERR); /* Return a Protection Error code */
- }
- return (NVM_NO_ERR); /* Return No Error */
- }
- char EEPROM_Erase_All (void)
- {
- while (!ESTAT_CBEIF) { /* Wait for EEPROM access controller to become ready */
- ;
- }
- ESTAT = (ESTAT_ACCERR_MASK | ESTAT_PVIOL_MASK); /* Clear existing error flags */
- (*(unsigned int *)0x0400) = 0xFFFF; /* Write the data to the specified address */
- ECMD = 0x41; /* Store programming command in FCMD */
- ESTAT_CBEIF = 1; /* Execute the command */
- if (ESTAT_ACCERR) { /* Check if there has been an access error */
- return (NVM_ACCESS_ERR); /* Return an Access Error code */
- }
- if (ESTAT_PVIOL) { /* Check if there has been a protection error */
- return (NVM_PROTECTION_ERR); /* Return a Protection Error code */
- }
- return (NVM_NO_ERR); /* Return No Error */
- }
- /** @brief This function reads a 16-bit word from the specified address in EEPROM
- * @param address, the start of the 16-bit data to read
- * @return The 16-bit word stored in location 'address'
- */
- unsigned int EEPROM_Read_Word (unsigned int address)
- {
- unsigned int data;
- while (!ESTAT_CBEIF) { /* Wait for EEPROM access controller to become ready */
- ;
- }
- data = (*(unsigned int *)address); /* Read the data at location 'address' */
- return (data); /* Return the data*/
- }
- #include <hidef.h> /* common defines and macros */
- #include "derivative.h" /* derivative-specific definitions */
- #include "sci.h"
- #include "eets4k.h"
- void main(void)
- {
- unsigned int data;
- EEPROM_Init(16384);
- EnableInterrupts;
- EEPROM_Erase_All ();
- EEPROM_Write_Word(0x400, 1234);
- data = EEPROM_Read_Word(0x400);
- for(;;)
- {
- _FEED_COP(); /* feeds the dog */
- } /* loop forever */
- }