标题:
STM32F103使用SPI读取EEPROM源程序
[打印本页]
作者:
Modbus下载
时间:
2019-7-16 09:49
标题:
STM32F103使用SPI读取EEPROM源程序
SPI读取EEPROM用的比较少,这个程序可以借鉴一下
单片机源程序如下:
#include "stm32f10x.h"
#include "25LC512.h"
#include "delay.h"
#include "led.h"
//PB5-mosi;PB3-clk;PA15-cs;PB4-miso;//
void LC512_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA, ENABLE);
/*PB3默认JTAG,需要先禁用再作为普通IO*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
DBGMCU->CR &= ~((uint32_t)1<<5);
AFIO->MAPR = (AFIO->MAPR & ~((uint32_t)0x7 << 24)) | (2 << 24); /* PA15 PB3 PB4 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//PB4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PA15
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
}
//初始化芯片
void init(void) // void main(void)第一个void表示函数没有返回值,第二个表示不带任何有实际意义的参数
{
cs = 1;
// miso = 0;
mosi = 1;
clk = 1;
}
void delay(u8 t) //延时
{
u8 i,j;
for(i = t;i > 0;i --)
for(j =0 ;j < 10;j ++)
{;;}
}
//write commend enable or disable signal
void spi_wren(u8 wren_com) //write enable wren_com=0x06 设置写使能0000 0110
{
u8 i;
u8 dig;
cs=0;
delay_us(10);
for(i=0;i<8;i++)
{
clk=0;
delay_us(10);
dig=wren_com>>7;
if(dig)
{ mosi=1;}
else
{mosi=0;}
wren_com=wren_com<<1;
clk=1;
delay_us(10);
}
delay_us(10);
//mosi = 0; //mosi=0,scl=0,when 8 bit data move over
clk = 1;
cs = 1;
delay_us(10);
}
void spi_wrdi(u8 wrdi_com) //write disable wr_com=0x04 设置写不使能0000 0100
{
u8 i;
u8 dig;
cs=0;
delay_us(10);
for(i=0;i<8;i++)
{
clk=0;
delay_us(10);
dig=wrdi_com>>7;
if(dig)
{ mosi=1;}
else
{mosi=0;}
wrdi_com=wrdi_com<<1;
clk=1;
delay_us(10);
}
delay_us(10);
//mosi = 0; //mosi=0,scl=0,when 8 bit data move over
clk = 1;
cs = 1;
delay_us(10);
}
//byte write 0000 0010
void spi_byte_write(u8 wr_byte_com,u16 wr_addr,u8 wr_dat) //write 1 btye data
{
u8 i,dig;
u16 j;
cs=0;
//delay_us(10);
for(i=0;i<8;i++)
{
clk=0;
//delay_us(10);
dig=wr_byte_com>>7;
if(dig)
{ mosi=1;}
else
{mosi=0;}
wr_byte_com=wr_byte_com<<1;
clk=1;
delay_us(1);
}
delay_us(1);
clk = 1;
for(j=0;j<16;j++)
{
clk=0;
//delay_us(10);
dig=wr_addr>>15; // output instruction code "0x02"
if(dig)
{ mosi=1;}
else
{mosi=0;}
wr_addr=wr_addr<<1;
clk=1;
delay_us(1);
}
delay_us(1);
clk = 1;
for(i=0;i<8;i++)
{
clk=0;
//delay_us(10);
dig=wr_dat>>7;
if(dig)
{ mosi=1;}
else
{mosi=0;}
wr_dat=wr_dat<<1;
clk=1;
delay_us(1);
}
delay_us(1);
// mosi = 0;
clk = 1;
cs = 1;
// check_wip(); //要有检测写入是否结束函数
}
/*
function name:spi_page write
//write 8 btye data
*/
void spi_page_write(u8 wr_page_com,u16 wr_addr,u8 len,u8 *pwr_dat)
{
u8 i,dig,n;
u16 j;
cs=0;
//delay_us(10);
for(i=0;i<8;i++)
{
clk=0;
//delay_us(10);
dig=wr_page_com&0x80;
if(dig)
{mosi=1;}
else
{mosi=0;}
wr_page_com=wr_page_com<<1;
clk=1;
delay_us(1);
}
delay_us(1);
clk = 1;
for(j=0;j<16;j++)
{
clk=0;
// delay_us(10);
dig=wr_addr>>15; // output instruction code "0x02"
if(dig)
{ mosi=1;}
else
{mosi=0;}
wr_addr=wr_addr<<1;
clk=1;
delay_us(1);
}
delay_us(1);
clk = 1;
for(n=0;n<len;n++)
{
for(i=0;i<8;i++)
{
clk=0;
// delay_us(10);
dig= pwr_dat[n]&0x80;
if(dig)
{ mosi=1;}
else
{mosi=0;}
pwr_dat[n]=pwr_dat[n]<<1;
clk=1;
delay_us(1);
}
delay_us(1);
clk=1;
}
delay_us(1);
//mosi = 0;
clk = 1;
cs = 1;
check_wip(); //要有检测写入是否结束函数
}
//read a byte data 0000 0011
u8 spi_byte_read(u8 read_com,u16 read_addr)
{
u8 read_dat,i,dig;
u16 j;
cs=0;
//delay_us(10);
for(i=0;i<8;i++)
{
clk=0;
//delay_us(10);
dig=read_com>>7;
if(dig)
{ mosi=1;}
else
{mosi=0;}
read_com=read_com<<1;
clk=1;
delay_us(1);
}
delay_us(1);
clk = 1;
for(j=0;j<16;j++)
{
clk=0;
//delay_us(10);
dig=read_addr>>15; // output instruction code "0x02"
if(dig)
{ mosi=1;}
else
{mosi=0;}
read_addr=read_addr<<1;
clk=1;
delay_us(1);
}
delay_us(1);
clk = 1;
for(i=0;i<8;i++)
{
clk=1;
//delay_us(10);
read_dat = read_dat << 1;
clk=0;
//delay_us(10);
//moso2=GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15); //读取输出口电平高低
read_dat|=moso;
delay_us(1);
}
delay_us(1);
clk = 1;
cs = 1;
return read_dat;
}
// page read
u8* spi_page_read(u8 read_com,u8 len,u16 wr_addr)
{
u8 rd_page_dat,i,dig,n,read_dat[128]={0},*read_out;
u16 j;
// miso=0;
cs=0;
// delay_us(10);
for(i=0;i<8;i++)
{
clk=0;
// delay_us(10);
dig=read_com>>7;
if(dig)
{ mosi=1;}
else
{mosi=0;}
read_com=read_com<<1;
clk=1;
delay_us(1);
}
clk = 1;
delay_us(1);
//mosi=0;
for(j=0;j<16;j++)
{
clk=0;
// delay_us(10);
dig=wr_addr>>15;
if(dig)
{ mosi=1;}
else
{mosi=0;}
wr_addr=wr_addr<<1;
clk=1;
delay_us(1);
}
//mosi=0;
clk = 1;
delay_us(1);
for(n = 0;n < len;n ++)
{
rd_page_dat = read_dat[n];
for(i=0;i<8;i++)
{
clk=1;
delay_us(1);
rd_page_dat = rd_page_dat<< 1;
clk=0;
//delay_us(10);
//moso2=GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15);//读取输出口电平高低
rd_page_dat|=moso;
delay_us(1);
}
read_dat[n]=rd_page_dat;
}
clk = 1;
cs = 1;
delay_us(1);
read_out=read_dat;
return read_out;
}
//write status 写入状态 设置status register状态寄存器写入0000 0001以及要写入的数据wrsr-dat
void spi_wrsr(u8 wrsr_com,u8 wrsr_dat)
{
u8 i;
u8 dig;
cs=0;
delay_us(10);
for(i=0;i<8;i++)
{
clk=0;
delay_us(10);
dig=wrsr_com>>7; //write status instruction is 0x01
if(dig)
{ mosi=1;}
else
{mosi=0;}
wrsr_com=wrsr_com<<1;
clk=1;
delay_us(10);
}
clk = 1;
delay_us(10);
for(i=0;i<8;i++)
{
clk=0;
delay_us(10);
dig=wrsr_dat>>7;
if(dig)
{ mosi=1;}
else
{mosi=0;}
wrsr_dat=wrsr_dat<<1;
clk=1;
delay_us(10);
}
//mosi = 0;
clk = 1;
cs = 1;
delay_us(10);
}
//read status 0000 0101
u8 spi_rdsr(u8 wdsr_com)
{
u8 dig;
u8 read_status,i;
cs=0;
delay_us(10);
for(i=0;i<8;i++)
{
clk=0;
delay_us(10);
dig=wdsr_com>>7; // first write instruction to mosi 0x05
if(dig)
{ mosi=1;}
else
{mosi=0;}
wdsr_com=wdsr_com<<1;
clk=1;
delay_us(10);
}
clk = 1;
delay_us(10);
for(i=0;i<8;i++)
{
clk=1;
delay_us(10);
read_status = read_status << 1;
clk=0;
delay_us(10);
//moso2=GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15); //读取输出口电平高低
read_status|=moso;
delay_us(10);
}
clk = 1;
cs = 1;
delay_us(10);
return read_status;
}
// check status register wip bit
void check_wip(void)
{
u8 temp,wip;
do{
temp=spi_rdsr(0x05);
wip = temp <<7;
}while(wip);
}
// page erase only used to 512K EEPROM spi PE擦除,0100 0010,以及地址
void spi_page_erase(u8 page_erase_com,u16 wr_addr)
{
u8 i,dig;
u16 j;
cs=0;
for(i=0;i<8;i++)
{
clk=0;
dig=page_erase_com&0x80;
if(dig)
{ mosi=1;}
else
{mosi=0;}
page_erase_com=page_erase_com<<1;
clk=1;
delay_us(1);
}
delay_us(1);
clk = 0;
for(j=0;j<16;j++)
{
clk=0;
dig=wr_addr&0x8000; //write address high 16 bit 0x0000
if(dig)
{ mosi=1;}
else
{mosi=0;}
wr_addr=wr_addr<<1;
clk=1;
delay_us(1);
}
delay_us(1);
mosi = 0;
clk = 0;
cs = 1;
check_wip(); //要有检测写入是否结束函数
}
//sector erase 扇区擦除 SE擦除1101 1000,以及地址
void spi_sector_erase(u8 sector_erase_com,u16 wr_addr)
{
u8 i,dig;
u16 j;
cs=0;
for(i=0;i<8;i++)
{
clk=0;
dig=sector_erase_com&0x80;
if(dig)
{ mosi=1;}
else
{mosi=0;}
sector_erase_com=sector_erase_com<<1;
clk=1;
delay_us(1);
}
delay_us(1);
clk = 0;
for(j=0;j<16;j++)
{
clk=0;
dig=wr_addr&0x8000;
if(dig)
{ mosi=1;}
else
{mosi=0;}
wr_addr=wr_addr<<1;
clk=1;
delay_us(1);
}
delay_us(1);
mosi = 0;
clk = 0;
cs = 1;
check_wip(); //要有检测写入是否结束函数
}
//chip erase 芯片擦除 CE擦除1100 0111
void spi_chip_erase(u8 chip_com)
{
u8 i;
u8 dig;
cs=0;
for(i=0;i<8;i++)
{
clk=0;
dig=chip_com&0x80;
if(dig)
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
//#include "led.h"
#include "delay.h"
//#include "key.h"
#include "sys.h"
//#include "lcd.h"
#include "usart.h"
#include "25LC512.h"
//#include "spi.h"
int main(void)
{
u8 pw_dat[8]={0xFF,0x00,0x01,0x09,0x10,0x01,0x00,0xDD},*pwr_dat1,*pwr_dat2;
u8 i=0;
u8 rxbuf[8]={0};
u8 rxbuf1[4]={0};
u8 rxbuf2[4]={0};
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
// RS485_Init(9600); //初始化RS485串口2
LC512_Init();
init();
//spi_wrsr(0x01,0x03);
printf("Data to Send:\r\n");
for(i=0;i<8;i++)
{
printf("%x\t", pw_dat[i]);
}
printf("\r\n");
spi_wren(0x06); //write enable 0x06
spi_page_write(write,0x0001,8,pw_dat);
// spi_wrsr(0x01,0x01); //write status register 0x01 no write protect 0x00
// spi_byte_write(write,0x0010,0x10); //write address1 0x00 address 0x00 and data 0x55
// spi_byte_write(write,0x0009,0x55);
// delay_ms(1000);
// spi_wren(0x06);
// spi_byte_write(write,0x000a,0x0a);
// delay_ms(1000);
// spi_wren(0x06);
// spi_byte_write(write,0x000b,0x0b);
// spi_wren(0x06);
// delay_ms(1000);
// *rs485buf=*pw_dat;
// spi_wrdi(wrdi); // write disable 0x04
// spi_page_read(0x01,0x01);
// P1 = spi_byte_read(read,0x0009);
// spi_page_erase(pe,0x0001);
// spi_sector_erase(se,addr);
// spi_chip_erase(ce);
// spi_deep_power_down_mode(dpd);
pwr_dat1=spi_page_read(read,4,0x0001);
for(i=0;i<4;i++)
{
rxbuf1[i]=*(pwr_dat1+i);
rxbuf[i]=rxbuf1[i];
}
pwr_dat2=spi_page_read(read,4,0x0005);
for(i=0;i<4;i++)
{
rxbuf2[i]=*(pwr_dat2+i);
rxbuf[i+4]=rxbuf2[i];
}
printf("Read Data:\r\n");
for(i=0;i<8;i++)
{
printf("%x\t",rxbuf[i]);
}
printf("\r\n");
// rs485buf[0]=spi_byte_read(read,0x0020);
// rs485buf[0]=spi_byte_read(read,0x0001);
// rs485buf[1]=spi_byte_read(read,0x0002);
// rs485buf[2]=spi_byte_read(read,0x0003);
delay_ms(1000);
}
复制代码
所有资料51hei提供下载:
SPI读取EEPROM.zip
(374.46 KB, 下载次数: 75)
2019-7-16 09:48 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
Modbus下载
时间:
2019-7-16 10:25
擦除可能有点问题,直接写就完事了
作者:
zanzouba
时间:
2019-12-24 11:10
下载下来才发现竟然是模拟SPI
作者:
muelfox
时间:
2020-4-13 15:51
楼主最好再来个硬件SPI
作者:
454267390
时间:
2020-5-18 10:36
刚好用到,Thanks♪(・ω・)ノ
作者:
zs.ag
时间:
2020-5-26 15:07
终于找到了
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1