如何将数据写入wordpress文站wordpress英文版改成中文

当前位置: 首页 > news >正文

如何将数据写入wordpress文站,wordpress英文版改成中文,电脑速成班短期电脑培训班,网上宣传广告怎么做1.前言 前面看B站中有些小伙伴吐槽F4的SPIDMA没有硬件可控的CS引脚#xff0c;那么今天我就来攻破这个问题 我这边暂时没有SPI的从机芯片#xff0c;并且接收的过程与发送的过程类似#xff0c;所以这里我就以发送的过程为例了。 2.理论 手册上给出了如下的描述 我们关注…1.前言 前面看B站中有些小伙伴吐槽F4的SPIDMA没有硬件可控的CS引脚那么今天我就来攻破这个问题 我这边暂时没有SPI的从机芯片并且接收的过程与发送的过程类似所以这里我就以发送的过程为例了。 2.理论 手册上给出了如下的描述 我们关注一下黑点的两行这是DMA操作的核心我们可以理解为TXE与DMA的触发挂钩这样理解上与程序上都比较好写。 手册上还给出了DMA的触发流程如下。 我们详细剖析一下TXE与DMA操作关联可以看到每一次TXE变高DMA就会进行一次搬运直到通讯结束这样一来我们就可以通过等待TXE置位来联动DMA。 除此之外我们还需监控BSY位等待TXE1然后BSY0后再关闭SPI进而完成通讯 然后是DMA通道本次实验我用的是DMA2的数据流3的通道3 3.程序 3.1 SPI初始化 void init_spi1(void) {RCC-AHB1ENR|11; //开启PB时钟RCC-AHB1ENR|10; //开启PA时钟RCC-APB2ENR|112; //开启SPI1时钟#if SPI1_NSSMODE0init_spi1_nss1();#elseGPIOA-MODER|28; //PA4功能复用GPIOA-OSPEEDR|28; //端口速度50MHZGPIOA-PUPDR|18; //PA4上拉输出GPIOA-AFR[0]|516; //功能复用到SPI1#endifGPIOA-MODER|210; //PA5功能复用GPIOA-OSPEEDR|210; //端口速度50MHZGPIOA-PUPDR|110; //PA3上拉输出GPIOA-AFR[0]|520; //功能复用到SPI1GPIOA-MODER|212; //PA6功能复用GPIOA-OSPEEDR|212; //端口速度50MHZGPIOA-PUPDR|112; //PA6上拉输出GPIOA-AFR[0]|524; //功能复用到SPI1GPIOA-MODER|214; //PA7功能复用GPIOA-OSPEEDR|214; //端口速度50MHZGPIOA-PUPDR|114; //PA7上拉输出GPIOA-AFR[0]|528; //功能复用到SPI1SPI1-CR1(110); //全双工模式#if SPI1_NSSMODE0SPI2-CR1|19; //软件控制nssSPI2-CR1|18; //选择芯片上的引脚#elseSPI1-CR2|12; //硬件控制NSS引脚#endifSPI1-CR1|12; //作为SPI主机#if SPI1_DATALENGTH8SPI1-CR1(111); //数据长度为8位#elseSPI1-CR1|(111); //数据长度为16位#endif#if SPI1_DMA_TX_EN1SPI1-CR2|11; //开启DMA传输#elseSPI1-CR2(11); //开启DMA传输#endifSPI1-CR1|10; //从第二位开始采集数据SPI1-CR1|11; //空闲状态下时钟保持高电平SPI1-CR1|SPI_SPEED_83; //APB2上84MHz8分频SPI1-CR1(17); //先发送MSB,高位先发送SPI1-I2SCFGR~(111); //关闭I2S功能使用SPI } 说一下区别吧很少就一句话 SPI的CR2的第一位解释如下 这里注意一下SPI的发送与接收是分开的我们可以根据需要开启其中的DMA。 3.2 DMA初始化 //初始化DMA2 组3 通道3 //SPI1_TX void init_DMA2_S3C3(unsigned char *SPIData,unsigned short SPIWEI) { DMA2_Stream3 -CR 0;//禁止数据流 ,才能写寄存器 //外设地址寄存器//将所需寄存器的地址放入PAR寄存器DMA2_Stream3 -PAR (unsigned int)(SPI1-DR);//数据流地址寄存器//M1AR仅在双通道模式下有用//将数据所在地址给M0AR寄存器DMA2_Stream3 -M0AR (unsigned int)(SPIData);DMA2_Stream3 -NDTR SPIWEI; // 一次传输数量DMA2_Stream3 -FCR 0x21; //FIFO所有配置失效DMA2_Stream3 -CR | 1 6; //储存器到外设模式//循环模式//当NDTR寄存器减到0时自动重装//单次模式(普通模式)//NDTR减到0后停止DMADMA2_Stream3 -CR ~(18); //非循环模式DMA2_Stream3 -CR ~(311); //外设数据长度:8位DMA2_Stream3 -CR ~(313); //存储器数据长度:8位DMA2_Stream3 -CR ~(19); //外设非增量模式DMA2_Stream3 -CR | 110; //存储器增量模式指针增加可用于传输数组DMA2_Stream3 -CR | 116; //中等优先级//突发传输//DMA占用CPU总线时间此时CPU无法工作//一个节拍:传输多少次32位变量//应用场景:从ram里读出字节DMA2_Stream3 -CR ~(321); //外设突发单次传输DMA2_Stream3 -CR (323); //存储器突发单次传输DMA2_Stream3 -CR | 325; //通道3DMA2_Stream3 -CR | 10; //使能数据流 }没有什么特别的地方和存储器去寄存器的操作方式一致。 3.3 发送 unsigned char SPI1_WR(unsigned char SPI1MODE,unsigned char SPI1Data) {unsigned char temp0;switch(SPI1MODE){case SPI1_WRMODE://清除全部设置SPI1-CR1(115); SPI1-CR1(110);#if SPI1_NSSMODE0#elseSPI1-CR1|(16); //开启SPI#endifwhile((SPI1-SR11)0); //等待发送缓冲为空SPI1-DRSPI1Data; //发送数据while((SPI1-SR10)0); //等待接受缓冲为空tempSPI1-DR; //接受数据while((SPI1-SR17)1); //等待发送缓冲为空#if SPI1_NSSMODE0;#elseSPI1-CR1(16); //关闭SPI#endifbreak;case SPI1_WOMODE:#if SPI1_NSSMODE0#elseSPI1-CR1|(16); //开启SPI#endifSPI1-CR1(115); //清除模式设置SPI1-CR1(110); //清除模式设置while((SPI1-SR11)0); //等待发送缓冲为空#if SPI1_DMA_TX_EN1while((SPI1-SR11)0); //等待发送缓冲为空#elsewhile((SPI1-SR11)0); //等待发送缓冲为空SPI1-DRSPI1Data; //发送数据while((SPI1-SR11)0); //等待发送缓冲为空#endif#if SPI1_NSSMODE0#else#endifwhile((SPI1-SR17)1); //等待总线空闲SPI1-CR1(16); //关闭SPIbreak;case SPI1_ROMODE:SPI1-CR1(110);//清除模式设置SPI1-CR1|110; //半双工模式只读tempSPI1-DR; //接受数据break;}return temp; } 这里稍微说说区别 核心在于两个TXE的判断 第一个TXE就是手册上的第一个判断 第二个也就是后面的但是由于DMA的存在所以下面无需我们再判断当一个数据搬运完成就会重新再次搬运直达搬运完所有数据TXE才会拉高所以这里我们无需进行循环判断 4.测试 最终程序 spi.c #include spi.hvoid init_spi1(void) {RCC-AHB1ENR|11; //开启PB时钟RCC-AHB1ENR|10; //开启PA时钟RCC-APB2ENR|112; //开启SPI1时钟#if SPI1_NSSMODE0init_spi1_nss1();#elseGPIOA-MODER|28; //PA4功能复用GPIOA-OSPEEDR|28; //端口速度50MHZGPIOA-PUPDR|18; //PA4上拉输出GPIOA-AFR[0]|516; //功能复用到SPI1#endifGPIOA-MODER|210; //PA5功能复用GPIOA-OSPEEDR|210; //端口速度50MHZGPIOA-PUPDR|110; //PA3上拉输出GPIOA-AFR[0]|520; //功能复用到SPI1GPIOA-MODER|212; //PA6功能复用GPIOA-OSPEEDR|212; //端口速度50MHZGPIOA-PUPDR|112; //PA6上拉输出GPIOA-AFR[0]|524; //功能复用到SPI1GPIOA-MODER|214; //PA7功能复用GPIOA-OSPEEDR|214; //端口速度50MHZGPIOA-PUPDR|114; //PA7上拉输出GPIOA-AFR[0]|528; //功能复用到SPI1SPI1-CR1(110); //全双工模式#if SPI1_NSSMODE0SPI2-CR1|19; //软件控制nssSPI2-CR1|18; //选择芯片上的引脚#elseSPI1-CR2|12; //硬件控制NSS引脚#endifSPI1-CR1|12; //作为SPI主机#if SPI1_DATALENGTH8SPI1-CR1(111); //数据长度为8位#elseSPI1-CR1|(111); //数据长度为16位#endif#if SPI1_DMA_TX_EN1SPI1-CR2|11; //开启DMA传输#elseSPI1-CR2(11); //开启DMA传输#endifSPI1-CR1|10; //从第二位开始采集数据SPI1-CR1|11; //空闲状态下时钟保持高电平SPI1-CR1|SPI_SPEED_2563; //APB2上84MHz8分频SPI1-CR1(17); //先发送MSB,高位先发送SPI1-I2SCFGR(111); //关闭I2S功能使用SPI }unsigned char SPI1_WR(unsigned char SPI1MODE,unsigned char SPI1Data) {unsigned char temp0;switch(SPI1MODE){case SPI1_WRMODE://清除全部设置SPI1-CR1(115); SPI1-CR1(110);#if SPI1_NSSMODE0#elseSPI1-CR1|(16); //开启SPI#endifwhile((SPI1-SR11)0); //等待发送缓冲为空SPI1-DRSPI1Data; //发送数据while((SPI1-SR10)0); //等待接受缓冲为空tempSPI1-DR; //接受数据while((SPI1-SR17)1); //等待发送缓冲为空#if SPI1_NSSMODE0;#elseSPI1-CR1(16); //关闭SPI#endifbreak;case SPI1_WOMODE:#if SPI1_NSSMODE0#elseSPI1-CR1|(16); //开启SPI#endifSPI1-CR1(115); //清除模式设置SPI1-CR1(110); //清除模式设置while((SPI1-SR11)0); //等待发送缓冲为空#if SPI1_DMA_TX_EN1while((SPI1-SR11)0); //等待发送缓冲为空#elsewhile((SPI1-SR11)0); //等待发送缓冲为空SPI1-DRSPI1Data; //发送数据while((SPI1-SR11)0); //等待发送缓冲为空#endif#if SPI1_NSSMODE0#else#endifwhile((SPI1-SR17)1); //等待总线空闲SPI1-CR1(16); //关闭SPIbreak;case SPI1_ROMODE:SPI1-CR1(110);//清除模式设置SPI1-CR1|110; //半双工模式只读tempSPI1-DR; //接受数据break;}return temp; }spi.h #ifndef SPI_H__ #define SPI_H__#include stm32f4xx.h#define SPI_SPEED_2 0 #define SPI_SPEED_4 1 #define SPI_SPEED_8 2 #define SPI_SPEED_16 3 #define SPI_SPEED_32 4 #define SPI_SPEED_64 5 #define SPI_SPEED_128 6 #define SPI_SPEED_256 7//定义空闲状态下的时钟状态为1则是高电平否则是低电平 #define SPI1_CPOL 1 //定义数据长度 #define SPI1_DATALENGTH 8#define SPI1_NSS1UP do{GPIOB-ODR|112;}while(0) #define SPI1_NSS1DOWN do{GPIOB-ODR~(112);}while(0)//是否软件管理NSS引脚 //0 软件管理 //1 硬件管理 #define SPI1_NSSMODE 1//是否开启SPI1发送的DMA功能 //0 关闭 //1 开启 #define SPI1_DMA_TX_EN 1 //是否开启SPI1接收的DMA功能 //0 关闭 //1 开启 #define SPI1_DMA_RX_EN 0//SPI2通信模式 //0 全双工通信 //1 只发送 //2 只接收 #define SPI1_WRMODE 0 #define SPI1_WOMODE 1 #define SPI1_ROMODE 2#endif DMA //初始化DMA2 组3 通道3 //SPI1_TX void init_DMA2_S3C3(unsigned char *SPIData,unsigned short SPIWEI) { DMA2_Stream3 -CR 0;//禁止数据流 ,才能写寄存器 //外设地址寄存器//将所需寄存器的地址放入PAR寄存器DMA2_Stream3 -PAR (unsigned int)(SPI1-DR);//数据流地址寄存器//M1AR仅在双通道模式下有用//将数据所在地址给M0AR寄存器DMA2_Stream3 -M0AR (unsigned int)(SPIData);DMA2_Stream3 -NDTR SPIWEI; // 一次传输数量DMA2_Stream3 -FCR 0x21; //FIFO所有配置失效DMA2_Stream3 -CR | 1 6; //储存器到外设模式//循环模式//当NDTR寄存器减到0时自动重装//单次模式(普通模式)//NDTR减到0后停止DMADMA2_Stream3 -CR ~(18); //非循环模式DMA2_Stream3 -CR ~(311); //外设数据长度:8位DMA2_Stream3 -CR ~(313); //存储器数据长度:8位DMA2_Stream3 -CR ~(19); //外设非增量模式DMA2_Stream3 -CR | 110; //存储器增量模式指针增加可用于传输数组DMA2_Stream3 -CR | 116; //中等优先级//突发传输//DMA占用CPU总线时间此时CPU无法工作//一个节拍:传输多少次32位变量//应用场景:从ram里读出字节DMA2_Stream3 -CR ~(321); //外设突发单次传输DMA2_Stream3 -CR ~(323); //存储器突发单次传输DMA2_Stream3 -CR | 325; //通道3DMA2_Stream3 -CR | 10; //使能数据流 }我们在主程序里如何使用呢首先初始化SPI然后是DMA最后触发传输即可。这里我传输5个数据0x01,0x02,0x04,0x01最后一位应该是00 unsigned char spi_test_data[5]{0x01,0x02,0x04,0x01}; init_spi1();//初始化SPI1 init_DMA2_S3C3(spi_test_data,5);//初始化DMA SPI1_WR(SPI1_WOMODE,5);//发送 可以看到效果拔群啊CS管脚也没问题。 5.结语 至此完整的SPI完全出来了手册上说这样的效果可以实现SPI的最高速率但是我没有测试过。刚刚看手册的时候发现DMA有乒乓功能嗯难道这样一来速率还能在高那么还是老样子有问题评论区见我们下篇文章见。