📄 mm36sb020.c
字号:
/* ---------- 宏晶科技 大唐设计 5/15/2003--- */
/* ---Fax: 0755-82902881,82944243 ----------- */
/* ---Mobile:0755-26346768,13922805190------- */
/* ---Email: sales@mcu-memory.com------------ */
/* -----------调试注意事项?----------------- */
/* IEB(片选信号) 可固定接到地,也可以由I/O来片选 */
/* SDO,SDIO,SCLK,各接一100K电阻到地 */
/* MM36SB020 OSC端:接一300K电阻到 VCC,一100p电容到 GND,加快速度。大唐不接时,没调通 */
/* MM36SB010 OSC端:接一680K电阻到 VCC,一100p电容到 GND,加快速度. 也可不接 */
/* MM36SB020 SMC0,SMC1端: SMC0 , SMC1 = 1 , 0 二线制; SMC0 , SMC1 = 0 , 0 三线制 */
/* MM36SB010 SMC端: 接到 VCC,二线制;接到 GND,三线制 */
#include <reg52.h>
#include <stdio.h>
#include <intrins.h>
/* 调试控制项 */
#define DEBUG_2_WIRE
//#define DEBUG_BUSY_PIN
#define DEBUG_MM36SB020
#define DEBUG_read_write_buffer
#define DEBUG_read_flash_sector
#define DEBUG_write_and_read_flash_sector
#ifdef DEBUG_2_WIRE
sbit SCLK = P1^7;
sbit SDO = P1^5;
sbit SDI = P1^5;
sbit IEB = P1^4;
#else
sbit SCLK = P1^7;
sbit SDO = P1^6;
sbit SDI = P1^5;
sbit IEB = P1^4;
#endif
#ifdef DEBUG_BUSY_PIN
sbit BUSY_PIN = P1^6;
#endif
/* 定义命令 */
#define ERSC 0x90f6 /* 檫除整个芯片 */
#define SRC 0xfffffffe /* 软件复位芯片 */
#define RSE 0x94 /* 读状态寄存器 */
#define RBE 0x98 /* 读一个字节数据从缓冲区 */
#define RME 0x9c /* 读一个字节数据从Flash存储器 */
#define RMEC 0xa0 /* 连续读一字节数据从Flash存储器,先自动地址增加 */
#define RMB 0xa4 /* 读一页数据(128 byte),从Flash存储器到缓冲区 */
#define WEB 0xa8 /* 写一个字节数据到缓冲区 */
#define WEBC 0xac /* 连续写一个字节数据到缓冲区,先自动地址增加 */
#define WBMEP 0xb0 /* 写缓冲区数据到Flash存储器,先自动页檫除 */
#define WBME 0xb4 /* 写缓冲区数据到Flash存储器,没有自动页檫除 */
/* 定义常量 */
#define LOW 0
#define HIGH 1
#define BUSY 2
#define OK 3
#define ARRAY_SIZE 128
#define COUNTER 128
/* #define Byte unsigned char */
/* #define Word unsigned int */
typedef unsigned char INT8U; /* 8 bit 无符号整型 */
typedef unsigned int INT16U; /* 16 bit 无符号整型 */
typedef unsigned long int INT32U; /* 32 bit 无符号整型 */
void delay_time(INT16U k); /* 延时函数 */
void clear_buffer(void); /* 清 CPU 内部缓冲区 INT8U idata verify_buffer[128] */
void send_reset_com(); /* 复位命令函数 */
INT8U busy(); /* 读状态函数 */
INT8U read_one_byte(); /* 读一字节 */
void send_one_byte(INT8U one_data); /* 发送一字节 */
void send_two_byte(INT16U one_data); /* 发送二字节 */
/* 读数据从缓冲区: */
/* in_buffer_begin_addr为缓冲区内开始地址, counter为读多少个数, array[]为MCU内部存储空间 */
INT8U read_data_from_buffer(INT8U in_buffer_begin_addr, INT8U counter, INT8U array[]);
/* 读数据从flash存储器: */
/* page_addr为页地址, in_page_byte_addr为页内地址, counter为读多少个数, array[]为MCU内部存储空间 */
INT8U read_data_from_flash(INT16U page_addr, INT8U in_page_byte_addr, INT8U counter, INT8U array[]);
/* 读一页数据到缓冲区,从flash存储器,page_addr为页地址 */
INT8U read_to_buffer_from_flash(INT16U page_addr);
/* 写数据到缓冲区 */
/* in_buffer_begin_addr为缓冲区内开始地址, counter为写多少个数, array[]为MCU内部存储空间 */
INT8U write_data_to_buffer(INT8U in_buffer_begin_addr, INT8U counter, INT8U send_array[]);
/* 写数据到Flash存储器 */
/* page_addr为页地址, in_page_begin_addr为页内地址,counter为写多少个数,send_array[]为MCU内部存储空间 */
INT8U write_data_to_flash(INT16U page_addr, INT8U in_page_begin_addr, INT8U counter, INT8U send_array[]);
/* 测试常量数组 */
INT8U code Test_array[128] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
};
INT8U code Test_array_continue[128] =
{
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
INT8U code Test_array_reverse[128] =
{
0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0,
0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8,
0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0,
0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8,
0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0,
0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0,
0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8,
0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98,
0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88,
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
};
INT8U idata verify_buffer[128];
void main()
{
INT8U buffer_index = 0;
P1 = 0xff;
P1 = 0xfe; //1111,1110;
P1 = 0xfd; //1111,1101;
P1 = 0xfb; //1111,1011;
P1 = 0xff;
/* 以上测试仿真器是否正常工着 */
#ifndef DEBUG_2_WIRE
IEB = LOW; // 选通 mm36sb010
#endif
send_reset_com(); // 发送 e-flash 复位命令 */
delay_time(10000); // 延时
while(1)
{
INT16U i = 0;
#ifdef DEBUG_read_write_buffer
clear_buffer(); /* 清 CPU 内部缓冲区 INT8U idata verify_buffer[128] */
while( busy() );
read_data_from_buffer(0, 128, verify_buffer); /* 读数据从 e-Flash 缓冲区 */
write_data_to_buffer(0, 128, Test_array); /* 写数据到 e-Flash 缓冲区 */
clear_buffer(); /* 清 CPU 内部缓冲区 INT8U idata verify_buffer[128] */
while( busy() );
read_data_from_buffer(0, 128, verify_buffer); /* 读数据从 e-Flash 缓冲区 */
write_data_to_buffer(0, 128, Test_array_continue); /* 写数据到 e-Flash 缓冲区 */
clear_buffer(); /* 清 CPU 内部缓冲区 INT8U idata verify_buffer[128] */
while( busy() );
read_data_from_buffer(0, 128, verify_buffer); /* 读数据从 e-Flash 缓冲区 */
write_data_to_buffer(0, 128, Test_array_reverse); /* 写数据到 e-Flash 缓冲区 */
clear_buffer(); /* 清 CPU 内部缓冲区 INT8U idata verify_buffer[128] */
while( busy() );
read_data_from_buffer(0, 128, verify_buffer); /* 读数据从 e-Flash 缓冲区 */
_nop_();
#endif
#ifdef DEBUG_read_flash_sector
for(i = 0; i < 10; i++) // MM36SB010 为 1024 个扇区,MM36SB020 为 2048 个扇区
{
clear_buffer(); /* 清 CPU 内部缓冲区 INT8U idata verify_buffer[128] */
read_data_from_flash(i, 0x00, COUNTER, verify_buffer);
// 读: 从第i个扇区第0个字节 共 COUNTER 个字节,读到 verify_buffer[128]
_nop_();
}
_nop_();
#endif
#ifdef DEBUG_write_and_read_flash_sector
for(i = 0; i < 10; i++)
{
clear_buffer(); /* 清 CPU 内部缓冲区 INT8U idata verify_buffer[128] */
write_data_to_flash(i, 0, COUNTER, Test_array);
// 将Test_array[128]数组的数写入第 i 个扇区
while( busy() ); //delay_time(10000);延时: MM36SB010,--17--26mS,without Rosc;MM36SB020,--12--18mS,with Rosc
read_data_from_flash(i, 0, COUNTER, verify_buffer);
// 读: 从第i个扇区第0个字节 共 COUNTER 个字节,到 verify_buffer[128]
clear_buffer(); /* 清 CPU 内部缓冲区 INT8U idata verify_buffer[128] */
write_data_to_flash(i, 0, COUNTER, Test_array_continue);
// 将Test_array_continue[128]数组的数写入第 i 个扇区
while( busy() ); //delay_time(10000); 延时: MM36SB010,--17--26mS,without Rosc;MM36SB020,--12--18mS,with Rosc
read_data_from_flash(i, 0, COUNTER, verify_buffer);
// 读: 从第i个扇区第0个字节 共 COUNTER 个字节,到 verify_buffer[128]
clear_buffer(); /* 清 CPU 内部缓冲区 INT8U idata verify_buffer[128] */
write_data_to_flash(i, 0, COUNTER, Test_array_reverse);
// 将Test_array_continue[128]数组的数写入第 i 个扇区
while( busy() ); //delay_time(10000);延时: MM36SB010,--17--26mS,without Rosc;MM36SB020,--12--18mS,with Rosc
read_data_from_flash(i, 0, COUNTER, verify_buffer);
// 读: 从第i个扇区第0个字节 共 COUNTER 个字节,到 verify_buffer[128]]
_nop_();
}
_nop_();
#endif
}
}
void delay_time(INT16U k)
{
INT16U j = 0;
for(j = 0; j<k; j++)
{
;
}
}
void clear_buffer(void)
{
INT8U buffer_index = 0;
for(buffer_index = 0; buffer_index < 128; buffer_index++)
{
verify_buffer[buffer_index] = 0; /* 清 CPU 内部缓冲区 */
}
}
void send_reset_com()
{
send_one_byte(0xfe);
send_one_byte(0xff);
send_one_byte(0xff);
send_one_byte(0xff);
}
INT8U read_one_byte()
{
INT8U i = 0, temp = 0, one_data = 0;
SDO = HIGH;
for(i = 0; i < 8; i ++)
{
SCLK = LOW;
one_data = one_data >> 1;
#ifdef DEBUG_MM36SB020
_nop_();
_nop_();
#endif
SCLK = HIGH;
#ifdef DEBUG_MM36SB020
_nop_();
_nop_();
#endif
if(temp = SDO)
one_data = one_data | 0x80;
}
SCLK = LOW;
return (one_data);
}
void send_one_byte(INT8U one_data)
{
INT8U i = 0;
// SCLK = LOW;
for(i = 0;i < 8;i ++)
{
SCLK = LOW;
SDI = one_data & 0x01;
#ifdef DEBUG_MM36SB020
_nop_();
_nop_();
#endif
SCLK = HIGH;
one_data = one_data >> 1;
#ifdef DEBUG_MM36SB020
_nop_();
_nop_();
#endif
}
// SDI = HIGH;
SCLK = LOW;
}
void send_two_byte(INT16U one_data)
{
INT8U i = 0;
for(i = 0;i < 16;i ++)
{
SCLK = LOW;
SDI = one_data & 0x01;
#ifdef DEBUG_MM36SB020
_nop_();
_nop_();
#endif
SCLK = HIGH;
one_data = one_data >> 1;
#ifdef DEBUG_MM36SB020
_nop_();
_nop_();
#endif
}
// SDI = HIGH;
SCLK = LOW;
}
#ifdef DEBUG_BUSY_PIN
INT8U busy( ) /*读状态命令*/
{
if(ACC = BUSY_PIN)
return 1;
else
return 0;
}
#else
INT8U busy( ) /*读状态命令*/
{
INT8U temp = 0;
send_one_byte(RSE); /*送RSE命令*/
temp = read_one_byte();
if(temp & 0x01) return 1; /* BUSY */
else return 0;
}
#endif
/* 读数据从缓冲区: */
/* in_buffer_begin_addr为缓冲区内开始地址, counter为读多少个数, array[]为MCU内部存储空间 */
INT8U read_data_from_buffer(INT8U in_buffer_begin_addr, INT8U counter, INT8U array[])
{
INT8U i ,temp=0;
if(busy()) return BUSY;
for(i = 0; i < counter; i ++) /* 连续读数据 */
{
send_one_byte(RBE); /* 送 RBE 指令, 读一个字节数据从 Buffer */
send_one_byte(in_buffer_begin_addr + i); /* 送页内地址 */
array[i] = read_one_byte(); /* 读数据 */
}
return OK;
}
/* 读数据从flash存储器: */
/* page_addr为页地址, in_page_byte_addr为页内地址, counter为读多少个数, array[]为MCU内部存储空间 */
INT8U read_data_from_flash(INT16U page_addr, INT8U in_page_byte_addr, INT8U counter, INT8U array[])
{
INT8U i ,temp=0;
if(busy()) return BUSY;
send_one_byte(RME); /* 送 RME 指令, 读一个字节数据从Flash存储器 */
send_one_byte(in_page_byte_addr); /* 送页内地址 */
send_two_byte(page_addr); /* 送页地址 */
array[0] = read_one_byte(); /* 读数据 */
for(i = 1; i < counter; i ++) /* 连续读数据 */
{
send_one_byte(RMEC); /* 送 RMEC 指令,连续读一字节数据从Flash存储器,先自动地址增加 */
array[i] = read_one_byte();
}
return OK;
}
/* 读一页数据到缓冲区,从flash存储器,page_addr为页地址 */
INT8U read_to_buffer_from_flash(INT16U page_addr)
{
INT8U i ,temp=0;
if(busy()) return BUSY;
send_one_byte(RMB); /* 送 RMB 指令, 读一页数据到缓冲区,从Flash存储器 */
send_two_byte(page_addr); /* 送页地址 */
delay_time(135); /* MM36SB010, Max = 135 uS, without Rosc; MM36SB020, Max = 105 uS, with Rosc */
return OK;
}
/* 写数据到缓冲区 */
/* in_buffer_begin_addr为缓冲区内开始地址, counter为写多少个数, send_array[]为MCU内部存储空间 */
INT8U write_data_to_buffer(INT8U in_buffer_begin_addr, INT8U counter, INT8U send_array[])
{
INT8U i = 0;
if(busy()) return BUSY;
send_one_byte(WEB); /* 送 WEB 指令,写一个字节数据到缓冲区 */
send_one_byte(in_buffer_begin_addr); /* 送缓冲区内首地址 */
send_one_byte(send_array[0]); /* 送第一字节数据 */
for(i = 1;i < counter; i ++)
{
send_one_byte(WEBC); /* 连续写一个字节数据到缓冲区,先自动地址增加 */
send_one_byte(send_array[i]); /* 送第 i 字节数据 */
}
return OK;
}
/* 写数据到Flash存储器 */
/* page_addr为页地址, in_page_begin_addr为页内地址,counter为写多少个数,send_array[]为MCU内部存储空间 */
INT8U write_data_to_flash(INT16U page_addr, INT8U in_page_begin_addr, INT8U counter, INT8U send_array[])
{
INT8U i = 0;
if(busy()) return BUSY;
read_to_buffer_from_flash(page_addr); /* 将整页数据读进缓冲区进行保护 */
write_data_to_buffer(in_page_begin_addr, counter, send_array);
/* in_buffer_begin_addr = in_page_begin_addr, 在缓冲区中修改相应的数据 */
send_one_byte(WBMEP); /* 送WBMEP指令, 写缓冲区数据到Flash存储器,先自动页檫除 */
send_two_byte(page_addr); /* 送页字节地址 */
return OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -