赞
踩
51单片机编程方式根据代码下载方法不同可分为两种,分别是在系统编程(ISP, In System Programming )和在程序中编程(IAP, In Application Programming)。
STC89C52RC 芯片内部 Flash 可分为程序区和 EEPROM 区。
unsigned char dat;
ISP_CONTR=0x81; // 打开 IAP 功能,允许编程改变 Flash ,设置 Flash 操作等待
时间
ISP_CMD = 0x02; // 允许对 "Data Flash/EEPROM 区 " 进行字节读取
ISP_CONTR=0x81; // 打开 IAP 功能,允许编程改变 Flash ,设置 Flash 操作等待
时间
ISP_CMD = 0x02; // 允许对 "Data Flash/EEPROM 区 " 进行字节读取
操作ISP_TRIG = 0x46; // 写入触发命令 0x46
ISP_TRIG = 0xB9; // 写入触发命令字 0xB9
操作ISP_TRIG = 0x46; // 写入触发命令 0x46
ISP_TRIG = 0xB9; // 写入触发命令字 0xB9
ISP_CONTR = 0x00; // 禁用 IAP 读写 EEPROM
ISP_CMD = 0x00; // 待机模式,无 ISP 操作
ISP_TRIG = 0x00; // 关闭 IAP 功能
由于 Flash 存储介质的特性,只能对其写入“ 0” 而不能写入“ 1” ,因此需要对扇区内写入“ 1” ,即擦除操作。在首次对扇区执行写入操作时,必须先执行扇区擦除操作。
EEPROM.h
文件sfr ISP_DATA = 0XE2; //定义ISP-IAP操作时的数据寄存器
sfr ISP_ADDRH = 0XE3; //定义ISP-IAP操作地址寄存器低位
sfr ISP_ADDRL = 0XE4; //定义ISP-IAP操作地址寄存器高位
sfr ISP_CMD = 0XE5; //定义ISP-IAP命令寄存器
sfr ISP_TRIG = 0XE6; //定义ISP-IAP命令触发寄存器
sfr ISP_CONTR = 0XE7; //定义ISP-IAP命令寄存器
EEPROM.c
文件#include <reg52.h>
#include <EEPROM.h>
static void IAPTrigger();
static void IAPDisable();
static void IAPTrigger()
{
ISP_TRIG = 0x46; //对ISP-IAP命令触发寄存器写入触发命令0x46
ISP_TRIG = 0xB9; //对ISP-IAP命令触发寄存器写入触发命令0xB9
}
static void IAPDisable()
{
ISP_CONTR = 0x00; //禁用IAP读写EEPROM
ISP_CMD = 0x00; //无IAP操作
ISP_TRIG = 0x00; //关闭IAP功能
}
unsigned char IAPByteRead(unsigned int addr) { unsigned char dat; //定义数据缓存变量 ISP_CONTR = 0x81; //打开IAP功能,允许编程改变Flash,设置Flash操作等待时间 ISP_CMD = 0x01; //允许对"Data Flash/EEPROM区"进行字节读取 ISP_ADDRL = addr; //IAP操作地址寄存器低位 ISP_ADDRH = addr >> 8; //IAP操作地址寄存器高位 IAPTrigger(); //触发IAP功能 dat = ISP_DATA; //将需要读出的数据放进缓存变量 IAPDisable(); //禁用IAP功能 return dat; //将读取到的数据作为返回值 } void IAPSectorErase(unsigned int addr) { ISP_CONTR = 0x81; //打开IAP功能,允许编程改变Flash,设置Flash操作等待时间 ISP_CMD = 0x03; //允许对"Data Flash/EEPROM区"进行扇区擦除 ISP_ADDRL = addr; //写入IAP操作地址寄存器低位 ISP_ADDRH = addr >> 8; //写入IAP操作地址寄存器高位 IAPTrigger(); //触发IAP功能 IAPDisable(); //禁用IAP功能 } void IAPByteWrite(unsigned int addr, unsigned char dat) { ISP_CONTR = 0x81; //打开IAP功能,允许编程改变Flash,设置Flash操作等待时间 ISP_CMD = 0x02; //允许对"Data Flash/EEPROM区"进行字节写入 ISP_ADDRL = addr; //IAP操作地址寄存器低位 ISP_ADDRH = addr >> 8; //IAP操作地址寄存器高位 ISP_DATA = dat; //将需要写入的数据放进ISP_DATA IAPTrigger(); //触发IAP功能 IAPDisable(); //禁用IAP功能 }
void IAPSectorErase(unsigned int addr); //擦除指定扇区函数
void IAPByteWrite(unsigned int addr, unsigned char dat); //字节写入函数
unsigned char IAPByteRead(unsigned int addr); //字节读取函数
main.c
文件#include <reg52.h>
#include <EEPROM.h>
sbit LED1 = P2 ^ 4; //位定义LED1
sbit LED2 = P2 ^ 5; //位定义LED2
sbit LED3 = P2 ^ 6; //位定义LED3
sbit KEY1 = P3 ^ 2; //位定义KEY1
sbit KEY2 = P3 ^ 3; //位定义KEY2
sbit KEY3 = P3 ^ 4; //位定义KEY3
static void DelayNms(int nms);
static void DelayNms(int nms)
{
unsigned int i,j;
for(i = 0; i < nms; i++)
{
for(j = 0; j < 123; j++)
{
}
}
}
void main() { P2 = IAPByteRead(0x2000); //读取起始地址为0x2000的扇区中的值,赋值给P2寄存器,恢复LED灯状态 while(1) { if(0 == KEY1) //第一次检测到KEY1按键被按下 { DelayNms(50); //等待约50ms后再次检测按键是否被按下,消除按键抖动带来的影响 if(0 == KEY1) //第二次检测到KEY1按键被按下 { LED1 = ~LED1; //对LED1状态取反,改变LED1的亮灭状态 while(0 == KEY1); //等待按键弹起 IAPSectorErase(0x2000); //擦除起始地址为0x2000的扇区 IAPByteWrite(0x2000,P2); //对起始地址为0x2000的扇区写入P2寄存器的值 } } if(0 == KEY2) //第一次检测到KEY2按键被按下 { DelayNms(50); //等待约50ms后再次检测按键是否被按下,消除按键抖动带来的影响 if(0 == KEY2) //第二次检测到KEY2按键被按下 { LED2 = ~LED2; //对LED2状态取反,改变LED2的亮灭状态 while(0 == KEY2); //等待按键弹起 IAPSectorErase(0x2000); //擦除起始地址为0x2000的扇区 IAPByteWrite(0x2000,P2); //对起始地址为0x2000的扇区写入P2寄存器的值 } } if(0 == KEY3) //第一次检测到KEY3按键被按下 { DelayNms(50); //等待约50ms后再次检测按键是否被按下,消除按键抖动带来的影响 if(0 == KEY3) //第二次检测到KEY3按键被按下 { LED3 = ~LED3; //改变LED3的开关状态 while(0 == KEY3); //等待按键弹起 IAPSectorErase(0x2000); //擦除起始地址为0x2000的扇区 IAPByteWrite(0x2000,P2); //对起始地址为0x2000的扇区写入P2寄存器的值 } } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。