找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4865|回复: 5
收起左侧

STM32F103使用SPI读取EEPROM源程序

[复制链接]
ID:584879 发表于 2019-7-16 09:49 | 显示全部楼层 |阅读模式
SPI读取EEPROM用的比较少,这个程序可以借鉴一下

单片机源程序如下:
  1. #include "stm32f10x.h"
  2. #include "25LC512.h"
  3. #include "delay.h"
  4. #include "led.h"
  5. //PB5-mosi;PB3-clk;PA15-cs;PB4-miso;//

  6. void LC512_Init(void)
  7. {
  8.         GPIO_InitTypeDef  GPIO_InitStructure;
  9.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA, ENABLE);
  10.         
  11.         /*PB3默认JTAG,需要先禁用再作为普通IO*/
  12.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  13.         GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);              
  14.         DBGMCU->CR  &= ~((uint32_t)1<<5);   
  15.         AFIO->MAPR = (AFIO->MAPR & ~((uint32_t)0x7 << 24)) | (2 << 24);     /*  PA15 PB3 PB4 */
  16.         
  17.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  18.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
  19.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
  20.   GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
  21.         
  22.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  23.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
  24.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
  25.   GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
  26.                
  27.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//PB4        
  28.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//输入
  29.   GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
  30.         
  31.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PA15
  32.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//复用推挽输出
  33.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
  34.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
  35.         
  36.         
  37. }

  38. //初始化芯片
  39. void init(void)                          // void main(void)第一个void表示函数没有返回值,第二个表示不带任何有实际意义的参数
  40. {
  41.         cs = 1;
  42. //        miso = 0;
  43.         mosi = 1;
  44.         clk = 1;
  45. }
  46. void delay(u8 t)        //延时
  47. {
  48.         u8 i,j;
  49.         for(i = t;i > 0;i --)
  50.                 for(j =0 ;j < 10;j ++)
  51.                 {;;}
  52. }
  53. //write commend enable or disable signal
  54. void spi_wren(u8 wren_com)               //write enable wren_com=0x06  设置写使能0000 0110
  55. {
  56.         u8 i;
  57.         u8 dig;
  58.         cs=0;
  59.         delay_us(10);
  60.         
  61.         for(i=0;i<8;i++)
  62.         {
  63.                 clk=0;
  64.                 delay_us(10);                                                                                                                                               
  65.                 dig=wren_com>>7;
  66.                 if(dig)
  67.                   { mosi=1;}
  68.       else
  69.                         {mosi=0;}
  70.                 wren_com=wren_com<<1;
  71.                 clk=1;
  72.     delay_us(10);
  73.         }
  74.         
  75.    delay_us(10);
  76.    //mosi = 0;                                //mosi=0,scl=0,when 8 bit data move over
  77.          clk = 1;
  78.          cs = 1;
  79.          delay_us(10);
  80.                
  81. }

  82.         
  83.         
  84. void spi_wrdi(u8 wrdi_com)       //write disable wr_com=0x04   设置写不使能0000 0100
  85. {
  86.         u8 i;
  87.         u8 dig;
  88.         cs=0;
  89.         delay_us(10);
  90.         
  91.         for(i=0;i<8;i++)
  92.         {
  93.                 clk=0;
  94.                 delay_us(10);
  95.                 dig=wrdi_com>>7;
  96.                 if(dig)
  97.                   { mosi=1;}
  98.       else
  99.                         {mosi=0;}
  100.                 wrdi_com=wrdi_com<<1;
  101.                 clk=1;
  102.     delay_us(10);
  103.                 }
  104.    delay_us(10);
  105.    //mosi = 0;                                //mosi=0,scl=0,when 8 bit data move over
  106.          clk = 1;
  107.          cs = 1;
  108.          delay_us(10);
  109.         }

  110.         //byte write           0000 0010
  111. void spi_byte_write(u8 wr_byte_com,u16 wr_addr,u8 wr_dat)         //write 1 btye data
  112. {
  113.   u8 i,dig;
  114.         u16 j;
  115.         cs=0;
  116.         //delay_us(10);
  117.         
  118.         for(i=0;i<8;i++)
  119.         {
  120.                 clk=0;
  121.                 //delay_us(10);
  122.                 dig=wr_byte_com>>7;     
  123.                 if(dig)
  124.                   { mosi=1;}
  125.       else
  126.                         {mosi=0;}
  127.                 wr_byte_com=wr_byte_com<<1;
  128.                 clk=1;
  129.     delay_us(1);
  130.                 }
  131.    delay_us(1);
  132.          clk = 1;
  133.    
  134.                
  135.         for(j=0;j<16;j++)
  136.         {
  137.                 clk=0;
  138.                 //delay_us(10);
  139.                 dig=wr_addr>>15;                 // output instruction code "0x02"
  140.                 if(dig)
  141.                   { mosi=1;}
  142.       else
  143.                         {mosi=0;}
  144.                 wr_addr=wr_addr<<1;
  145.                 clk=1;
  146.     delay_us(1);
  147.                 }
  148.    delay_us(1);
  149.          clk = 1;
  150.          
  151.                
  152.         for(i=0;i<8;i++)
  153.         {
  154.                 clk=0;
  155.                 //delay_us(10);
  156.                 dig=wr_dat>>7;     
  157.                 if(dig)
  158.                   { mosi=1;}
  159.       else
  160.                         {mosi=0;}
  161.                 wr_dat=wr_dat<<1;
  162.                 clk=1;
  163.     delay_us(1);
  164.                 }        

  165.          delay_us(1);
  166.   // mosi = 0;                                
  167.          clk = 1;
  168.          cs = 1;
  169. //         check_wip();                                                    //要有检测写入是否结束函数

  170. }


  171. /*
  172. function name:spi_page write
  173. //write 8 btye data

  174. */
  175. void spi_page_write(u8 wr_page_com,u16 wr_addr,u8 len,u8 *pwr_dat)         
  176. {
  177.   u8 i,dig,n;
  178.         u16 j;
  179.         cs=0;
  180.         //delay_us(10);
  181.         for(i=0;i<8;i++)
  182.         {
  183.                 clk=0;
  184. //delay_us(10);
  185.                 dig=wr_page_com&0x80;     
  186.                 if(dig)
  187.                   {mosi=1;}
  188.     else
  189.                         {mosi=0;}
  190.                 wr_page_com=wr_page_com<<1;
  191.                 clk=1;
  192.     delay_us(1);
  193.                 }
  194.    delay_us(1);
  195.          clk = 1;
  196.    
  197.         
  198.         for(j=0;j<16;j++)
  199.         {
  200.                 clk=0;
  201.         //        delay_us(10);
  202.                 dig=wr_addr>>15;                 // output instruction code "0x02"
  203.                 if(dig)
  204.                   { mosi=1;}
  205.       else
  206.                         {mosi=0;}
  207.                 wr_addr=wr_addr<<1;
  208.                 clk=1;
  209.     delay_us(1);
  210.                 }
  211.    delay_us(1);
  212.          clk = 1;

  213.                
  214.         for(n=0;n<len;n++)
  215.         {
  216.                 for(i=0;i<8;i++)
  217.         {
  218.                 clk=0;
  219.         //        delay_us(10);
  220.                 dig= pwr_dat[n]&0x80;     
  221.                 if(dig)
  222.                   { mosi=1;}
  223.      else
  224.                         {mosi=0;}
  225.                 pwr_dat[n]=pwr_dat[n]<<1;
  226.                 clk=1;
  227.     delay_us(1);
  228.         }        
  229.         delay_us(1);
  230.         clk=1;
  231.         
  232.         }

  233.          delay_us(1);
  234.    //mosi = 0;                                
  235.          clk = 1;
  236.          cs = 1;

  237.          check_wip();                                                   //要有检测写入是否结束函数
  238.         
  239. }
  240.         

  241. //read a byte data                          0000 0011
  242. u8 spi_byte_read(u8 read_com,u16 read_addr)
  243. {
  244.   u8 read_dat,i,dig;
  245.         u16 j;
  246.         cs=0;
  247.         //delay_us(10);
  248.         for(i=0;i<8;i++)
  249.         {
  250.                 clk=0;
  251.                 //delay_us(10);
  252.                 dig=read_com>>7;     
  253.                 if(dig)
  254.                   { mosi=1;}
  255.       else
  256.                         {mosi=0;}
  257.                 read_com=read_com<<1;
  258.                 clk=1;
  259.     delay_us(1);
  260.                 }
  261.    
  262.                 delay_us(1);
  263.           clk = 1;
  264.    
  265.         for(j=0;j<16;j++)
  266.         {
  267.                 clk=0;
  268.                 //delay_us(10);
  269.                 dig=read_addr>>15;                 // output instruction code "0x02"
  270.                 if(dig)
  271.                   { mosi=1;}
  272.       else
  273.                         {mosi=0;}
  274.                 read_addr=read_addr<<1;
  275.                 clk=1;
  276.     delay_us(1);
  277.                 }
  278.    delay_us(1);
  279.          clk = 1;
  280.          
  281.         
  282.         for(i=0;i<8;i++)
  283.   {
  284.                 clk=1;
  285.     //delay_us(10);
  286.                 read_dat = read_dat << 1;
  287.     clk=0;
  288.                 //delay_us(10);
  289.     //moso2=GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15);   //读取输出口电平高低
  290.                 read_dat|=moso;
  291.     delay_us(1);
  292.         }
  293.    
  294.            delay_us(1);               
  295.           clk = 1;
  296.           cs = 1;
  297.          
  298.                 return read_dat;               
  299.                                                       
  300. }



  301. // page read
  302. u8* spi_page_read(u8 read_com,u8 len,u16 wr_addr)
  303. {
  304.   
  305.         u8 rd_page_dat,i,dig,n,read_dat[128]={0},*read_out;
  306.         u16 j;
  307. //        miso=0;
  308.         cs=0;
  309. //        delay_us(10);
  310.         for(i=0;i<8;i++)
  311.         {
  312.                 clk=0;
  313.         //        delay_us(10);
  314.                 dig=read_com>>7;     
  315.                 if(dig)
  316.                   { mosi=1;}
  317.       else
  318.                         {mosi=0;}
  319.                 read_com=read_com<<1;
  320.                 clk=1;
  321.     delay_us(1);
  322.                 }
  323.     clk = 1;
  324.                 delay_us(1);
  325.           //mosi=0;

  326.         for(j=0;j<16;j++)
  327.         {
  328.                 clk=0;
  329.         //        delay_us(10);
  330.                 dig=wr_addr>>15;               
  331.                 if(dig)
  332.                   { mosi=1;}
  333.       else
  334.                         {mosi=0;}
  335.                 wr_addr=wr_addr<<1;
  336.                 clk=1;
  337.     delay_us(1);
  338.                 }
  339.    //mosi=0;
  340.          clk = 1;
  341.          delay_us(1);
  342.                
  343.     for(n = 0;n < len;n ++)
  344.         {
  345.                 rd_page_dat = read_dat[n];
  346.                 for(i=0;i<8;i++)
  347.   {
  348.                 clk=1;
  349.     delay_us(1);
  350.                 rd_page_dat = rd_page_dat<< 1;
  351.     clk=0;
  352.                 //delay_us(10);
  353.     //moso2=GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15);//读取输出口电平高低            
  354.                 rd_page_dat|=moso;
  355.     delay_us(1);
  356.         }   
  357.    read_dat[n]=rd_page_dat;
  358.      }
  359.                                  
  360.           clk = 1;
  361.           cs = 1;
  362.                 delay_us(1);
  363.         read_out=read_dat;
  364.         return read_out;
  365.         
  366. }


  367. //write status 写入状态                 设置status register状态寄存器写入0000 0001以及要写入的数据wrsr-dat
  368. void spi_wrsr(u8 wrsr_com,u8 wrsr_dat)
  369. {
  370.   u8 i;
  371.         u8 dig;
  372.         cs=0;
  373.         delay_us(10);
  374.         for(i=0;i<8;i++)
  375.         {
  376.                 clk=0;
  377.                 delay_us(10);
  378.                 dig=wrsr_com>>7;     //write status instruction is 0x01
  379.                 if(dig)
  380.                   { mosi=1;}
  381.       else
  382.                         {mosi=0;}
  383.                 wrsr_com=wrsr_com<<1;
  384.                 clk=1;
  385.     delay_us(10);
  386.                 }
  387.   
  388.         clk = 1;
  389.         delay_us(10);        
  390.         for(i=0;i<8;i++)
  391.         {
  392.                 clk=0;
  393.                 delay_us(10);
  394.                 dig=wrsr_dat>>7;     
  395.                 if(dig)
  396.                   { mosi=1;}
  397.       else
  398.                         {mosi=0;}
  399.                 wrsr_dat=wrsr_dat<<1;
  400.                 clk=1;
  401.     delay_us(10);
  402.                 }        
  403.          
  404.    //mosi = 0;                                
  405.          clk = 1;
  406.          cs = 1;
  407.          delay_us(10);
  408.         }

  409.         
  410.         //read status                 0000 0101
  411. u8 spi_rdsr(u8 wdsr_com)
  412. {
  413.         u8 dig;
  414.         u8 read_status,i;
  415.         
  416.   cs=0;
  417.         delay_us(10);
  418.         for(i=0;i<8;i++)
  419.         {
  420.                 clk=0;
  421.                 delay_us(10);
  422.                 dig=wdsr_com>>7;               // first write instruction to mosi  0x05
  423.                 if(dig)
  424.                   { mosi=1;}
  425.       else
  426.                         {mosi=0;}
  427.                 wdsr_com=wdsr_com<<1;
  428.                 clk=1;
  429.     delay_us(10);
  430.                 }
  431.     clk = 1;
  432.           delay_us(10);               

  433.   for(i=0;i<8;i++)
  434.   {
  435.                 clk=1;
  436.     delay_us(10);
  437.                 read_status = read_status << 1;
  438.     clk=0;
  439.                 delay_us(10);
  440.     //moso2=GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15);   //读取输出口电平高低
  441.                 read_status|=moso;
  442.     delay_us(10);
  443.         }
  444.                            
  445.           clk = 1;
  446.           cs = 1;
  447.           delay_us(10);
  448.                 return read_status;               
  449. }

  450. // check status register wip bit
  451. void check_wip(void)
  452. {
  453.         u8 temp,wip;
  454.         do{        
  455.         temp=spi_rdsr(0x05);        
  456.         wip = temp <<7;
  457.         }while(wip);
  458. }

  459.         
  460. // page erase        only used to 512K EEPROM spi                PE擦除,0100 0010,以及地址
  461. void spi_page_erase(u8 page_erase_com,u16 wr_addr)
  462. {
  463.   u8 i,dig;
  464.         u16 j;
  465.         cs=0;
  466.         
  467.         for(i=0;i<8;i++)
  468.         {
  469.                 clk=0;
  470.                 dig=page_erase_com&0x80;     
  471.                 if(dig)
  472.                   { mosi=1;}
  473.       else
  474.                         {mosi=0;}
  475.                 page_erase_com=page_erase_com<<1;
  476.                 clk=1;
  477.     delay_us(1);
  478.                 }
  479.    delay_us(1);
  480.          clk = 0;
  481.    
  482.                 for(j=0;j<16;j++)
  483.         {
  484.                 clk=0;
  485.                 dig=wr_addr&0x8000;             //write address high 16 bit          0x0000      
  486.                 if(dig)
  487.                   { mosi=1;}
  488.       else
  489.                         {mosi=0;}
  490.                 wr_addr=wr_addr<<1;
  491.                 clk=1;
  492.     delay_us(1);
  493.                 }
  494.    delay_us(1);
  495.    mosi = 0;                                
  496.          clk = 0;
  497.          cs = 1;
  498.          check_wip();                                                    //要有检测写入是否结束函数

  499. }

  500. //sector erase 扇区擦除                                       SE擦除1101 1000,以及地址
  501. void spi_sector_erase(u8 sector_erase_com,u16 wr_addr)      
  502. {
  503.   u8 i,dig;
  504.         u16 j;
  505.         cs=0;
  506.         
  507.         for(i=0;i<8;i++)
  508.         {
  509.                 clk=0;
  510.                 dig=sector_erase_com&0x80;     
  511.                 if(dig)
  512.                   { mosi=1;}
  513.       else
  514.                         {mosi=0;}
  515.                 sector_erase_com=sector_erase_com<<1;
  516.                 clk=1;
  517.     delay_us(1);
  518.                 }
  519.    delay_us(1);
  520.          clk = 0;
  521.    
  522.                 for(j=0;j<16;j++)
  523.         {
  524.                 clk=0;
  525.                 dig=wr_addr&0x8000;                  
  526.                 if(dig)
  527.                   { mosi=1;}
  528.       else
  529.                         {mosi=0;}
  530.                 wr_addr=wr_addr<<1;
  531.                 clk=1;
  532.     delay_us(1);
  533.                 }
  534.    delay_us(1);
  535.    mosi = 0;                                
  536.          clk = 0;
  537.          cs = 1;
  538.          check_wip();                                                    //要有检测写入是否结束函数

  539. }

  540. //chip erase 芯片擦除                          CE擦除1100 0111
  541. void spi_chip_erase(u8 chip_com)
  542. {
  543.         u8 i;
  544.         u8 dig;
  545.         cs=0;
  546.         
  547.         for(i=0;i<8;i++)
  548.         {
  549.                 clk=0;
  550.                 dig=chip_com&0x80;
  551.                 if(dig)
  552. ……………………

  553. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

  1. //#include "led.h"
  2. #include "delay.h"
  3. //#include "key.h"
  4. #include "sys.h"
  5. //#include "lcd.h"
  6. #include "usart.h"         
  7. #include "25LC512.h"                 
  8. //#include "spi.h"

  9. int main(void)
  10. {
  11.   u8        pw_dat[8]={0xFF,0x00,0x01,0x09,0x10,0x01,0x00,0xDD},*pwr_dat1,*pwr_dat2;
  12.         u8 i=0;
  13.         u8 rxbuf[8]={0};
  14.         u8 rxbuf1[4]={0};
  15.         u8 rxbuf2[4]={0};

  16.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
  17.         delay_init();   //初始化延时函数
  18.         uart_init(115200);        //初始化串口波特率为115200  
  19. //        RS485_Init(9600);                //初始化RS485串口2
  20.         LC512_Init();
  21.         init();
  22.         //spi_wrsr(0x01,0x03);
  23.         
  24.         printf("Data to Send:\r\n");
  25.         for(i=0;i<8;i++)
  26.         {        
  27.                 printf("%x\t", pw_dat[i]);
  28.         }
  29.         printf("\r\n");

  30.         spi_wren(0x06);                     //write enable   0x06        
  31.         spi_page_write(write,0x0001,8,pw_dat);
  32.         //  spi_wrsr(0x01,0x01);        //write status register 0x01  no write protect         0x00        
  33. //        spi_byte_write(write,0x0010,0x10);     //write address1 0x00 address 0x00 and data  0x55        
  34. //        spi_byte_write(write,0x0009,0x55);
  35. //        delay_ms(1000);
  36. //        spi_wren(0x06);
  37. //        spi_byte_write(write,0x000a,0x0a);
  38. //        delay_ms(1000);
  39. //        spi_wren(0x06);
  40. //        spi_byte_write(write,0x000b,0x0b);
  41. //        spi_wren(0x06);
  42. //        delay_ms(1000);
  43.                
  44. //        *rs485buf=*pw_dat;
  45. //        spi_wrdi(wrdi);                     // write disable  0x04
  46. //        spi_page_read(0x01,0x01);        
  47. //        P1 = spi_byte_read(read,0x0009);

  48. //        spi_page_erase(pe,0x0001);
  49. //        spi_sector_erase(se,addr);
  50. //        spi_chip_erase(ce);
  51. //        spi_deep_power_down_mode(dpd);
  52.     pwr_dat1=spi_page_read(read,4,0x0001);         
  53.                 for(i=0;i<4;i++)
  54.                 {
  55.                         rxbuf1[i]=*(pwr_dat1+i);
  56.                         rxbuf[i]=rxbuf1[i];
  57.                 }
  58.                
  59.                 pwr_dat2=spi_page_read(read,4,0x0005);         
  60.                 for(i=0;i<4;i++)
  61.                 {
  62.                         rxbuf2[i]=*(pwr_dat2+i);
  63.                         rxbuf[i+4]=rxbuf2[i];
  64.                 }

  65.                 printf("Read Data:\r\n");
  66.                 for(i=0;i<8;i++)
  67.                 {
  68.                         printf("%x\t",rxbuf[i]);
  69.                 }
  70.                 printf("\r\n");
  71. //                                rs485buf[0]=spi_byte_read(read,0x0020);
  72. //                    rs485buf[0]=spi_byte_read(read,0x0001);
  73. //                    rs485buf[1]=spi_byte_read(read,0x0002);
  74. //                                 rs485buf[2]=spi_byte_read(read,0x0003);                                                                           
  75.                 delay_ms(1000);        
  76.         }

复制代码

所有资料51hei提供下载:
SPI读取EEPROM.zip (374.46 KB, 下载次数: 75)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:584879 发表于 2019-7-16 10:25 | 显示全部楼层
擦除可能有点问题,直接写就完事了
回复

使用道具 举报

ID:636998 发表于 2019-12-24 11:10 | 显示全部楼层
下载下来才发现竟然是模拟SPI
回复

使用道具 举报

ID:384581 发表于 2020-4-13 15:51 | 显示全部楼层
楼主最好再来个硬件SPI
回复

使用道具 举报

ID:603888 发表于 2020-5-18 10:36 | 显示全部楼层
刚好用到,Thanks♪(・ω・)ノ
回复

使用道具 举报

ID:429752 发表于 2020-5-26 15:07 | 显示全部楼层
终于找到了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表