×
单片机 > 单片机程序设计 > 详情

STM32驱动FM24CL16

发布时间:2020-09-02 发布时间:
|

根据小苗开发板例程,修改得好用的读写FM24CL16的2K bytes代码,分享给大家。

小苗开发板的程序有点问题,I2C_Read()里最后产生stop条件时间不对;另外FM24CL16是11位地址的,在I2C_Write()里也应体现出来。

先贴代码,以后再解析。


  1. /************************************************************** 

  2.  ** 函数名 :drv_i2c1_init 

  3.  ** 功能   : 初始化I2C1接口。包括GPIO配置和I2C1配置 

  4.     //PB6--I2C1_SCL, PB7--I2C1_SDA. 

  5.  ** 输入   :无 

  6.  ** 输出   :无 

  7.  ** 返回   :无 

  8.  ** 注意   :无 

  9. ***************************************************************/  

  10. void drv_i2c1_init(void)  

  11. {  

  12.     GPIO_InitTypeDef  GPIO_InitStructure; //GPIO  

  13.     I2C_InitTypeDef  I2C_InitStructure;   //IIC  

  14.   

  15.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); //使能I2C时钟  

  16.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIO时钟  

  17.   

  18.     GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;//IIC引脚PB6--SCL, PB7--SDA.  

  19.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;        //复用开漏输出  

  20.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //50MHZ  

  21.     GPIO_Init(GPIOB, &GPIO_InitStructure);  

  22.   

  23.     I2C_DeInit(I2C1); //将I2C1寄存器重置为缺省值  

  24.     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;        //设置I2C1为I2C模式  

  25.     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//I2C快速Tlow/Thigh = 2  

  26.     I2C_InitStructure.I2C_OwnAddress1 = 0x01;         //设置第一个设备自身地址·  

  27.     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;       //使能应答ACK  

  28.     I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //定义应答地址7bit  

  29.     I2C_InitStructure.I2C_ClockSpeed = 200000;        //设置时钟频率200Khz  

  30.   

  31.     I2C_Cmd(I2C1, ENABLE); //使能IIC1  

  32.     I2C_Init(I2C1, &I2C_InitStructure);//初始化IIC1  

  33.     I2C_AcknowledgeConfig(I2C1, ENABLE);//使能应答功能  

  34. }  

  35. /************************************************************** 

  36.  ** 函数名 :I2C_Write_Byte 

  37.  ** 功能   :字节写入操作 

  38.  ** 输入   :addr:要写入的FRAM的地址,data:要写入的内容 

  39.  ** 输出   :无 

  40.  ** 返回   :无 

  41.  ** 注意   :无 

  42. ***************************************************************/  

  43. u8 I2C_Write_Byte(u16 addr,u8 data)  

  44. {  

  45.     u16 i = 0;  

  46.     u8 flag = 0;  

  47.   

  48.     addr = addr & 0x07FF;  

  49.       

  50.     I2C_GenerateSTART(I2C1, ENABLE);//产生IIC1传输START条件  

  51.     i = 0;  

  52.     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) //检查EV5   

  53.     {  

  54.         i++;      

  55.         if(I2C_MAX_DEAD_TIME <= i)  

  56.         {  

  57.             flag = 1;    

  58.             break;  

  59.         }  

  60.     }   

  61.       

  62.     I2C_Send7bitAddress(I2C1, FRAM_ADDR|(((addr>>8)&0x07)<<1), I2C_Direction_Transmitter);//发送器件地址  

  63.   

  64.     i = 0;  

  65.     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))//检查VE6    

  66.     {  

  67.         i++;      

  68.         if(I2C_MAX_DEAD_TIME <= i)  

  69.         {  

  70.             flag = 2;  

  71.             break;  

  72.         }  

  73.     }  

  74.       

  75.     I2C_SendData(I2C1, (u8)addr);//发送写地址  

  76.   

  77.     i = 0;  

  78.     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))//检查VE8  

  79.     {  

  80.         i++;      

  81.         if(I2C_MAX_DEAD_TIME <= i)  

  82.         {  

  83.             flag = 3;  

  84.             break;  

  85.         }  

  86.     }  

  87.       

  88.     I2C_SendData(I2C1, (u8)data);//写入字节  

  89.   

  90.     i = 0;  

  91.     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))//检查VE8    

  92.     {  

  93.         i++;      

  94.         if(I2C_MAX_DEAD_TIME <= i)  

  95.         {  

  96.             flag = 4;  

  97.             break;  

  98.         }  

  99.     }     

  100.    

  101.     I2C_GenerateSTOP(I2C1, ENABLE); //产生IIC传输STOP条件   

  102.     I2C_Standby();  

  103.   

  104.     return flag;  

  105. }  

  106.   

  107. /************************************************************** 

  108.  ** 函数名 :I2C_Write_Page 

  109.  ** 功能   :页写入操作 

  110.  ** 输入   :Waddr:要写入的FRAM的地址,pBuffer:存放要写入的内容,Num:写入的字节数。 

  111.     这里不做页检验,认为waddr和waddr+num都一页内的地址 

  112.  ** 输出   :无 

  113.  ** 返回   :无 

  114.  ** 注意   :一页8个字节,每次写入操作不得大于8 

  115. ***************************************************************/  

  116. static u8 I2C_Write_Page(u16 Waddr,u8* pBuffer, u8 Num)  

  117. {  

  118.     u16 i;  

  119.     u8 flag = 0;  

  120.   

  121.     Waddr = Waddr & 0x07FF;  

  122.   

  123.     i = 0;  

  124.     while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) //总线忙  

  125.     {  

  126.         i++;      

  127.         if(I2C_MAX_DEAD_TIME <= i)  

  128.         {  

  129.             flag = 1;  

  130.             break;  

  131.         }  

  132.     }  

  133.       

  134.     I2C_GenerateSTART(I2C1, ENABLE);               //产生IIC1传输START条件  

  135.   

  136.     i = 0;  

  137.     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))//检查EV5   

  138.     {  

  139.         i++;      

  140.         if(I2C_MAX_DEAD_TIME <= i)  

  141.         {  

  142.             flag = 2;  

  143.             break;  

  144.         }  

  145.     }  

  146.       

  147.     I2C_Send7bitAddress(I2C1, FRAM_ADDR|(((Waddr>>8)&0x07)<<1), I2C_Direction_Transmitter);//发送器件地址  

  148.   

  149.     i = 0;  

  150.     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))//检查VE6  

  151.     {  

  152.         i++;      

  153.         if(I2C_MAX_DEAD_TIME <= i)  

  154.         {  

  155.             flag = 3;  

  156.             break;  

  157.         }  

  158.     }  

  159.       

  160.     I2C_SendData(I2C1, (u8)Waddr);//发送写地址  

  161.   

  162.     i = 0;  

  163.     while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))//检查VE8  

  164.     {  

  165.         i++;      

  166.         if(I2C_MAX_DEAD_TIME <= i)  

  167.         {  

  168.             flag = 4;  

  169.             break;  

  170.         }  

  171.     }  

  172.       

  173.     while(Num--)    

  174.     {  

  175.         I2C_SendData(I2C1, *pBuffer);//写入字节   

  176.         pBuffer++;  

  177.           

  178.         i = 0;  

  179.         while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))//检查VE8  

  180.         {  

  181.             i++;      

  182.             if(I2C_MAX_DEAD_TIME <= i)  

  183.             {  

  184.                 flag = 5;  

  185.                 break;  

  186.             }  

  187.         }         

  188.     }  

  189.     I2C_GenerateSTOP(I2C1, ENABLE);//产生IIC传输STOP条件   

  190.       

  191.     return flag;  

  192. }  

  193.   

  194. //For FM24CL16, 16384 bits = 2k bytes.  

  195. /************************************************************** 

  196.  ** 函数名 :I2C_Write 

  197.  ** 功能   :写入数据 

  198.  ** 输入   :Waddr:要写入的FRAM的地址,pBuffer:存放要写入的内容,Num:写入的字节数。 

  199.     对FM24CL16, Waddr是11位地址。 

  200.  ** 输出   :无 

  201.  ** 返回   :无 

  202.  ** 注意   : 

  203. ***************************************************************/  

  204. void I2C_Write(u16 Waddr,u8* pBuffer,  u16 Num)  

  205. {  

  206.     u8 ADDR;  

  207.   

  208.     Waddr = Waddr & 0x07FF;  

  209.       

  210.     ADDR=Waddr % I2C_PAGESIZE;  

  211.     ADDR=I2C_PAGESIZE-ADDR;   //差ADDR个字节,满1页;  

  212.   

  213.     if (Num <= ADDR)     //写页不对齐部分,且所有 数据在本页内  

  214.     {  

  215.         I2C_Write_Page(Waddr,pBuffer,Num);//不满一页的,写完直接跳出  

  216.         Num=0;  

  217.         I2C_Standby();    

  218.     }  

  219.     else  

  220.     {  

  221.         if(ADDR) //写页不对齐部分  

  222.         {  

  223.             I2C_Write_Page(Waddr,pBuffer,ADDR);  

  224.             Num-=ADDR;  //减去不对齐的字节  

  225.             Waddr+=ADDR;//写地址后移ADDR  

  226.             pBuffer+=ADDR;//指针后移ADDR  

  227.             I2C_Standby();  

  228.         }  

  229.           

  230.         while(Num)//写页对齐部分  

  231.         {  

  232.             if(Num>=I2C_PAGESIZE)//如果要写入的数据大于等于1页  

  233.             {  

  234.                 I2C_Write_Page(Waddr,pBuffer,I2C_PAGESIZE); //写一页  

  235.                 Num-=I2C_PAGESIZE;    //减去一页  

  236.                 Waddr+=I2C_PAGESIZE;  //写地址向后移一页  

  237.                 pBuffer+=I2C_PAGESIZE;//指针后移一页  

  238.                 I2C_Standby();  

  239.             }  

  240.             else  

  241.             {  

  242.                 I2C_Write_Page(Waddr,pBuffer,Num);//不满一页的,写完直接跳出  

  243.                 Num=0;  

  244.                 I2C_Standby();  

  245.             }  

  246.         }  

  247.     }  

  248. }  

  249.   

  250. /************************************************************** 

  251.  ** 函数名 :I2C_Read 

  252.  ** 功能   :从FRAM中读取1个或多个数据 

  253.  ** 输入   :Raddr:要读取的FRAM的地址,pBuffer存放从FRAM中读取的内容,Num:读取的字节数。 

  254.     //If the internal address reaches 7FFh it will wrap around to 000h on the next read cycle. 

  255.     上面说明read不用考虑页边界和256边界. 

  256.  ** 输出   :无 

  257.  ** 返回   :无 

  258.  ** 注意   :无 

  259. ***************************************************************/  

  260. u8 I2C_Read(u16 Raddr ,u8* pBuffer,u16 Num)  

  261. {  

  262.     u16 i;  

  263.     u8 flag = 0;  

  264.       

  265.     if(Num==0)  

  266.         return 0xFF;  

  267.   

  268.     Raddr = Raddr & 0x07FF;  

  269.   

  270.     i = 0;  

  271.     while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) //检测总线忙标志位      

  272.     {  

  273.         i++;      

  274.         if(I2C_MAX_DEAD_TIME <= i)  

  275.         {  

  276.             flag = 1;  

  277.             break;  

  278.         }  

  279.     }  

  280.       

  281.     I2C_AcknowledgeConfig(I2C1, ENABLE);//允许应答  

  282.     I2C_GenerateSTART(I2C1, ENABLE);//产生IIC1传输START条件  

  283.   

  284.     i = 0;  

  285.     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))//检查EV5  

  286.     {  

  287.         i++;      

  288.         if(I2C_MAX_DEAD_TIME <= i)  

  289.         {  

  290.             flag = 2;  

  291.             break;  

  292.         }  

  293.     }  

  294.       

  295.     I2C_Send7bitAddress(I2C1,  FRAM_ADDR|(((Raddr>>8)&0x07)<<1), I2C_Direction_Transmitter);//发送器件地址  

  296.   

  297.     i = 0;  

  298.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))//检查VE6  

  299.     {  

  300.         i++;      

  301.         if(I2C_MAX_DEAD_TIME <= i)  

  302.         {  

  303.             flag = 3;  

  304.             break;  

  305.         }  

  306.     }  

  307.       

  308.     I2C_SendData(I2C1, (u8)Raddr);//发送伪写地址  

  309.   

  310.     i = 0;  

  311.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))//检查VE8  

  312.     {  

  313.         i++;      

  314.         if(I2C_MAX_DEAD_TIME <= i)  

  315.         {  

  316.             flag = 4;  

  317.             break;  

  318.         }  

  319.     }     

  320.   

  321.     I2C_GenerateSTART(I2C1, ENABLE);//产生IIC1传输START条件  

  322.     i = 0;  

  323.     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))//检查EV5  

  324.     {  

  325.         i++;      

  326.         if(I2C_MAX_DEAD_TIME <= i)  

  327.         {  

  328.             flag = 5;  

  329.             break;  

  330.         }  

  331.     }  

  332.       

  333.     I2C_Send7bitAddress(I2C1, FRAM_ADDR|(((Raddr>>8)&0x07)<<1), I2C_Direction_Receiver); //接收地址  

  334.   

  335.     i = 0;  

  336.     while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))//检查VE6  

  337.     {  

  338.         i++;      

  339.         if(I2C_MAX_DEAD_TIME <= i)  

  340.         {  

  341.             flag = 6;  

  342.             break;  

  343.         }  

  344.     }  

  345.       

  346.     while (Num)  

  347.     {  

  348.         if(Num==1)  

  349.         {  

  350.             I2C_AcknowledgeConfig(I2C1, DISABLE);   //最后一位后要关闭应答的  

  351.             //I2C_GenerateSTOP(I2C1, ENABLE);           //发送停止位     //It's a bug.  

  352.         }  

  353.   

  354.         i = 0;  

  355.         while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) //检测VE7        //always dead here.  

  356.         {  

  357.             i++;      

  358.             if(I2C_MAX_DEAD_TIME <= i)  

  359.             {  

  360.                 flag = 7;  

  361.                 break;  

  362.             }  

  363.         }  

  364.           

  365.         *pBuffer = I2C_ReceiveData(I2C1);  

  366.         pBuffer++;  

  367.         Num--;  

  368.     }  

  369.   

  370.     I2C_GenerateSTOP(I2C1, ENABLE);         //发送停止位     //It's a bug.     

  371.     I2C_AcknowledgeConfig(I2C1, ENABLE);//再次允许应答模式  

  372.   

  373.     return flag;  

  374. }  

  375.   

  376. /* 

  377. //FM24CL16不需要忙等待,EEPROM才需要 

  378. Unlike other nonvolatile memory technologies, there is no write delay with FRAM.  

  379. The entire memory cycle occurs in less time than a single bus clock. 

  380. Therefore, any operation including read or write can occur immediately following a write.  

  381. Acknowledge polling, a technique used with EEPROMs to determine if a write is complete is unnecessary and 

  382. will always return a 'ready' condition. 

  383. An actual memory array write occurs after the 8th data bit is transferred. 

  384. */  

  385. /************************************************************** 

  386.  ** 函数名 :I2C_Standby 

  387.  ** 功能   :忙等待 

  388.  ** 输入   :无 

  389.  ** 输出   :无 

  390.  ** 返回   :无 

  391.  ** 注意   :无 

  392. ***************************************************************/  

  393. u8 I2C_Standby(void)                                                     

  394. {  

  395. #if 0  

  396.     u16 i;  

  397.     u8 flag = 0;  

  398.       

  399.     i = 0;  

  400.     do  

  401.     {  

  402.         I2C_GenerateSTART(I2C1, ENABLE);//产生IIC1传输START条件  

  403.         I2C_Send7bitAddress(I2C1, FRAM_ADDR, I2C_Direction_Transmitter);//向FRAM发送地址  

  404.             i++;      

  405.             if(I2C_MAX_DEAD_TIME <= i)  

  406.             {  

  407.                 flag = 7;  

  408.                 break;  

  409.             }         

  410.     }while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));//检测SR1第1位,查看地址是否发送完成  

  411.       

  412.     I2C_ClearFlag(I2C1, I2C_FLAG_AF); //清除应答错误标志位     

  413.     I2C_GenerateSTOP(I2C1, ENABLE);   //产生IIC传输STOP条件  

  414.       

  415.     return flag;  

  416. #else  

  417.   return 0x00;  

  418. #endif  

  419. }  



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于arm的指纹识别门禁系统是如何设计的