教你LPC54102双核套件固件库SPI的用法

发布时间:2023-04-03  

  最近进度有点慢。现在把我SPI这部分分享下吧。这次我使用SPI0和I2C2这两个模块,I2C2负责采集MPU6050的数据,然后用OLED刷新数据。


  SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议,在LPC5410中有两个SPI的模块,分别是SPI0和SPI1。


  SPI根据SPI时钟极性的极性和SPI时钟相位,SPI时钟极性CPOL, =0表示在没有数据传输时为低电平,= 1表示没有数据传输时为高电平。SPI时钟相位CPHA,= 0表示时钟的第一个沿更新数据、第二个沿锁存数据,= 1表示时钟的第一个沿锁存数据、第二个沿更新数据。如下面的几个时序图:

  教你LPC54102双核套件固件库SPI的用法

  教你LPC54102双核套件固件库SPI的用法

  教你LPC54102双核套件固件库SPI的用法

  教你LPC54102双核套件固件库SPI的用法

  教你LPC54102双核套件固件库SPI的用法

  我这次用了LPC54102的SPI0刷了小OLED。首先LPC54102套件上有个SPI / I2C brdge header,如下套件的原理图:

  教你LPC54102双核套件固件库SPI的用法

  具体位置如下图:

  教你LPC54102双核套件固件库SPI的用法

  板子的背面有对应的丝印文字,很容易找到。

  这次没用到中断和DMA。首先我们要配置好管脚。

  voidInit_SPI_PinMux(void)

  {

  /* 1.3 = SPI0_SCK, 0.14 = SPI0_SSELN0,0.12 = SPI0_MOSI, 1.4 = SPI0_MISO */

  Chip_IOCON_PinMuxSet(LPC_IOCON, 1,3, (IOCON_FUNC5 | IOCON_DIGITAL_EN |IOCON_MODE_PULLUP));

  Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 14,(IOCON_FUNC1 | IOCON_DIGITAL_EN | IOCON_MODE_PULLUP));

  Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 12,(IOCON_FUNC1 | IOCON_DIGITAL_EN | IOCON_MODE_PULLUP));

  Chip_IOCON_PinMuxSet(LPC_IOCON, 1,4, (IOCON_FUNC5 | IOCON_DIGITAL_EN |IOCON_MODE_PULLUP));

  }

  然后进行SPI的初始化。如下函数:

  根据OLED上的SSD1306提供的手册和别人的写的模拟SPI驱动,我们要选用CPOL = 0,和CPA = 0这种模式。

  SSD1306的4线SPI的时序图:

  教你LPC54102双核套件固件库SPI的用法

  voidSPI_Init()

  {

  uint32_t memSize, *devMem;

  ROM_SPIM_INIT_T spimInit;

  ROM_SPIM_XFER_CONFIG_T spimConfig;

  int i;

  Init_SPI_PinMux();

  Chip_Clock_EnablePeriphClock(LPC_SPIM_CLOCK);

  Chip_SYSCON_PeriphReset(LPC_SPIM_RESET);

  /* Get needed size for drivercontext memory */

  memSize = ROM_SPIM_GetMemSize();

  if (memSize 》 sizeof(drvData)) {

  DEBUGOUT(“Can‘t allocatememory for driver context ”);

  }

  devMem = drvData; /* Or just use malloc(memSize) */

  /* Initialize driver */

  spimInit.pUserData = NULL;

  spimInit.base = (uint32_t) LPC_SPIM_PORT;

  spimInit.baseClockRate =Chip_Clock_GetAsyncSyscon_ClockRate();

  spimInit.spiPol[0] = 0; /* Active low select for SSEL0 */

  spimInit.spiPol[1] = 1;

  spimInit.spiPol[2] = 1;

  spimInit.spiPol[3] = 1;

  spimHandle = ROM_SPIM_Init(devMem,&spimInit);

  if (spimHandle == NULL) {

  /* Error initializing SPI */

  DEBUGOUT(“Error initializingROM ”);

  }

  /* Set SPI transfer configuration */

  spimConfig.dXferBitRate = SPI_BITRATE;

  spimConfig.mode =ROM_SPI_CLOCK_CPHA0_CPOL0;

  spimConfig.lsbFirst = 0;

  spimConfig.dataBits = 8;

  spimConfig.PreDelay = 3;

  spimConfig.PostDelay = 1;

  spimConfig.FrameDelay = 2;

  spimConfig.TransferDelay = 1;

  if (ROM_SPIM_SetupTransfer(spimHandle,&spimConfig) != LPC_OK) {

  DEBUGOUT(“SPI configurationis invalid ”);

  }

  /* Show desired and actual SPI rates */

  DEBUGOUT(“SPI rate = %d (actual%d) ”, spimConfig.dXferBitRate, spimConfig.rXferBitRate);

  /* Callback registration for assertionand de-assertion events */

  ROM_SPIM_RegisterCallback(spimHandle,ROM_SPIM_ASSERTSSEL_CB, (void *) CBspiMasterXferCSAssertCB);

  ROM_SPIM_RegisterCallback(spimHandle,ROM_SPIM_DEASSERTSSEL_CB, (void *) CBspiMMasterXferCSDeAssertCB);

  }

  我对这里面几个关键的参数作下说明吧:

  spimInit.spiPol[0] = 0; /* Active low select for SSEL0 */

  spimInit.spiPol[1] = 1;

  spimInit.spiPol[2] = 1;

  spimInit.spiPol[3] = 1;

  spimInit.spiPol[X]是对应的4个片选SSEL0~ SSEL3引脚。

  spimConfig.dXferBitRate= SPI_BITRATE;这个是时钟频率的参数,单位是HZ。

  spimConfig.mode= ROM_SPI_CLOCK_CPHA0_CPOL0;这是设定SPI时钟极性的极性和SPI时钟相位的参数。如在SPI的底层中可以看到这4个参数代表了4中模式。

  教你LPC54102双核套件固件库SPI的用法

  spimConfig.lsbFirst= 0;这个是设置开始传输的数据是最高位还是最低位。9代表开始传输的是最高位,1代表开始传输的最低位。

  spimConfig.dataBits= 8;这个参数是每次传输的数据多少位,可以1到16bit数据之间。

  spimConfig.PreDelay = 3;

  spimConfig.PostDelay = 1;

  spimConfig.FrameDelay = 2;

  spimConfig.TransferDelay = 1;

  上面这几个参数是传输时的几个延时,我这里就不作过多说明了,我也在了解中。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    ,所以不用自己刷固件。 ESP-01S WiFi模块是一款低功耗高性价比的嵌入式无线网络控制模块。可满足智能电网、楼宇自动化、安防、智能家居、远程医疗等物联网应用的需求。该模......
    组装的可动线圈驱动器容易造成缺陷和不良特性,大规模生产中常常会出现这种情况。印刷固态驱动器消除了这种不确定性,并使得驱动器性能保持一致。 · xMEMS固态硅驱动器的功率远低于传统驱动器的功率,而尺......
    安全固件更新 - STM32 SBSFU的实现与应用;STM32 安全固件更新 STM32 安全固件更新离不开STM32 安全启动。 参考上图23, 理解STM32 安全固件......
    STM32 SBSFU的实现与应用;STM32安全固件更新 STM32安全固件更新离不开STM32安全启动。 参考上图23,理解STM32安全固件更新的流程。 下载固件头 验证固件头 下载(加密......
    STM32安全固件更新的设计与实现;STM32 提供了安全固件更新的参考设计。为了理解STM32 安全固件更新,我们可以先去看一看普通的固件更新式如何设计,包括一般流程、端到......
    STM32安全固件更新的安全挑战;固件更新是我们软件生命周期中必须面临的问题。软件生命周期中有多种原因让我们需要固件更新,而固件更新也会带来安全问题,如使用固件更新来攻击电子钱包。 STM32 已经提供了很多的安全技术来应对固件......
    STM32安全固件更新的额外设计;为了安全的额外设计 我们要让一般的固件更新变成安全的固件更新。体现在: a. 固件是保密的 b. 固件是完整的 c. 固件是可靠的 固件的保密,在传......
    全开源的软硬件及上位机支持,支持windos和linux Stock can并且都免驱,且支持Python。 而且远不止于此,经过我不断探索,在gitlhub各个大神仓库各种折腾。 我发现这个canable这个项目衍生出了很多开源固件......
    持Python。 而且远不止于此,经过我不断探索,在gitlhub各个大神仓库各种折腾。我发现这个canable这个项目衍生出了很多开源固件,目前固件和支持的软件已经极为丰富。 而且主芯片STM32F042......
    车规MCU的安全启动固件;安全启动固件(Secure Boot Firmware) 车规MCU的安全启动固件(Secure Boot Firmware)是一......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>