尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

MPC5744P (八) SPI

MPC5744P (八) SPI 代码工程上传了大家自取https://pan.baidu.com/s/11aew6hw3XaAaoaPlzu7XYw?pwd6666串行外设接口SPI模块提供同步串行总线用于芯片与外部外设器件之间的通信。在本章节中简单的介绍了如何使用SPI与外设通信。一SPI特性本模块支持以下功能全双工、三线同步传输主机模式从机模式从机模式下支持从选信号持续有效时的数据流传输发送缓冲采用深度为 5 级的发送先入先出缓存TX FIFO实现发送缓冲操作接收缓冲采用深度为 5 级的接收先入先出缓存RX FIFO实现接收缓冲操作TX FIFO、RX FIFO 可独立关闭实现 SPI 队列的低延迟更新支持查看 TX、RX FIFO 状态便于调试可按帧配置传输属性4 组传输属性寄存器串行时钟SCK极性、相位可编程配置多种可编程延时串行帧长度可编程4 ~ 16 位超过 16 位的 SPI 帧可通过持续片选格式实现传输支持片选信号持续保持功能8 路外设片选信号PCSE外接多路分配器可扩展至 256 路外接多路分配器时最多支持 128 路外设片选PCSE的信号消抖功能DMA 支持向 TX FIFO 写入数据、从 RX FIFO 读取数据TX FIFO 非满TFFFRX FIFO 非空RFDF中断触发条件队列传输完成EOQFTX FIFO 非满TFFF当前帧传输完成TCF发送 FIFO 为空时尝试发送TFUFRX FIFO 非空RFDF接收 FIFO 已满时收到新帧RFOF全局中断请求线改良型 SPI 传输格式可适配低速外设器件通信低功耗架构特性支持停机模式MPC5744P的SPI模块的框图如下所示二寄存器SPI模块的所有寄存器如下图所示。1SPI_MCR模块配置寄存器该寄存器包含多位配置字段用于设置模块运行相关的各类工作属性。HALT 位与 MDIS 位可随时改写但配置生效时机为下一个帧边界。当模块处于运行状态时仅允许修改 MCR 寄存器中的 HALT 和 MDIS 位。2SPI_CTARn时钟与传输属性寄存器用于定义各类传输属性。模块处于运行状态时禁止对 CTAR 寄存器执行写操作。主机模式下CTAR 寄存器可配置一组传输属性包括帧长度、时钟相位与极性、数据位传输顺序、波特率以及各类延时参数。从机模式下仅使用 CTAR0 中的部分位域配置从机传输属性。模块配置为 SPI 主机时TX FIFO 表项命令段内的 CTAS 字段用于选择本次传输使用哪一路 CTAR 寄存器配置模块配置为 SPI 总线从机时固定使用 CTAR0 寄存器。(注当使用一路SPI控制不通时钟与传输属性的外设时就可以用到该寄存器。比如SPI0要与W25Q641MHz的时钟、CPHA0、CPOL0)和DRV8343(2MHz的时钟、CPHA1、CPOL0)通信就可以将CTAR0配置为1MHz的时钟、CPHA0、CPOL0将CTAR1配置为2MHz的时钟、CPHA1、CPOL0在传输时在SPI_PUSHR寄存器中选择要使用CTAR0还是CTAR1即可该寄存器内主要涉及到SCK波特率配置、极性和相位配置、传输延迟配置目前我还没用到有需求详见手册1.SCK波特率配置在手册中提到的SCK波特率计算方法如下图所示即$$SCK波特率 (fP /PBR)*[(1DBR)/BR]$$式中fP为外设时钟频率在本工程中已配置为 fP 40MHz参考本系列教程的三系统时钟的PBRIDGEx_CLKPBR默认值为2DBR默认值为0BR根据自己需求设置。2.极性和相位配置主机模式下时钟与传输属性寄存器CTARn中的 CPOL、CPHA 位用于配置串行时钟 SCK 的极性与相位CPOL配置 SCK 空闲状态的电平极性CPHA配置 SOUT 上的数据是在第一个 SCK 边沿之前有效还是在第一个 SCK 边沿时刻有效当CPHA0时当CPHA1时寄存器详解如下3SPI_SR状态寄存器SR包含状态位与标志位。这些位用于反映外设模块运行状态并标记可触发中断或 DMA 请求的事件是否发生。软件向 SR 中的标志位写入 1即可清除该标志位向标志位写入 0 则无效。受省电机制影响模块禁用模式下该寄存器可能不可写。4SPI_RSERRSER 用于控制 DMA 请求与中断请求模块处于运行状态时禁止对 RSER 寄存器执行写操作5SPI_PUSHR该寄存器用于指定待送入发送 FIFO 的数据。对该寄存器执行 8 位或 16 位写访问时都会将完整 32 位数据送入发送 FIFO。在主机模式下该寄存器承载 16 位传输数据与 16 位命令信息。读取 PUSHR 寄存器将返回发送 FIFO 队首的数据条目。当外设模块处于禁用状态时向该寄存器写入数据不会更新 FIFO 内容。因此模块禁用期间执行读操作读取到的是模块启用状态下最后一次写入 PUSHR 寄存器的值。6SPI_POPRPOPR 用于读取接收 FIFO。对 POPR 执行 8 位、16 位读操作和 32 位读操作对接收 FIFO 产生的作用完全一致。向该寄存器执行写操作会触发传输错误。三功能先搁置一下过两天补。。。最近太忙了四代码main.c文件#include derivative.h /* include peripheral declarations */ #include project.h #include mode_entry.h #include gpio.h #include uart.h #include spi.h extern void xcptn_xmpl(void); void peri_clock_gating(void); /* Configure gating/enabling peri. clocks */ __attribute__ ((section(.text))) int main(void) { int counter 0; xcptn_xmpl (); /* Configure and Enable Interrupts */ peri_clock_gating(); /* Configure gating/enabling peri. clocks for modes*/ system160mhz(); /* sysclk160MHz, dividers configured, mode trans*/ gpio_output(PA5,SIUL2_SRC_FULL_DIS,SIUL2_SSS_1); //PA5 SPI1_CS0 gpio_output(PA6,SIUL2_SRC_FULL_DIS,SIUL2_SSS_1); //PA6 SPI1_SCK gpio_output(PA7,SIUL2_SRC_FULL_DIS,SIUL2_SSS_1); //PA7 SPI1_MOSI gpio_input(PA8,SIUL2_NULL,44,SIUL2_SSS_1); //PA8 SPI1_MISO spi_init(SPI1,SPI_PCS0,SPI_POL_LOW,SPI_PHA_1,SPI_BR_16); uint8_t RecDataMaster[4]; uint8_t SenDataMaster[4]; uint16_t time1,time2; SenDataMaster[0] 0x9F; SenDataMaster[1] 0xFF; SenDataMaster[2] 0xFF; SenDataMaster[3] 0xFF; for(;;) { spi_swap_string(SPI1,SenDataMaster,RecDataMaster,4); counter; } return 0; } void peri_clock_gating (void) { MC_ME.RUN_PC[0].R 0x00000000; /* gate off clock for all RUN modes */ MC_ME.RUN_PC[1].R 0x000000FE; /* enable peri clock for all RUN modes */ /* Note: RUN_PC0 is default cfg for PCTLs */ MC_ME.PCTL204.B.RUN_CFG 0x00000001; //开启LIN_0时钟门 MC_ME.PCTL91.B.RUN_CFG 0x00000001; //开启LIN_1时钟门 MC_ME.PCTL98.B.RUN_CFG 0x00000001; //开启SPI_1时钟门 }spi.c文件/** * file spi.c * brief spi驱动 * details 适配MPC5744P * author loopy * date 2026-08-16 * version V1.0 * note 无 */ //头文件包含 #include spi.h #include project.h volatile struct SPI_tag *SPI[SPI_MAX] {SPI_0, SPI_1, SPI_2, SPI_3}; /** * brief spi初始化函数 * param spi_num: SPI模块编号 * param spi_pcs: 启用的片选引脚 * param spi_pol: SCK的极性 * param spi_pha: 相位 * param spi_br: 分频系数 * return 无 * note 无 */ void spi_init(spi_num spi_num,uint8_t spi_pcs,spi_pol spi_pol,spi_pha spi_pha,uint8_t spi_br) { SPI[spi_num]-MCR.B.MSTR 1; //使能主机模式 SPI[spi_num]-MCR.B.PCSIS spi_pcs; //使能片选引脚 SPI[spi_num]-MCR.B.MDIS 0; //SPI[spi_num]-MCR.B.MTFE 1; //SPI[spi_num]-MCR.B.SMPL_PT 0; SPI[spi_num]-MCR.B.HALT 1; //停止模式下配置 SPI[spi_num]-MODE.CTAR[0].B.CPOL spi_pol; SPI[spi_num]-MODE.CTAR[0].B.CPHA spi_pha; SPI[spi_num]-MODE.CTAR[0].B.FMSZ 7; //8字节传输 /* 时钟计算SCK baud rate (fP /PBR) x [(1DBR)/BR] * fP为外设时钟频率在本工程中已配置为 fP 40MHz * PBR默认值为2DBR默认值为0BR根据自己需求设置 */ SPI[spi_num]-MODE.CTAR[0].B.BR spi_br; //分频系数 SPI[spi_num]-MCR.B.HALT 0; //停止模式下配置 } /** * brief spi发送接收字节函数 * param spi_num: SPI模块编号 * param byte: 传输的byte * param spi_keepcs: 启用的片选引脚 * return recdata: 读取返回值 * note 当前默认片选脚0 */ uint8_t spi_swap_byte(spi_num spi_num,uint8_t byte,spi_keepcs spi_keepcs) { uint8_t recdata 0; SPI[spi_num]-PUSHR.PUSHR.R 0x08010000 | byte | (uint32_t)((uint32_t)spi_keepcs31); while (SPI[spi_num]-SR.B.TCF ! 1){} while (SPI[spi_num]-SR.B.RFDF ! 1){} recdata SPI[spi_num]-POPR.R; SPI[spi_num]-SR.R 0xDA0A0000; return recdata; } /** * brief spi发送接收字符串函数 * param spi_num: SPI模块编号 * param *send_data: 发送的数组 * param *read_data: 接收的数组 * param len: 数组长度 * return 无 * note 无 */ void spi_swap_string(spi_num spi_num,uint8_t *send_data,uint8_t *read_data,uint8_t len) { uint8_t i 0; for(i0;ilen;i) { if(i len - 1) { read_data[i] spi_swap_byte(spi_num,send_data[i],SPI_RETURN_PCS); } else { read_data[i] spi_swap_byte(spi_num,send_data[i],SPI_KEEP_PCS); } } }spi.h文件/** * file spi.h * brief spi驱动 * details 适配MPC5744P * author loopy * date 2026-08-16 * version V1.0 * note 无 */ #ifndef PERIPHERALS_SPI_H_ #define PERIPHERALS_SPI_H_ //头文件包含 #include MPC5744P.h //宏定义 #define SPI_PCS0 0b00000001 //片选0 #define SPI_PCS1 0b00000010 //片选1 #define SPI_PCS2 0b00000100 //片选2 #define SPI_PCS3 0b00001000 //片选3 #define SPI_PCS4 0b00010000 //片选4 #define SPI_PCS5 0b00100000 //片选5 #define SPI_PCS6 0b01000000 //片选6 #define SPI_PCS7 0b10000000 //片选7 //数据类型定义 typedef enum //SPI序号 { SPI0 0x0, SPI1 0x1, SPI2 0x2, SPI3 0x3, SPI_MAX 0x4, }spi_num; typedef enum //SPI极性 { SPI_POL_LOW 0x0, //SCK空闲状态为低电平 SPI_POL_HIGH 0x1, //SCK空闲状态为高电平 }spi_pol; typedef enum //SPI相位 { SPI_PHA_0 0x0, //在 SCK第一个边沿捕获数据在下一个边沿更新数据 SPI_PHA_1 0x1, //在 SCK第一个边沿更新数据在下一个边沿捕获数据 }spi_pha; typedef enum //SPI 片选保持 { SPI_RETURN_PCS 0x0, //一个字节传输完成片选恢复 SPI_KEEP_PCS 0x1, //保持片选 }spi_keepcs; typedef enum //SPI BR系数 { SPI_BR_2 0x0, SPI_BR_4 0x1, SPI_BR_6 0x2, SPI_BR_8 0x3, SPI_BR_16 0x4, SPI_BR_32 0x5, SPI_BR_64 0x6, SPI_BR_128 0x7, SPI_BR_256 0x8, SPI_BR_512 0x9, SPI_BR_1024 0xA, SPI_BR_2048 0xB, SPI_BR_4096 0xC, SPI_BR_8192 0xD, SPI_BR_16384 0xE, SPI_BR_32768 0xF, }spi_br; //全局函数声明 /** * brief spi初始化函数 * param spi_num: SPI模块编号 * param spi_pcs: 启用的片选引脚 * param spi_pol: SCK的极性 * param spi_pha: 相位 * param spi_br: 分频系数 * return 无 * note 无 */ extern void spi_init(spi_num spi_num,uint8_t spi_pcs,spi_pol spi_pol,spi_pha spi_pha,uint8_t spi_br); /** * brief spi发送接收函数 * param spi_num: SPI模块编号 * param byte: 传输的byte * param spi_keepcs: 启用的片选引脚 * return recdata: 读取返回值 * note 无 */ extern uint8_t spi_swap_byte(spi_num spi_num,uint8_t byte,spi_keepcs spi_keepcs); /** * brief spi发送接收字符串函数 * param spi_num: SPI模块编号 * param *send_data: 发送的数组 * param *read_data: 接收的数组 * param len: 数组长度 * return 无 * note 无 */ void spi_swap_string(spi_num spi_num,uint8_t *send_data,uint8_t *read_data,uint8_t len); #endif /* PERIPHERALS_SPI_H_ */五实验现象与W25Q64发0x9F波形如下
返回列表