平台:stc12le5a60+W25X16+keil
W25X16.H
W25X.H
1 #ifndef _W25X_H_ 2 #define _W25X_H_ 3 4 #include <REG52.H> 5 6 #define uint8 unsigned char 7 #define uint16 unsigned int 8 #define uchar unsigned char 9 #define uint unsigned int 10 #define uint32 unsigned long 11 12 sbit W25X_HOLD= P1^2; 13 sbit W25X_WP = P1^3; 14 sbit W25X_CS = P1^4; 15 sbit W25X_DI = P1^5; 16 sbit W25X_DO = P1^6; 17 sbit W25X_CLK= P1^7; 18 19 #define nop() _nop_() 20 21 #define W25X_WriteEnable 0x06 //写使能 备注:xcc 22 #define W25X_WriteDisable 0x04 //写禁能 23 #define W25X_ReadStatusReg 0x05 //读状态寄存器 24 #define W25X_WriteStatusReg 0x01 //写状态寄存器 25 #define W25X_ReadData 0x03 //读数据 26 #define W25X_FastReadData 0x0B //读数据 27 #define W25X_FastReadDual 0x3B //快读双输出 28 #define W25X_PageProgram 0x02 //页编程 29 #define W25X_BlockErase 0xD8 //块擦除 30 #define W25X_SectorErase 0x20 //扇区擦除 31 #define W25X_ChipErase 0xC7 //芯片擦除 32 #define W25X_PowerDown 0xB9 //掉电 33 #define W25X_ReleasePowerDown 0xAB //释放掉电 34 #define W25X_DeviceID 0xAB //器件ID 35 #define W25X_ManufactDeviceID 0x90 //制造/器件ID 36 #define W25X_JedecDeviceID 0x9F //JEDEC ID 37 38 39 40 uchar SPI_Read_StatusReg(); 41 void SPI_Write_StatusReg(byte); 42 void SPI_Write_Enable(); 43 void SPI_Write_Disable(); 44 uchar SPI_Read_ID1(); 45 uint SPI_Read_ID2(uchar ID_Addr); 46 uint SPI_Read_ID3(); 47 uchar SPI_Read_Byte(uint32 Dst_Addr); 48 void SPI_Read_nBytes(uint32 Dst_Addr, uchar nBytes_128); 49 uchar SPI_FastRead_Byte(uint32 Dst_Addr); 50 void SPI_FastRead_nBytes(uint32 Dst_Addr, uchar nBytes_128); 51 void SPI_Write_Byte(uint32 Dst_Addr, uchar byte); 52 void SPI_Write_nBytes(uint32 Dst_Addr, uchar nBytes_128); 53 void SPI_Erase_Chip(); 54 void SPI_Erase_Sector(uint32 Dst_Addr); 55 void SPI_Wait_Busy(); 56 void SPI_PowerDown(); 57 void SPI_ReleasePowerDown(); 58 void SPI_init(); 59 void SPI_Send_Byte(uchar out); 60 uchar SPI_Get_Byte(); 61 void delay_nms(uchar i); 62 void delay(uchar tt); 63 64 #endif
W25X.C
W25X.C
1 #include <W25X.H> 2 #include <REG52.H> 3 #include <intrins.h> 4 5 extern uint8 upper_128[16]; 6 extern uint8 tx_buff[16]; 7 8 void delay_nms(uchar i) 9 { uchar j; 10 i=i*2; 11 for(;i>0;i--) { j = 246; while(--j); } 12 } 13 void delay(uchar tt) 14 { while(tt--);} 15 //================================================================================================= 16 //SPI_Read_StatusReg Reads the status register of the serial flash 17 //SPI_Write_StatusReg Performs a write to the status register 18 //SPI_Write_Enable Write enables the serial flash 19 //SPI_Write_Disable Write disables the serial flash 20 //SPI_Read_ID1 Reads the device ID using the instruction 0xAB 21 //SPI_Read_ID2 Reads the manufacturer ID and device ID with 0x90 22 //SPI_Read_ID3() Reads the JedecDevice ID 23 //SPI_Read_Byte Reads one byte from the serial flash and returns byte(max of 20 MHz CLK frequency) 24 //SPI_Read_nBytes Reads multiple bytes(max of 20 MHz CLK frequency) 25 //SPI_FastRead_Byte Reads one byte from the serial flash and returns byte(max of 33 MHz CLK frequency) 26 //SPI_FastRead_nBytes Reads multiple bytes(max of 33 MHz CLK frequency) 27 //SPI_Write_Byte Program one byte to the serial flash 28 //SPI_Write_nBytes Program n bytes to the serial flash, n<=256 29 //SPI_Erase_Chip Erases entire serial flash 30 //SPI_Erase_Sector Erases one sector (64 KB) of the serial flash 31 //SPI_Wait_Busy Polls status register until busy bit is low 32 //================================================================================================= 33 uchar SPI_Read_StatusReg() //读状态寄存器 备注:Xcc 34 { uchar byte = 0; 35 W25X_CS = 0; // enable device 36 SPI_Send_Byte(W25X_ReadStatusReg); // send Read Status Register command 37 byte = SPI_Get_Byte(); // receive byte 38 W25X_CS = 1; // disable device 39 return byte; 40 } 41 void SPI_Write_StatusReg(byte) //写状态寄存器 42 { W25X_CS = 0; // enable device 43 SPI_Send_Byte(W25X_WriteStatusReg); // select write to status register 44 SPI_Send_Byte(byte); // data that will change the status(only bits 2,3,7 can be written) 45 W25X_CS = 1; // disable the device 46 } 47 void SPI_Write_Enable() //写使能 48 { W25X_CS = 0; // enable device 49 SPI_Send_Byte(W25X_WriteEnable); // send W25X_Write_Enable command 50 W25X_CS = 1; // disable device 51 } 52 void SPI_Write_Disable() //写禁能 53 { W25X_CS = 0; // enable device 54 SPI_Send_Byte(W25X_WriteDisable); // send W25X_WriteW25X_DIsable command 55 W25X_CS = 1; // disable device 56 } 57 uchar SPI_Read_ID1() //释放掉电/器件ID 58 { uchar byte; 59 W25X_CS = 0; // enable device 60 SPI_Send_Byte(W25X_DeviceID); // send read device ID command (ABh) 61 SPI_Send_Byte(0); // send address 62 SPI_Send_Byte(0); // send address 63 SPI_Send_Byte(0); // send 3_Dummy address 64 byte = SPI_Get_Byte(); // receive Device ID byte 65 W25X_CS = 1; // disable device 66 delay(4); // remain CS high for tRES2 = 1.8uS 67 return byte; 68 } 69 uint SPI_Read_ID2(uchar ID_Addr) //制造/器件ID 70 { uint IData16; 71 W25X_CS = 0; // enable device 72 SPI_Send_Byte(W25X_ManufactDeviceID); // send read ID command (90h) 73 SPI_Send_Byte(0x00); // send address 74 SPI_Send_Byte(0x00); // send address 75 SPI_Send_Byte(ID_Addr); // send W25Pxx selectable ID address 00H or 01H 76 IData16 = SPI_Get_Byte()<<8; // receive Manufature or Device ID byte 77 IData16 |= SPI_Get_Byte(); // receive Device or Manufacture ID byte 78 W25X_CS = 1; // disable device 79 return IData16; 80 } 81 uint SPI_Read_ID3() //读JEDEC ID 82 { uint IData16; 83 W25X_CS = 0; // enable device 84 SPI_Send_Byte(W25X_JedecDeviceID); // send read ID command (9Fh) 85 IData16 = SPI_Get_Byte()<<8; // receive Manufature or Device ID byte 86 IData16 |= SPI_Get_Byte(); // receive Device or Manufacture ID byte 87 tx_buff[2] = SPI_Get_Byte(); 88 W25X_CS = 1; // disable device 89 return IData16; 90 } 91 uchar SPI_Read_Byte(uint32 Dst_Addr) //读某地址 数据 92 { uchar byte = 0; 93 W25X_CS = 0; // enable device 94 SPI_Send_Byte(W25X_ReadData); // read command 95 SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFFFF) >> 16));// send 3 address bytes 96 SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFF) >> 8)); 97 SPI_Send_Byte((uchar)(Dst_Addr & 0xFF)); 98 byte = SPI_Get_Byte(); 99 W25X_CS = 1; // disable device 100 return byte; // return one byte read 101 } 102 void SPI_Read_nBytes(uint32 Dst_Addr, uchar nBytes_128) //读某地址起nBytes_128字节以内内容 103 { uint32 i = 0; 104 W25X_CS = 0; // enable device 105 SPI_Send_Byte(W25X_ReadData); // read command 106 SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); // send 3 address bytes 107 SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8)); 108 SPI_Send_Byte(Dst_Addr & 0xFF); 109 for (i = 0; i < nBytes_128; i++) // read until no_bytes is reached 110 upper_128[i] = SPI_Get_Byte(); // receive byte and store at address 80H - FFH 111 W25X_CS = 1; // disable device 112 } 113 uchar SPI_FastRead_Byte(uint32 Dst_Addr) //快读 某地址 数据 114 { uchar byte = 0; 115 W25X_CS = 0; // enable device 116 SPI_Send_Byte(W25X_FastReadData); // fast read command 117 SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); // send 3 address bytes 118 SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8)); 119 SPI_Send_Byte(Dst_Addr & 0xFF); 120 SPI_Send_Byte(0xFF); // dummy byte 121 byte = SPI_Get_Byte(); 122 W25X_CS = 1; // disable device 123 return byte; // return one byte read 124 } 125 void SPI_FastRead_nBytes(uint32 Dst_Addr, uchar nBytes_128) //快读 某地址 nBytes_128 个字节数据 126 { uchar i = 0; 127 W25X_CS = 0; // enable device 128 SPI_Send_Byte(W25X_FastReadData); // read command 129 SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); // send 3 address bytes 130 SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8)); 131 SPI_Send_Byte(Dst_Addr & 0xFF); 132 SPI_Send_Byte(0xFF); // dummy byte 133 for (i = 0; i < nBytes_128; i++) // read until no_bytes is reached 134 upper_128[i] = SPI_Get_Byte(); // receive byte and store at address 80H - FFH 135 W25X_CS = 1; // disable device 136 } 137 void SPI_Write_Byte(uint32 Dst_Addr, uchar byte) //页编程 138 { W25X_CS = 0; // enable device 139 SPI_Write_Enable(); // set WEL 140 SPI_Wait_Busy(); 141 W25X_CS = 0; 142 SPI_Send_Byte(W25X_PageProgram); // send Byte Program command 143 SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); // send 3 address bytes 144 SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8)); 145 SPI_Send_Byte(Dst_Addr & 0xFF); 146 SPI_Send_Byte(byte); // send byte to be programmed 147 W25X_CS = 1; // disable device 148 } 149 void SPI_Write_nBytes(uint32 Dst_Addr, uchar nBytes_128) //页编程 128个字节 150 { 151 uchar i, byte; 152 W25X_CS = 0; /* enable device */ 153 SPI_Write_Enable(); /* set WEL */ 154 W25X_CS = 0; 155 SPI_Send_Byte(W25X_PageProgram); /* send Byte Program command */ 156 SPI_Send_Byte(((Dst_Addr & 0xFFFFFF) >> 16)); /* send 3 address bytes */ 157 SPI_Send_Byte(((Dst_Addr & 0xFFFF) >> 8)); 158 SPI_Send_Byte(Dst_Addr & 0xFF); 159 160 for (i = 0; i < nBytes_128; i++) 161 { 162 byte = upper_128[i]; 163 SPI_Send_Byte(byte); /* send byte to be programmed */ 164 } 165 W25X_CS = 1; /* disable device */ 166 } 167 void SPI_Erase_Chip() //擦除芯片 168 { 169 W25X_CS = 0; // enable device 170 SPI_Write_Enable(); // set WEL 171 W25X_CS = 0; 172 SPI_Wait_Busy(); 173 W25X_CS = 0; 174 SPI_Send_Byte(W25X_ChipErase); // send Chip Erase command 175 W25X_CS = 1; // disable device 176 } 177 void SPI_Erase_Sector(uint32 Dst_Addr) //扇区擦除 178 { W25X_CS = 0; // enable device 179 SPI_Write_Enable(); // set WEL 180 W25X_CS = 0; 181 SPI_Send_Byte(W25X_SectorErase); // send Sector Erase command 182 SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFFFF) >> 16));// send 3 address bytes 183 SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFF) >> 8)); 184 SPI_Send_Byte((uchar)Dst_Addr & 0xFF); 185 W25X_CS = 1; // disable device 186 } 187 void SPI_Wait_Busy() //等待忙结束 188 { while (SPI_Read_StatusReg() == 0x03) 189 SPI_Read_StatusReg(); // waste time until not busy WEL & Busy bit all be 1 (0x03) 190 } 191 void SPI_PowerDown() 192 { W25X_CS = 0; // enable device 193 SPI_Send_Byte(W25X_PowerDown); // send W25X_PowerDown command 0xB9 194 W25X_CS = 1; // disable device 195 delay(6); // remain CS high for tPD = 3uS 196 } 197 void SPI_ReleasePowerDown() 198 { W25X_CS = 0; // enable device 199 SPI_Send_Byte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB 200 W25X_CS = 1; // disable device 201 delay(6); // remain CS high for tRES1 = 3uS 202 } 203 204 205 206 #ifdef SST_SPI 207 void SPI_init() 208 { P1 = 0xFF; 209 SPCR = 0x50; 210 } 211 void SPI_Send_Byte(uchar out) 212 { unsigned char temp; 213 SPDR = out; 214 do { temp = SPSR & 0x80; } while (temp != 0x80); 215 SPSR = SPSR & 0x7F; 216 } 217 uchar SPI_Get_Byte() 218 { unsigned char temp; 219 SPDR = 0x00; 220 do { temp = SPSR & 0x80; } while (temp != 0x80); 221 SPSR = SPSR & 0x7F; 222 return SPDR; 223 } 224 #endif 225 226 #ifndef SST_SPI 227 void SPI_init() 228 { W25X_CLK = 0; // set clock to low initial state for SPI operation mode 0 229 // W25X_CLK = 1; // set clock to High initial state for SPI operation mode 3 230 // _hold = 1; 231 W25X_WP = 1; 232 W25X_CS = 1; 233 SPI_Write_Disable(); 234 } 235 void SPI_Send_Byte(uchar out) 236 { uchar i = 0; 237 for (i = 0; i < 8; i++) 238 { if ((out & 0x80) == 0x80) // check if MSB is high 239 W25X_DI = 1; 240 else 241 W25X_DI = 0; // if not, set to low 242 W25X_CLK = 1; // toggle clock high 243 out = (out << 1); // shift 1 place for next bit 244 nop();nop();nop();nop(); 245 W25X_CLK = 0; // toggle clock low 246 } 247 } 248 uchar SPI_Get_Byte() 249 { uchar i = 0, in = 0, temp = 0; 250 for (i = 0; i < 8; i++) 251 { in = (in << 1); // shift 1 place to the left or shift in 0 252 temp = W25X_DO; // save input 253 W25X_CLK = 1; // toggle clock high 254 if (temp == 1) // check to see if bit is high 255 in |= 0x01; // if high, make bit high 256 W25X_CLK = 0; // toggle clock low 257 } 258 return in; 259 } 260 #endif
MAIN.C
MAIN.C
#include <REG52.H> #include <intrins.h> #include <W25X.H> #define uint8 unsigned char #define uint16 unsigned int #define uchar unsigned char #define uint unsigned int #define uint32 unsigned long void init_cpu(void); void delay(uchar tt); void trace(uchar *str,uchar len); void test_page(uchar addr); void read_page(uchar addr); void Verify(uchar byte, uchar cor_byte); uint8 Rxtemp; bit MYTI; uint8 tx_buff[16]; uint8 upper_128[16]; bit rx_ok; void main(void) { uint i; W25X_HOLD= 1; init_cpu(); SPI_init(); tx_buff[0]='O'; tx_buff[1]='K'; trace(tx_buff,2); for(;;) { if(rx_ok == 1) { rx_ok = 0; switch(Rxtemp) { case 0x01: Rxtemp = 0; tx_buff[0] = SPI_Read_ID1(); trace(tx_buff,1); break; case 0x02: i = SPI_Read_ID2(0x00); tx_buff[1] = (uchar)i; tx_buff[0] = (uchar)(i>>8); trace(tx_buff,2); break; case 0x03: i = SPI_Read_ID3(); tx_buff[1] = (uchar)i; tx_buff[0] = (uchar)(i>>8); trace(tx_buff,3); break; case 0x04: tx_buff[0] = SPI_Read_Byte(0x00000000); trace(tx_buff,1); break; case 0x05: tx_buff[0] = 0x55; SPI_Write_Byte(0x00000000,0xa5); trace(tx_buff,1); break; case 0x06: tx_buff[0] = SPI_Read_StatusReg(); trace(tx_buff,1); break; case 0x07: SPI_Write_Enable(); break; case 0x08: upper_128[0]=0x01;upper_128[1]=0x02;upper_128[2]=0x03;upper_128[3]=0x04; SPI_Write_nBytes(0x00000000,4); break; case 0x09: SPI_Erase_Chip(); break; case 0x0a: SPI_Erase_Sector(0x000ff000); while(1) { tx_buff[0] = SPI_Read_StatusReg(); if(tx_buff[0] == 0) { trace(tx_buff,1); break; } } break; case 0x0b: test_page(0x00); break; case 0x0c: read_page(0x00); break; default: break; } } } } void init_cpu(void) { TMOD = 0x21; PCON = PCON | 0x80; //波特率加倍 SCON = 0x50; //异步、10位、波特率可变,无校验位 TH1 = 0xf4; //在11.0592M晶振下,波特率是9600, TL1 = 0xf4; TR1 = 1; //T1 timer run ES = 1; //uart interrupt enable EA = 1; //all interrupt enable } //串口中断程序 void UART_isr(void) interrupt 4 { if(RI) { RI = 0; Rxtemp = SBUF; //接收 //SBUF = Rxtemp; //发送 rx_ok = 1; return; } if(TI) { TI = 0; MYTI = 1; } } void test_page(uchar addr) { uint i; uchar byte; uint32 Dst_Addr; W25X_CS = 0; // enable device SPI_Write_Enable(); // set WEL W25X_CS = 0; Dst_Addr = (uint32)addr*256; Dst_Addr = 0x0ff000;//(uint32)addr*256; SPI_Send_Byte(W25X_PageProgram); // send Byte Program command SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFFFF) >> 16)); // send 3 address bytes SPI_Send_Byte((uchar)((Dst_Addr & 0xFFFF) >> 8)); SPI_Send_Byte((uchar)(Dst_Addr & 0xFF)); for (i = 0; i < 256; i++) // send byte to be programmed SPI_Send_Byte(i); W25X_CS = 1; delay_nms(5); W25X_CS = 0; while(1) { tx_buff[0] = SPI_Read_StatusReg(); trace(tx_buff,1); if(tx_buff[0] == 0) break; } Dst_Addr = 0x0ff000; for (i = 0; i < 256; i++) { byte = SPI_Read_Byte(Dst_Addr+i); ES = 0; SBUF = byte; while (TI == 0); TI = 0; ES = 1; } W25X_CS = 1; } //================================================================================================= void read_page(uchar addr) { uint i; uchar byte; uint32 Dst_Addr; Dst_Addr = addr*256; Dst_Addr = 0x0ff000; W25X_CS = 0; for (i = 0; i < 256; i++) { byte = SPI_Read_Byte(Dst_Addr+i); ES = 0; SBUF = byte; while (TI == 0); TI = 0; ES = 1; } W25X_CS = 1; } //================================================================================================= void Verify(uchar byte, uchar cor_byte) { if (byte != cor_byte) { while(1); //LED_Error = 0; /* display to view error on LED. */ } } //================================================================================================= void myputchar(uchar c) { ES = 0; SBUF = c; while (TI == 0); TI = 0; ES = 1; } //================================================================================================= void trace(uchar *str,uchar len) { uint i; for(i=0;i<len;i++) { myputchar(*str); str++; } }
以上测试正确