龙空技术网

「STC8A8K64S4A12开发板」—片外存储器FRAM讲解

电子友人章 388

前言:

目前各位老铁们对“delayc文件主要包含哪些函数并简要说明各函数的作用”可能比较关怀,各位老铁们都需要学习一些“delayc文件主要包含哪些函数并简要说明各函数的作用”的相关内容。那么小编同时在网上网罗了一些对于“delayc文件主要包含哪些函数并简要说明各函数的作用””的相关资讯,希望咱们能喜欢,大家快快来学习一下吧!

文章目录前言一、硬件设计1.FRAM铁电存储器介绍2.SPI总线原理2.1.接口信号定义2.2.SPI的4种工作模式3.STC8A8K64S4A12系列单片机SPI介绍二、软件设计1.SPI相关寄存器汇集2.寄存器解析2.1.SPI控制寄存器SPCTL2.2.SPI状态寄存器SPSTAT2.3.中断允许寄存器IE22.4.中断优先级控制寄存器3.SPI配置步骤4.外接FRAM存储器读写单字节实验(模拟SPI)4.1.工程需要用到的c文件4.2.头文件引用和路径设置4.3.编写代码4.4.硬件连接5.外接FRAM存储器读写多字节实验(模拟SPI)5.1.编写代码5.2.硬件连接6.外接FRAM存储器读写单字节实验(硬件SPI)6.1.工程需要用到的c文件6.2.头文件引用和路径设置6.3.编写代码6.4.硬件连接7.外接FRAM存储器读写多字节实验(硬件SPI)7.1.编写代码7.2.硬件连接总结前言

今天介绍下STC8A8K64S4A12系列单片机FRAM铁电存储器原理和SPI总线的原理及工作模式,掌握STC8A8K64S4A12系列单片机SPI外设相关的寄存器配置及程序设计。

一、硬件设计1.FRAM铁电存储器介绍

FRAM(全称是Ferroelectric Random Access Memory)铁电存储器,该存储器能兼容RAM的一切功能,并且和ROM技术一样,是一种非易失性的存储器。可以说铁电存储器在这两类存储类型间搭起了一座跨越沟壑的桥梁——一种非易失性的RAM。

铁电存储器的工作原理是:当在铁电晶体材料上加入电场,晶体中的中心原子会沿着电场方向运动,达到稳定状态。晶体中的每个自由浮动的中心原子只有2个稳定状态,一个记为逻辑中的0,另一个记为1。中心原子能在常温、没有电场的情况下,停留在此状态达100年以上。铁电存储器不需要定时刷新,能在断电情况下保存数据。由于整个物理过程中没有任何原子碰撞,铁电存储器有高速读写、超低功耗和无限次写入等优点。

说到FRAM铁电存储器,就必须要介绍下美国Ramtron公司,该公司成立于1984年,是一家研究和开发铁电技术用于半导体存储器的公司。2012年9月,Ramtron公司被美国著名半导体公司赛普拉斯(Cypress)并购。2020年4月,infineon英飞凌完成了总价值90亿欧元(合人民币693亿元)对Cypress赛普拉斯半导体公司的收购。

Ramtron公司的FRAM主要包括两大类:串行FRAM和并行FRAM。其中串行FRAM又分I2C总线方式的FM24xx系列和SPI总线方式的FM25xx系列。艾克姆科技FRAM选择的存储器芯片是FM25CL64B芯片(SPI总线方式)。

图1:外部FRAM存储器实物图

☆注:Ramtron公司的商业FRAM产品全部由美国和日本的战略代工厂所制造。

2.SPI总线原理

SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速、全双工、同步的通信总线。SPI是Motorola公司推出的一种同步串行接口技术,SPI由一个主设备和一个或多个从设备组成,在一次数据传输过程中,接口上只能有一个主机和一个从机通信。

SPI总线的优点是操作简单、数据传输速率较高、全双工,缺点是只支持单个主机、没有指定的流控制、没有应答机制确认是否接收到数据。

2.1.接口信号定义

SPI总线接口包括以下四种信号:

MOSI(Master Output,Slave Input):主器件数据输出,从器件数据输入。MISO(Master Input, Slave Output):主器件数据输入,从器件数据输出。SCK(Serial Clock):有时也称为SCLK,时钟信号,由主器件产生。CS(Chip select):有时也称为SS,从器件使能信号,由主器件控制,实际使用时,经常用GPIO来代替。

SPI总线支持连接多个从机,如下图所示,SPI主机通过连接到从机的片选信号使能/禁止从机,并且同时只能使能一个从机,因此总线里面有多少个从机,就需要多少个片选信号。当SPI主机需要和总线中某个从机进行通信时,主机会拉低对应的CS信号使能该从机,之后发起通信,通信完成后,拉高CS信号,解除总线的占用。

图2:SPI总线结构

对于SPI总线,我们还需要深刻理解下面几个知识点。

■ 硬件片选和软件片选的区别

所谓硬件片选指的是SPI本身具有片选信号,当我们通过SPI发送数据时,SPI外设自动拉低CS信号使能从机,发送完成后自动拉高CS信号释放从机,这个过程是不需要软件操作的。而软件片选则是需要使用GPIO作为片选信号,SPI在发送数据之前,需要先通过软件设置作为片选信号的GPIO输出低电平,发送完成之后再设置该GPIO输出高电平。

■ SPI总线是回环结构

SPI是一个环形总线结构,如下图所示,主设备和从设备构成一个环形。在时钟SCK的作用下,主设备发送一个位到从设备,因为是环形结构,所以从设备必定会同时传送一个位到主设备。同样,主设备向从设备发送一个字节,从设备也必定会同时传送一个字节到主设备。理解了环形结构,就很容易理解下面几点:

SPI是全双工,同步的通信总线。主设备向从设备发送数据时,无论我们需不需要从设备返回数据,从设备都会返回数据。主设备从从设备读取一个字节数据时,为什么需要写一个字节数据到从设备:因为是环形结构,不写数据过去,对方的数据就不会被移位过来。

图3:SPI数据传输示意图

■ SPI主机和从机之间连接时信号不需要交叉

SPI主机和从机连接时,MOSI和MISO信号是不需要交叉连接的,因为MOSI本身就表示了主机输出、从机输入,MISO表示主机输入、从机输出,因此不能交叉连接。

图4:MOSI和MISO不能交叉连接

2.2.SPI的4种工作模式

SPI总线共有4种工作模式:模式0~模式3,这4种工作模式是由时钟相位和时钟极性确定的。

1.时钟极性CPOL(Clock polarity):SPI总线空闲时,时钟信号SCLK的电平称为时钟极性,有以下两种模式:

CPOL=0:SPI总线空闲时,时钟信号为低电平。CPOL=1:SPI总线空闲时,时钟信号为高电平。

2.时钟相位CPHA(Clock phase):SPI在时钟信号SCLK第几个边沿开始采样数据,有以下两种模式:

CPHA=0:在第1个时钟边沿进行数据采样。CPHA=1:在第2个时钟边沿进行数据采样。

时钟极性CPOL时钟相位CPHA各有2种模式,他们两两组合就形成了SPI的4种工作模式,如下表所示。

表1:SPI总线的4种工作模式

序号

SPI工作模式

描述

备注

1

模式0

CPOL=0,CPHA=0

重要

2

模式1

CPOL=0,CPHA=1

3

模式2

CPOL=1,CPHA=0

4

模式3

CPOL=1,CPHA=1

重要

SPI的4种模式中,最常用的是模式0和模式3。正是由于SPI有4种工作模式,因此当我们使用SPI总线时,需要去查询SPI总线中主机设备(如单片机)和从机设备(如SPI 存储器)的数据手册,确定他们支持什么模式,从而选择适合的工作模式。

SPI的4种模式的时序图如下。

■ 时钟相位CPHA=0时的时序

图5:CPHA=0时SPI时序

■ 时钟相位CPHA=1时的时序

图6:CPHA=0时SPI时序

3.STC8A8K64S4A12系列单片机SPI介绍

STC8A8K64S4A12系列单片机片内有1个高速串行通信接口SPI接口(以下简称SPI),该接口支持两种操作模式:主模式和从模式。这样,STC8A8K64S4A12系列单片机SPI通信方式可分为3种:单主单从(一个主机设备连接一个从机设备)、互为主从(两个设备连接,设备可互为主机和从机)、单主多从(一个主机设备连接多个从机设备)。

图7:SPI通信方式分类

STC8A8K64S4A12系列单片机每一组SPI都有4个IO引脚供选择使用,如下表所示。

表2:单片机SPI外设引脚分配

☆注:独立GPIO表示开发板没有其他的电路使用这个GPIO,非独立GPIO说明开发板有其他电路用到了该GPIO。须知同一时刻只能使能一组IO口作为SPI使用。

STC8A8K64S4A12系列单片机SPI使用哪一组IO口由P_SW1外围设备切换控制寄存器的B2、B3位决定,如下图所示。

图8:外围设备切换控制寄存器P_SW1

☆注:一般P_SW1寄存器B2、B3位默认是0,即如果没有对P_SW1寄存器进行操作,则默认选择的SPI是P1.2、P1.3、P1.4、P1.5这一组。

二、软件设计1.SPI相关寄存器汇集

STC8A8K64S4A12系列单片机使用SPI外设时会用到6个寄存器,如下表所示:

表3:STC8A8K64S4A12系列SPI使用寄存器汇总

序号

寄存器名

读/写

功能描述

1

P_SW1

读/写

外设端口切换控制寄存器1。

2

SPCTL

读/写

SPI控制寄存器。

3

SPSTAT

读/写

SPI状态寄存器。

4

SPDAT

读/写

SPI数据寄存器。

5

IE2

读/写

中断允许寄存器2。

6

IP2

读/写

中断优先级控制寄存器2。

2.寄存器解析2.1.SPI控制寄存器SPCTL

SPI控制寄存器控制SPI工作模式、时钟频率、使能选择等,详见下图。

图9:SPI控制寄存器SPCTL

2.2.SPI状态寄存器SPSTAT

SPI状态寄存器SPSTAT的B7位用来标志SPI传输完成,B6位则在SPI对数据寄存器SPDAT写操作时置1,详见下图。

图10:SPI状态寄存器SPSTAT

2.3.中断允许寄存器IE2

中断允许寄存器IE2中B1位用于对SPI中断的使能控制,参考下图。

图11:SPI中断允许寄存器

☆注:中断允许寄存器IE2还有对其他外设的中断使能控制位,所以操作该寄存器时要按位操作。

2.4.中断优先级控制寄存器

中断优先级控制寄存器IP2和IP2H中B1位组合起来用于对SPI中断的优先级进行配置,详见下图。

图12:中断优先级控制寄存器

☆注:中断优先级控制寄存器还有对其他外设的中断优先级控制位,所以操作这些寄存器时要按位操作。

3.SPI配置步骤

针对STC8A8K64S4A12系列单片机SPI,软件的配置过程如下:

图13:SPI中断方式和非中断方式软件配置步骤

4.外接FRAM存储器读写单字节实验(模拟SPI)4.1.工程需要用到的c文件

本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。

表4:实验需要用到的c文件

序号

文件名

后缀

功能描述

1

uart

.c

包含与用户uart有关的用户自定义函数。

2

fm25cl64b

.c

SPI通信及操作FRAM有关的用户自定义函数。

3

delay

.c

包含用户自定义延时函数。

4.2.头文件引用和路径设置

■ 需要引用的头文件

#include "delay.h"  #include "uart.h"  #include " fm25cl64b.h"  

■ 需要包含的头文件路径

本例需要包含的头文件路径如下表:

表5:头文件包含路径

序号

路径

描述

1

…\ Source

uart.h、fm25cl64b.h和delay.h头文件在该路径,所以要包含。

2

…\Use

STC8.h头文件在该路径,所以要包含。

MDK中点击魔术棒,打开工程配置窗口,按照下图所示添加头文件包含路径。

图14:添加头文件包含路径

4.3.编写代码

首先,在fm25cl64b.c文件中编写模拟SPI方式的读写字节函数,这里的模拟SPI读字节函数与写字节函数是分开的,代码如下:

程序清单:模拟SPI写字节函数

/*****************************************************************************  * 描  述 : 模拟SPI写入一个字节  * 入  参 : uint8 date  * 返回值 : 无  ****************************************************************************/  void SPI_WriteByte(uint8 date)  {    uint8 temp,i;    temp = date;        for (i = 0; i < 8; i++)       {       SPI_SCK_0;           delay_us(10);       if((temp&0x80)==0x80)       { SPI_MOSI_1; }       else        { SPI_MOSI_0; }       SPI_SCK_1 ;           delay_us(10);       temp <<= 1;     }     SPI_MOSI_0;   } 

程序清单:模拟SPI读字节函数

/***********************************************************************  * 描  述 : 模拟SPI读取一个字节  * 入  参 : 无  * 返回值 : 读取uint8数据  ***********************************************************************/  uint8 SPI_ReadByte(void)  {    uint8 temp=0;    uint8 i;                        for(i = 0; i < 8; i++)      {      temp <<= 1;      SPI_SCK_0 ;              delay_us(10);          if(E_SPI_MISO)       {temp++; }      SPI_SCK_1 ;          delay_us(10);     }     return(temp);  }

然后,编写对FRAM存储器的基本操作函数,如下表所示。

表6:FRAM相关用户函数汇集

序号

函数名

功能描述

1

FramWriteByte

向FRAM指定地址存入单字节数据。

2

FramReadByte

从FRAM指定地址读取单字节数据。

3

FRAM_Read_Nbyte

从FRAM指定地址读取多字节数据。

4

FRAM_Write_Nbyte

向FRAM指定地址存入多字节数据。

5

FRAM_Erase_Nbyte

在FRAM指定地址开始擦除指定长度的数据。

关于每个操作外部FRAM相关用户函数,下面给出详细代码。

程序清单:向指定地址存入单字节数据函数

/****************************************************************************  * 描  述 : 向指定地址存入数据  * 入  参 : uint16 address写入的地址,uint8  da写入的数据  * 返回值 : 无  **************************************************************************/  void FramWriteByte(uint16 address,uint8  da)  {    uint8 temM,temL;      temM=(uint8)((address&0xff00)>>8);    temL=(uint8)(address&0x00ff);      SPI_CS_0;                              //使能器件      SPI_WriteByte(FM25CL64_WREN);          //写使能FRAM        SPI_CS_1;                              //取消片选     delay_80us();      SPI_CS_0;                              //使能器件     SPI_WriteByte(FM25CL64_WRITE);         //写数据到FRAM存储器命令    SPI_WriteByte(temM);                   //写存储器地址高8位    SPI_WriteByte(temL);                   //写存储器地址低8位    SPI_WriteByte(da);                     //写入要存入的数据    SPI_CS_1;                              //取消片选   } 

程序清单:从指定地址读取单字节数据函数

/***************************************************************************  * 描  述 : 向指定地址读取数据  * 入  参 : uint16 address要读取的地址  * 返回值 : 返回读取到的数据uint8  ***************************************************************************/  uint8 FramReadByte(uint16 address)  {    uint8  temp,temM,temL;      temM=(uint8)((address&0xff00)>>8);    temL=(uint8)(address&0x00ff);      SPI_CS_0;                           //使能器件               SPI_WriteByte(FM25CL64_READ);       //读存储器命令下发    SPI_WriteByte(temM);                //待读地址高位下发    SPI_WriteByte(temL);                //待读地址低位下发    temp = SPI_ReadByte();              //读存储器数据    SPI_CS_1;                           //取消片选             return temp;  } 

程序清单:从指定地址读取多字节数据函数

/************************************************************************ 功能描述:在指定地址开始读取多字节数据 入口参数:pbuf:数据存储区  ReadAddr:读数据首地址  Len:要读取的字节数 返回值:无  *************************************************************************/  void FRAM_Read_Nbyte(uint8 * pbuf,uint16 ReadAddr,uint16 Len)     {      uint16 i;                                                             SPI_CS_0;                                          //使能器件         SPI_WriteByte(FM25CL64_READ);                      //发送读数据命令         SPI_WriteByte((uint8)((ReadAddr&0xE0)>>8));      //写入高8位址,最大地址13位    SPI_WriteByte((uint8)ReadAddr);                  //写入低8位址      for(i=0;i<Len;i++)                                 //连续读取数据       {         *pbuf++=SPI_ReadByte();                         //读一个字节                }      SPI_CS_1;                                          //取消片选              } 

程序清单:向指定地址存入多字节数据函数

/************************************************************************ 功能描述:在指定地址开始写入多字节数据 入口参数:pbuf:数据存储区  WriteAddr:写入数据首地址  Len:要写入的字节数 返回值:无  **************************************************************************/  void FRAM_Write_Nbyte(uint8 * pbuf,uint16 WriteAddr,uint16 Len)  {      uint16 i;            SPI_CS_0;                                           //使能器件         SPI_WriteByte(FM25CL64_WREN);                       //写使能FRAM          SPI_CS_1;                                           //取消片选        delay_80us();        SPI_CS_0;                                           //使能器件           SPI_WriteByte(FM25CL64_WRITE);                      //发送写数据命令         SPI_WriteByte((uint8)((WriteAddr&0xE0)>>8));      //写入高8位址,最大地址13位     SPI_WriteByte((uint8)WriteAddr);                  //写入低8位址            for(i=0;i<Len;i++)                                  //连续写入数据       {                     SPI_WriteByte(pbuf[i]);                    //写入要存入的数据     }          SPI_CS_1;                                        //取消片选  }  

程序清单:擦除指定长度的数据函数

/************************************************************************* 功能描述:在指定地址开始擦除指定长度的数据 入口参数:EraseAddr:擦除首地址  Len:要擦除的字节数 返回值:无  **************************************************************************/  void FRAM_Erase_Nbyte(uint16 EraseAddr,uint16 Len)  {      uint16 i;            SPI_CS_0;                                           //使能器件         SPI_WriteByte(FM25CL64_WREN);                       //写使能FRAM          SPI_CS_1;                                           //取消片选      delay_80us();        SPI_CS_0;                                           //使能器件         SPI_WriteByte(FM25CL64_WRITE);                    //发送写数据命令         SPI_WriteByte((uint8)((EraseAddr&0xE0)>>8));      //写入高8位址,最大地址13位     SPI_WriteByte((uint8)EraseAddr);                  //写入低8位址            for(i=0;i<Len;i++)                                  //连续擦除数据       {                     SPI_WriteByte(0x00);                     //擦除数据即写入0x00      }          SPI_CS_1;                                           //取消片选  } 

最后,在主函数中对串口1进行初始化,并通过串口1发送不同的命令实现对单片机片外FRAM的单字节读、写及擦除等操作。

代码清单:主函数

int main()  {      uint8   Temp;            P3M1 &= 0xFE;   P3M0 &= 0xFE;                     //设置P3.0为准双向口      P3M1 &= 0xFD;   P3M0 |= 0x02;                     //设置P3.1为推挽输出            SPI_CS_1;                                     //SPI使能引脚初始化      Uart1_Init();                                 //串口1初始化        EA = 1;                                        //使能总中断     delay_ms(10);                                 //初始化后延时          while (1)      {       if(WriteFLAG)                        //写模式           {                WriteFLAG=0;                      //写标志变量清零,发送一次                FramWriteByte(0x0050,0x33);       //向FRAM地址0x0050中写入单字节数据0x33             SendDataByUart1(0x33);            //串口1发送数据0x33表示写操作完成           }           if(ReadFLAG)                         //读模式           {                ReadFLAG=0;                       //读标志变量清零,发送一次                Temp=FramReadByte(0x0050);        //从FRAM地址0x0050读取单字节数据并赋值给变量Temp             SendDataByUart1(Temp);              //串口1发送Temp变量值(即读取的单字节数据)           }             if(ClearFLAG)                        //擦除模式           {                ClearFLAG=0;                      //清除标志变量清零,发送一次                FRAM_Erase_Nbyte(0x0050,1);       //擦除FRAM地址0x0050的数据             SendDataByUart1(0x00);            //串口1发送数据0x00表示擦除完成           }         }  } 
4.4.硬件连接

图15:开发板连接图

5.外接FRAM存储器读写多字节实验(模拟SPI)5.1.编写代码

首先,在fm25cl64b.c文件中编写模拟SPI方式的读写字节函数和对FRAM存储器的基本操作函数。请参考“实验2-15-1:外接FRAM存储器读写单字节实验(模拟SPI)”部分。

然后,在主函数中对串口1进行初始化,并通过串口1发送不同的命令实现对单片机片外FRAM的多字节读、写及擦除等操作。

代码清单:主函数

int main()  {      P3M1 &= 0xFE;   P3M0 &= 0xFE;                     //设置P3.0为准双向口      P3M1 &= 0xFD;   P3M0 |= 0x02;                     //设置P3.1为推挽输出            SPI_CS_1;                                     //SPI使能引脚初始化      Uart1_Init();                                 //串口1初始化        EA = 1;                                       //使能总中断    delay_ms(10);                                 //初始化后延时          while(1)    {                 if(WriteFLAG)                                     //写模式           {                              WriteFLAG=0;                                   //写标志变量清零,发送一次                FRAM_Write_Nbyte(FRAM_Test_Write,0x0000,10);   //向FRAM地址0x0000中写入FRAM_Test_Write数组中10个字节数据          SendDataByUart1(0x33);                         //串口1发送数据0x33表示写操作完成           }           if(ReadFLAG)                                      //读模式           {                ReadFLAG=0;                                    //读标志变量清零,发送一次                FRAM_Read_Nbyte(FRAM_Test_Read,0x0000,10) ;    //从FRAM地址0x0000读取10个字节数据存放数组FRAM_Test_Read中                SendStringByUart1_n(FRAM_Test_Read,10);        //串口1发送数组FRAM_Test_Read中的值(即读取的多字节数据)           }             if(ClearFLAG)                                     //清除模式           {                ClearFLAG=0;                                   //清除标志变量清零,发送一次                FRAM_Erase_Nbyte(0x0000,10);         //擦除FRAM地址0x0000开始的10个字节长度的数据             SendDataByUart1(0x00);                         //串口1发送数据0x00表示擦除完成           }         }  }  
5.2.硬件连接

图16:开发板连接图

6.外接FRAM存储器读写单字节实验(硬件SPI)6.1.工程需要用到的c文件

本例需要用到的c文件如下表所示,工程需要添加下表中的c文件。

表7:实验需要用到的c文件

序号

文件名

后缀

功能描述

1

uart

.c

包含与用户uart有关的用户自定义函数

2

fm25cl64b

.c

SPI通信及操作FRAM有关的用户自定义函数。

3

delay

.c

包含用户自定义延时函数。

6.2.头文件引用和路径设置

■ 需要引用的头文件

#include "delay.h"  #include "uart.h"  #include " fm25cl64b.h"  

■ 需要包含的头文件路径

本例需要包含的头文件路径如下表:

表8:头文件包含路径

序号

路径

描述

1

…\ Source

uart.h、fm25cl64b.h和delay.h头文件在该路径,所以要包含。

2

…\User

STC8.h头文件在该路径,所以要包含。

MDK中点击魔术棒,打开工程配置窗口,按照下图所示添加头文件包含路径。

图17:添加头文件包含路径

6.3.编写代码

首先,在fm25cl64b.c文件中对硬件SPI进行初始化,并编写硬件SPI的读写字节函数,代码如下:

程序清单:硬件SPI初始化函数

/**************************************************************************************  * 描  述 : 硬件SPI初始化  * 入  参 : 无  * 返回值 : 无  **************************************************************************************/  void Init_SPI(void)            {       P_SW1 |=0X08;                         //将 SPI 调整到 P7.4 P7.5 P7.6  P7.7        P_SW1 &=0XFB;                         //将 SPI 调整到 P7.4 P7.5 P7.6  P7.7       SPDAT = 0;      SPSTAT = SPIF | WCOL;               //清除SPI状态位      SPCTL = SPEN | MSTR | SSIG;         //主机模式        }  

程序清单:硬件SPI读写字节函数

/***********************************************************************  * 描  述 : 硬件SPI写入一个字节,并返回一个值  * 入  参 : uint8 date  * 返回值 : 无  ***********************************************************************/  uint8 SPI_SendByte(uint8 SPI_SendData)  {    SPDAT = SPI_SendData;        //触发SPI发送数据    while (!(SPSTAT & SPIF));    //等待发送完成    SPSTAT = SPIF | WCOL;        //清除SPI状态位    return SPDAT;                //返回SPI数据  } 

然后,编写对FRAM存储器的基本操作函数,如下表所示。

表9:FRAM相关用户函数汇集

序号

函数名

功能描述

1

FramWriteByte

向FRAM指定地址存入单字节数据。

2

FramReadByte

从FRAM指定地址读取单字节数据。

3

FRAM_Read_Nbyte

从FRAM指定地址读取多字节数据。

4

FRAM_Write_Nbyte

向FRAM指定地址存入多字节数据。

5

FRAM_Erase_Nbyte

在FRAM指定地址开始擦除指定长度的数据。

关于每个操作外部FRAM相关用户函数,下面给出详细代码。

程序清单:向指定地址存入单字节数据函数

/**************************************************************************  * 描  述 : 向指定地址存入数据  * 入  参 : uint16 address写入的地址,uint8  da写入的数据  * 返回值 : 无  **************************************************************************/  void FramWriteByte(uint16 address,uint8  da)  {    uint8 temM,temL;      temM=(uint8)((address&0xff00)>>8);    temL=(uint8)(address&0x00ff);      SPI_CS_0;                    //使能器件     SPI_SendByte(WREN);          //写使能FRAM        SPI_CS_1;                    //取消片选     delay_80us();      SPI_CS_0;                    //使能器件     SPI_SendByte(WRITEE);        //写数据到FRAM存储器命令    SPI_SendByte(temM);          //写存储器地址高8位    SPI_SendByte(temL);          //写存储器地址低8位    SPI_SendByte(da);            //写入要存入的数据    SPI_CS_1;                    //取消片选   }  

程序清单:从指定地址读取单字节数据函数

/**************************************************************************  * 描  述 : 向指定地址读取数据  * 入  参 : uint16 address要读取的地址  * 返回值 : 返回读取到的数据uint8  ***************************************************************************/  uint8 FramReadByte(uint16 address)  {    uint8  temp,temM,temL;      temM=(uint8)((address&0xff00)>>8);    temL=(uint8)(address&0x00ff);      SPI_CS_0;                      //使能器件              SPI_SendByte(READD);           //读存储器命令下发    SPI_SendByte(temM);            //待读地址高位下发    SPI_SendByte(temL);            //待读地址低位下发    temp = SPI_SendByte(0xFF);     //读存储器数据    SPI_CS_1;                      //取消片选            return temp;  }

程序清单:从指定地址读取多字节数据函数

/************************************************************************** 功能描述:在指定地址开始读取多字节数据 入口参数:pbuf:数据存储区  ReadAddr:读数据首地址  Len:要读取的字节数 返回值:无  **************************************************************************/  void FRAM_Read_Nbyte(uint8 * pbuf,uint16 ReadAddr,uint16 Len)     {      uint16 i;                                                             SPI_CS_0;                                          //使能器件         SPI_SendByte(FM25CL64_READ);                       //发送读数据命令         SPI_SendByte((uint8)((ReadAddr&0xE0)>>8));       //写入高8位址,最大地址13位    SPI_SendByte((uint8)ReadAddr);                     //写入低8位址      for(i=0;i<Len;i++)                                 //连续读取数据       {         *pbuf++=SPI_SendByte(0xFF);                     //读一个字节                }      SPI_CS_1;                                          //取消片选              } 

程序清单:向指定地址存入多字节数据函数

/************************************************************************* 功能描述:在指定地址开始写入多字节数据 入口参数:pbuf:数据存储区  WriteAddr:写入数据首地址  Len:要写入的字节数 返回值:无  **********************************************************************/  void FRAM_Write_Nbyte(uint8 * pbuf,uint16 WriteAddr,uint16 Len)  {      uint16 i;            SPI_CS_0;                                           //使能器件         SPI_SendByte(FM25CL64_WREN);                        //写使能FRAM          SPI_CS_1;                                           //取消片选        delay_80us();        SPI_CS_0;                                           //使能器件         SPI_SendByte(FM25CL64_WRITE);                       //发送写数据命令         SPI_SendByte((uint8)((WriteAddr&0xE0)>>8));      //写入高8位址,最大地址13位     SPI_SendByte((uint8)WriteAddr);                     //写入低8位址            for(i=0;i<Len;i++)                                  //连续写入数据       {                     SPI_SendByte(pbuf[i]);                    //写入要存入的数据    }          SPI_CS_1;                                           //取消片选  } 

程序清单:擦除指定长度的数据函数

/************************************************************************* 功能描述:在指定地址开始擦除指定长度的数据 入口参数:EraseAddr:擦除首地址  Len:要擦除的字节数 返回值:无  ****************************************************************************/  void FRAM_Erase_Nbyte(uint16 EraseAddr,uint16 Len)  {      uint16 i;            SPI_CS_0;                                           //使能器件         SPI_SendByte(FM25CL64_WREN);                        //写使能FRAM          SPI_CS_1;                                           //取消片选        delay_80us();        SPI_CS_0;                                           //使能器件           SPI_SendByte(FM25CL64_WRITE);                       //发送写数据命令         SPI_SendByte((uint8)((EraseAddr&0xE0)>>8));       //写入高8位址,最大地址13位    SPI_SendByte((uint8)EraseAddr);                     //写入低8位址            for(i=0;i<Len;i++)                                  //连续擦除数据       {                     SPI_SendByte(0x00);                       //擦除数据即写入0x00      }          SPI_CS_1;                                       //取消片选  } 

最后,在主函数中对串口1和SPI进行初始化,并通过串口1发送不同的命令实现对单片机片外FRAM的单字节读、写及擦除等操作。

代码清单:主函数

int main()  {      uint8   Temp;            P3M1 &= 0xFE;   P3M0 &= 0xFE;                     //设置P3.0为准双向口      P3M1 &= 0xFD;   P3M0 |= 0x02;                     //设置P3.1为推挽输出            SPI_CS_1;                                     //SPI使能引脚初始化      Init_SPI();                                     //初始化SPI      Uart1_Init();                                 //串口1初始化        EA = 1;                                       //使能总中断    delay_ms(10);                                 //初始化后延时          while (1)      {       if(WriteFLAG)                        //写模式           {                WriteFLAG=0;                      //写标志变量清零,发送一次                FramWriteByte(0x0050,0x33);       //向FRAM地址0x0050中写入单字节数据0x33          SendDataByUart1(0x33);            //串口1发送数据0x33表示写操作完成           }           if(ReadFLAG)                         //读模式           {                ReadFLAG=0;                       //读标志变量清零,发送一次                Temp=FramReadByte(0x0050);        //从FRAM地址0x0050读取单字节数据并赋值给变量Temp          SendDataByUart1(Temp);            //串口1发送Temp变量值(即读取的单字节数据)           }             if(ClearFLAG)                        //擦除模式           {                ClearFLAG=0;                      //清除标志变量清零,发送一次                FRAM_Erase_Nbyte(0x0050,1);       //擦除FRAM地址0x0050的数据          SendDataByUart1(0x00);            //串口1发送数据0x00表示擦除完成           }         }  }  
6.4.硬件连接

图18:开发板连接图

7.外接FRAM存储器读写多字节实验(硬件SPI)7.1.编写代码

首先,在fm25cl64b.c文件中编写硬件SPI方式的读写字节函数和对FRAM存储器的基本操作函数。请参考“实验2-15-3:外接FRAM存储器读写单字节实验(硬件SPI)”部分。

然后,在主函数中对串口1和SPI进行初始化,并通过串口1发送不同的命令实现对单片机片外FRAM的多字节读、写及擦除等操作。

代码清单:主函数

int main()  {      P3M1 &= 0xFE;   P3M0 &= 0xFE;                     //设置P3.0为准双向口      P3M1 &= 0xFD;   P3M0 |= 0x02;                     //设置P3.1为推挽输出            SPI_CS_1;                                     //SPI使能引脚初始化      Init_SPI();                                     //初始化SPI      Uart1_Init();                                 //串口1初始化        EA = 1;                                       //使能总中断     delay_ms(10);                                 //初始化后延时          while(1)    {                 if(WriteFLAG)                                     //写模式           {                              WriteFLAG=0;                                   //写标志变量清零,发送一次                FRAM_Write_Nbyte(FRAM_Test_Write,0x0000,10);   //向FRAM地址0x0000中写入FRAM_Test_Write数组中10个字节数据          SendDataByUart1(0x33);                         //串口1发送数据0x33表示写操作完成           }           if(ReadFLAG)                                      //读模式           {                ReadFLAG=0;                                    //读标志变量清零,发送一次                FRAM_Read_Nbyte(FRAM_Test_Read,0x0000,10) ;    //从FRAM地址0x0000读取10个字节数据存放数组FRAM_Test_Read中                SendStringByUart1_n(FRAM_Test_Read,10);        //串口1发送数组FRAM_Test_Read中的值(即读取的多字节数据)           }             if(ClearFLAG)                                     //清除模式           {                ClearFLAG=0;                                   //清除标志变量清零,发送一次                FRAM_Erase_Nbyte(0x0000,10);              //擦除FRAM地址0x0000开始的10个字节长度的数据             SendDataByUart1(0x00);                         //串口1发送数据0x00表示擦除完成           }         }  }
7.2.硬件连接

图19:开发板连接图

总结

以上是今天要讲的内容,希望对大家有帮助,如果有啥不明白的,欢迎讨论哦!

标签: #delayc文件主要包含哪些函数并简要说明各函数的作用