系统扩展设计及例题的介绍与实际应用相结合,原理图中给出了各元器件的实际应用参数。在第7-12章中的每一道例题都采用汇编、C51两种语言分别编程实现。第12章中数字显示温度计、RLC测量仪两个应用实例的电路及程序都通过了验证。第10章STC系列单片机片内EEPROM的应用10.1EEPROM模块所属特殊功能寄存器10.2EEPROM读、写、擦除第10章STC系列单片机片内EEPROM的应用•STC系列单片机内部不仅集成了用于存储程序的EEPROM,还集成了用于存储数据的EEPROM,不同的型号容量不同,从1KB-45KB不等。•EEPROM主要用于保存在掉电时不允许丢失的数据,在应用过程中所采集、运算或通过键盘输入等得到的一些修正参数。•STC系列单片机内部集成的用于存储数据的EEPROM和用于存储程序的EEPROM地址重叠,但属于不同的物理空间。用户程序指令代码是通过串口直接下载至程序存储器,而用于存储数据的EEPROM则通过用户程序进行读写操作。•EEPROM分为若干个扇区,每个扇区的大小为512B,数据存储器的擦除操作是按扇区进行的,可以擦写的次数在10万次以上。•使用时,同一次修改的数据应该存放于同一个扇区,不是同一次修改的数据最好存放在不同的扇区,不一定要存满。内部EEPROM的扇区地址如表10-1所示。起始地址结束地址起始地址结束地址第一扇区第二扇区0000H01FFH0200H03FFH第三扇区第四扇区0400H05FFH0600H07FFH…………10.1EEPROM模块所属特殊功能寄存器•对存储数据的EEPROM读、写、擦除等操作要用到6个特殊功能寄存器特殊功能寄存器名称地址描述复位初值IAP_DATAC2H/E2H数据寄存器11111111BIAP_ADDRHC3H/E3H地址寄存器高8位00000000BIAP_ADDRLC4H/E4H地址寄存器低8位00000000BIAP_CMDC5H/E5H命令寄存器xxxxxx00BIAP_TRIGC6H/E6H命令触发寄存器xxxxxxxxBIAP_CONTRC7H/E7H控制寄存器0000x000BSTC11/10Fxx、STC12C5A60S2等单片机的6个特殊功能寄存器的地址分别为C2-C7H;而STC12C56xx、STC12C54xx、STC89/90C51xx等系列单片机的地址为E2-E7H。1.命令寄存器IAP_CMDMS1、MS0决定EEPROM的工作方式MS1MS0操作任务的选择00待机模式,不操作01对EEPROM进行读操作10对EEPROM进行写操作11对EEPROM进行擦除操作2.控制寄存器IAP_CONTR•对IAPEN、SWBS两位,用户只能写入1、0或0、0。IAPEN:读、写、擦除使能位。清0后禁止对EEPROM进行读、写、擦除;置1后允许对EEPROM进行读、写、擦除。SWBS:若对该位写入0,则是选择了用户应用程序(IAP)对EEPROM进行操作;该位若写入1,则是选择了单片机内部固化的系统监控程序(ISP)对EEPROM进行操作。SWRST:若对该位写入1时将产生系统软件复位,复位响应时,硬件自动将该位清零。CMD_FAIL:若该位为0,表示对EEPROM的读、写、擦除等操作是成功的;若该位为1,表示对EEPROM的读、写、擦除等操作失败,须由软件清0。WT2、WT1、WT0这三位设置等待时间,写入EEPROM单元的数据需要55μs的内部编程时间。如果是对内部扇区擦除,则需要21ms。在此期间,不得对EEPROM的任何单元进行任何访问,否则在此之前写入的命令失效。这三位的值决定等待上述时间所需要的系统时钟周期数,具体情况如表10-3所示。WT2WT1WT0读(2个时钟)写(55us)扇区擦除(21ms)对应fosc1112个时钟55个时钟21012个时钟1MHz1102个时钟100个时钟42024个时钟2MHz1012个时钟165个时钟63036个时钟3MHz1002个时钟330个时钟126072个时钟6MHz0112个时钟660个时钟252144个时钟12MHz0102个时钟1000个时钟420240个时钟20MHz0012个时钟1320个时钟504288个时钟24MHz0002个时钟1760个时钟672384个时钟30MHz10.2EEPROM读、写、擦除•EEPROM进行读写时,必须按一个字节一个字节地操作。•通过以下程序了解对EEPROM的读、写、擦除的过程。(1)从STC12C5A60S2单片机片内EEPROM中某单元读取数据(假设系统时钟频率为20MHz)MOVIAP_ADDRH,#BYTE_ADDRH;送单元地址的高8位MOVIAP_ADDRL,#BYTE_ADDRL;送单元地址的低8位MOVIAP_CONTR,#10000010B;设置等待时间且允许EEPROM进行读、写、擦除操作MOVIAP_CMD,#00000001B;送字节读指令MOVIAP_TRIG,#5AH;启动内部读取工作MOVIAP_TRIG,#0A5HNOP;等待2个时钟周期的时间NOPMOVA,ISP_DATA;将读出的数据存入A寄存器•对STC10/10Fxx、STC12C5Axx等系列单片机启动读、写、擦除工作时,先给IAP_TRIG寄存器送立即数5AH,再送A5H作为触发信号;而对STC12C56xx、STC12C54xx、STC89/90C51xx等系列单片机需先送46H,再送B9H作为触发信号。(2)向STC12C5A60S2单片机片内EEPROM中某单元写入数据(假设系统时钟频率为20MHz):MOVIAP_DATA,#DATA;先将要写入的数据送至IAP_DATA寄存器MOVIAP_ADDRH,#BYTE_ADDRH;送单元地址的高8位MOVIAP_ADDRL,#BYTE_ADDRL;送单元地址的低8位MOVIAP_CONTR,#10000010B;设置等待时间且允许对EEPROM进行读、写、擦除操作MOVIAP_CMD,#00000010B;送字节写命令MOVIAP_TRIG,#5AH;启动内部编程工作MOVIAP_TRIG,#0A5HLCALLDELAY_55µs;调用延时55μs的子程序,等待编程结束•完成读、写操作后,地址不会自动加1,每次执行读、写操作时须重新送地址。(3)如果在某扇区中已向部分单元写入了数据,要想再改写数据,需对该扇区的所有单元进行全部擦除,即改写数据前先对整个扇区进行擦除,对扇区擦除的程序如下(假设系统时钟频率为20MHz):MOVIAP_ADDRH,#SECTOR_ADDR_HIGH;送扇区起始地址的高8位MOVIAP_ADDRL,#SECTOR_ADDR_LOW;送扇区起始地址的低8位MOVIAP_CONTR,#10000010B;设置等待时间且允许对EEPROM进行读、写、擦除等操作MOVIAP_CMD,#00000011B;送扇区擦除指令MOVIAP_TRIG,#5AH;启动擦除进程MOVIAP_TRIG,#0A5HLCALLDELAY_21ms;延时21ms,等待擦除结束【例10-1】将STC12C5A60S2单片机片内RAM的50H-5FH单元的数据依次写入EEPROM的第一扇区的0000H-000FH单元。•分析:如果在读、写、擦除的过程中,没有对EEPROM相关的寄存器进行访问,读、写、擦除一般是成功的。为了防止在读、写、擦除的过程中电源发生波动,在读、写、擦除后需要判断操作是否成功。设系统的时钟频率为20MHz,用R0作为指针指向片内RAM的50H-5FH单元,DPTR指向EEPROM的0000H-000FH地址,要将数据写入EEPROM,首先对整个扇区进行擦除。若擦除不成功,需要重新擦除;若擦除成功,可将片内RAM50H-5FH单元的数据写进EEPROM的0000H-000FH单元,然后再读出EEPROM的数据与片内RAM的50H-5FH单元的数据比较,若相同,表示写操作成功,若不同,表示写操作失败,需重新擦除后,将数据再次写进EEPROM对应的单元•汇编语言子程序IAP_DATAEQU0C2H;数据寄存器IAP_ADDRHEQU0C3H;高8位地址寄存器IAP_ADDRLEQU0C4H;低8位地址寄存器IAP_CMDEQU0C5H;命令寄存器IAP_TRIGEQU0C6H;触发寄存器IAP_CONTREQU0C7H;控制寄存器SECTION_ADDREQU0000H;扇区首地址ORG0000HLJMPMAINORG0100HMAIN:MOVSP,#0BFH;初始化堆栈指针START0:MOVDPTR,#SECTION_ADDR;第一扇区的首地址送DPTRLCALLSECTION_ERASE;调用扇区擦除子程序MOVA,IAP_CONTR;读控制寄存控制器JNBACC.4,START;若此位为0,表示擦除成功,可进行编程LJMPSTART0;若擦除失败,须重新进行擦除START:MOVDPTR,#SECTION_ADDR;第一扇区的首地址送DPTRMOVR0,#50H;R0作为片内RAM的指针MOVR2,#16;R2作为写16个字节的计数器LOOP:LCALLBYTE_PROGRAM;调用向EEPROM写数据的子程序LCALLBYTE_READ;调用读EEPROM子程序MOVA,@R0CJNEA,IAP_DATA,START0;如果读到的数据与原数据不等,则重新开始INCDPTR;EEPROM地址加1INCR0;片内RAM地址加1DJNZR2,LOOP;计数不为0,跳转至LOOPSJMP$SECTION_ERASE:;擦除MOVIAP_CONTR,#82H;设置等待时间且允许对EEPROM进行操作MOVIAP_CMD,#03H;对EEPROM进行扇区擦除命令MOVIAP_ADDRL,DPL;送入扇区首地址的低8位MOVIAP_ADDRH,DPH;送入扇区首地址的高8位MOVIAP_TRIG,#5AH;启动擦除操作MOVIAP_TRIG,#0A5HLCALLDELAY_21ms;延时等待RETBYTE_PROGRAM:;写MOVA,@R0;读取片内RAM单元50H-5FH的内容MOVIAP_DATA,A;将数据送至数据寄存器MOVIAP_CONTR,#82H;允许对EERPOM操作并设置等待时间MOVIAP_CMD,#02H;对EEPROM进行写操作指令MOVIAP_ADDRL,DPL;送地址的低8位MOVIAP_ADDRH,DPH;送地址的高8位MOVIAP_TRIG,#5AH;启动写操作MOVIAP_TRIG,#0A5HLCALLDELAY_55μs;延时等待RETBYTE_READ:;读MOVIAP_CONTR,#82HMOVIAP_CMD,#01H;读EEPROM命令MOVIAP_ADDRL,DPL;送入地址的低8位MOVIAP_ADDRH,DPH;送入地址的高8位MOVIAP_TRIG,#5AH;启动读操作MOVIAP_TRIG,#0A5HNOPNOPRETDELAY_55μs:;略DELAY_21ms:;略ENDC51程序:#includeSTC12C5A.h#includeintrins.h//声明本征函数库#defineucharunsignedchar#defineuintunsignedint#defineSECTION_ADDR0x0000//定义扇区的首地址uchardata*dp;//定义指针ucharTemp;uinti,xdat;longy;voidSECTION_ERASE(uintSECTION_ADDR);//扇区擦除函数voidBYTE_PROGRAM(uintbyte_addr);//扇区编程函数ucharBYTE_READ(uintbyte_addr);//读扇区内容函数voidDelay_μs()reentrant;//延时函数voidmain(){ucharflag=0;//定义扇区擦除失败的标记位dp=0x5