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

工会网站建设方案wordpress文章折叠

工会网站建设方案,wordpress文章折叠,影楼和工作室的区别,wordpress集成到app系列文章目录 1. stm32之SPI通信协议 文章目录 系列文章目录前言一、电路接线图二、应用案例代码三、应用案例分析3.1 SPI通信模块3.2 W25Q64模块3.3 主程序 前言 提示#xff1a;本文主要用作在学习江科大自化协STM32入门教程后做的归纳总结笔记#xff0c;旨在学习记录本文主要用作在学习江科大自化协STM32入门教程后做的归纳总结笔记旨在学习记录如有侵权请联系作者 本案例使用软件SPI通信的方式实现了STM32与W25Q64 Flash存储器的通信完成了常见的Flash存储器操作如读ID、页写、扇区擦除、读取数据等。 一、电路接线图 下图所示为W25Q64模块硬件接线图左边是W25Q64模块作为从机右边是stm32作为主机。为了方便下一章节硬件SPI的接线这里直接就选择了硬件SPI1外设的接线方式。其中PA4对应主机的从机选择线SPI1_NSS连接到从机的CS引脚PA5对应主机的时钟同步线SPI1_SCK连接到从机的CLK引脚PA6对应主机的主机输入从机输出线SPI1_MISO连接到从机的DO引脚PA7对应主机的主机输出从机输入线SPI1_MOSI连接到从机的DI引脚。最后W25Q64模块的VCC和GND分别接到stm32的电源正负极进行供电。 二、应用案例代码 MySPI.h #ifndef __MYSPI_H #define __MYSPI_Hvoid MySPI_Init(void); void MySPI_Start(void); void MySPI_Stop(void); uint8_t MySPI_SwapByte(uint8_t ByteSend);#endifMySPI.c #include stm32f10x.h // Device headervoid MySPI_W_SS(uint8_t BitValue) {GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue); }void MySPI_W_SCK(uint8_t BitValue) {GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue); }void MySPI_W_MOSI(uint8_t BitValue) {GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue); }uint8_t MySPI_R_MISO(void) {return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6); }void MySPI_Init(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);MySPI_W_SS(1);MySPI_W_SCK(0); }void MySPI_Start(void) {MySPI_W_SS(0); }void MySPI_Stop(void) {MySPI_W_SS(1); }uint8_t MySPI_SwapByte(uint8_t ByteSend) {uint8_t i, ByteReceive 0x00;for (i 0; i 8; i ){MySPI_W_MOSI(ByteSend (0x80 i));MySPI_W_SCK(1);if (MySPI_R_MISO() 1){ByteReceive | (0x80 i);}MySPI_W_SCK(0);}return ByteReceive; }W25Q64.h #ifndef __W25Q64_H #define __W25Q64_Hvoid W25Q64_Init(void); void W25Q64_ReadID(uint8_t *MID, uint16_t *DID); void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count); void W25Q64_SectorErase(uint32_t Address); void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count);#endifW25Q64_Ins.h #ifndef __W25Q64_INS_H #define __W25Q64_INS_H#define W25Q64_WRITE_ENABLE 0x06 #define W25Q64_WRITE_DISABLE 0x04 #define W25Q64_READ_STATUS_REGISTER_1 0x05 #define W25Q64_READ_STATUS_REGISTER_2 0x35 #define W25Q64_WRITE_STATUS_REGISTER 0x01 #define W25Q64_PAGE_PROGRAM 0x02 #define W25Q64_QUAD_PAGE_PROGRAM 0x32 #define W25Q64_BLOCK_ERASE_64KB 0xD8 #define W25Q64_BLOCK_ERASE_32KB 0x52 #define W25Q64_SECTOR_ERASE_4KB 0x20 #define W25Q64_CHIP_ERASE 0xC7 #define W25Q64_ERASE_SUSPEND 0x75 #define W25Q64_ERASE_RESUME 0x7A #define W25Q64_POWER_DOWN 0xB9 #define W25Q64_HIGH_PERFORMANCE_MODE 0xA3 #define W25Q64_CONTINUOUS_READ_MODE_RESET 0xFF #define W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID 0xAB #define W25Q64_MANUFACTURER_DEVICE_ID 0x90 #define W25Q64_READ_UNIQUE_ID 0x4B #define W25Q64_JEDEC_ID 0x9F #define W25Q64_READ_DATA 0x03 #define W25Q64_FAST_READ 0x0B #define W25Q64_FAST_READ_DUAL_OUTPUT 0x3B #define W25Q64_FAST_READ_DUAL_IO 0xBB #define W25Q64_FAST_READ_QUAD_OUTPUT 0x6B #define W25Q64_FAST_READ_QUAD_IO 0xEB #define W25Q64_OCTAL_WORD_READ_QUAD_IO 0xE3#define W25Q64_DUMMY_BYTE 0xFF#endifW25Q64.c #include stm32f10x.h // Device header #include MySPI.h #include W25Q64_Ins.hvoid W25Q64_Init(void) {MySPI_Init(); }void W25Q64_ReadID(uint8_t *MID, uint16_t *DID) {MySPI_Start();MySPI_SwapByte(W25Q64_JEDEC_ID);*MID MySPI_SwapByte(W25Q64_DUMMY_BYTE);*DID MySPI_SwapByte(W25Q64_DUMMY_BYTE);*DID 8;*DID | MySPI_SwapByte(W25Q64_DUMMY_BYTE);MySPI_Stop(); }void W25Q64_WriteEnable(void) {MySPI_Start();MySPI_SwapByte(W25Q64_WRITE_ENABLE);MySPI_Stop(); }void W25Q64_WaitBusy(void) {uint32_t Timeout;MySPI_Start();MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);Timeout 100000;while ((MySPI_SwapByte(W25Q64_DUMMY_BYTE) 0x01) 0x01){Timeout --;if (Timeout 0){break;}}MySPI_Stop(); }void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count) {uint16_t i;W25Q64_WriteEnable();MySPI_Start();MySPI_SwapByte(W25Q64_PAGE_PROGRAM);MySPI_SwapByte(Address 16);MySPI_SwapByte(Address 8);MySPI_SwapByte(Address);for (i 0; i Count; i ){MySPI_SwapByte(DataArray[i]);}MySPI_Stop();W25Q64_WaitBusy(); }void W25Q64_SectorErase(uint32_t Address) {W25Q64_WriteEnable();MySPI_Start();MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);MySPI_SwapByte(Address 16);MySPI_SwapByte(Address 8);MySPI_SwapByte(Address);MySPI_Stop();W25Q64_WaitBusy(); }void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count) {uint32_t i;MySPI_Start();MySPI_SwapByte(W25Q64_READ_DATA);MySPI_SwapByte(Address 16);MySPI_SwapByte(Address 8);MySPI_SwapByte(Address);for (i 0; i Count; i ){DataArray[i] MySPI_SwapByte(W25Q64_DUMMY_BYTE);}MySPI_Stop(); }main.c #include stm32f10x.h // Device header #include Delay.h #include OLED.h #include W25Q64.huint8_t MID; uint16_t DID;uint8_t ArrayWrite[] {0x01, 0x02, 0x03, 0x04}; uint8_t ArrayRead[4];int main(void) {OLED_Init();W25Q64_Init();OLED_ShowString(1, 1, MID: DID:);OLED_ShowString(2, 1, W:);OLED_ShowString(3, 1, R:);W25Q64_ReadID(MID, DID);OLED_ShowHexNum(1, 5, MID, 2);OLED_ShowHexNum(1, 12, DID, 4);W25Q64_SectorErase(0x000000);W25Q64_PageProgram(0x000000, ArrayWrite, 4);W25Q64_ReadData(0x000000, ArrayRead, 4);OLED_ShowHexNum(2, 3, ArrayWrite[0], 2);OLED_ShowHexNum(2, 6, ArrayWrite[1], 2);OLED_ShowHexNum(2, 9, ArrayWrite[2], 2);OLED_ShowHexNum(2, 12, ArrayWrite[3], 2);OLED_ShowHexNum(3, 3, ArrayRead[0], 2);OLED_ShowHexNum(3, 6, ArrayRead[1], 2);OLED_ShowHexNum(3, 9, ArrayRead[2], 2);OLED_ShowHexNum(3, 12, ArrayRead[3], 2);while (1){} }完整工程stm32之软件SPI读写W25Q64存储器 三、应用案例分析 从整体架构来看主要分为SPI通信模块、W25Q64模块接下来重点分析一下SPI通信模块以及W25Q64模块。 3.1 SPI通信模块 SPI通信模块主要封装了一个模块初始化函数和三个时序单元模块。 SPI模块初始化函数 void MySPI_Init(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);MySPI_W_SS(1);MySPI_W_SCK(0); }这个没什么好讲的了都是一样的套路了。 这里要注意一下的就是PA4SS、PA5SCK、PA7MOSI引脚配置为推挽输出模式GPIO_Mode_Out_PP用于主设备主动输出信号。PA6MISO配置为上拉输入模式GPIO_Mode_IPU表示从设备的数据通过此引脚传输到主设备。 最后再设置一下总线的初始状态即可设置 SS 引脚为高电平即取消选择从设备然后初始化时钟引脚为低电平。 三个时序单元模块 三个时序单元分别是起始信号、终止信号以及交换一个字节。 起始信号、终止信号 void MySPI_Start(void) {MySPI_W_SS(0); }void MySPI_Stop(void) {MySPI_W_SS(1); }起始条件SS从高电平切换到低电平 终止条件SS从低电平切换到高电平 交换一个字节 uint8_t MySPI_SwapByte(uint8_t ByteSend) {uint8_t i, ByteReceive 0x00;for (i 0; i 8; i ){MySPI_W_MOSI(ByteSend (0x80 i));MySPI_W_SCK(1);if (MySPI_R_MISO() 1){ByteReceive | (0x80 i);}MySPI_W_SCK(0);}return ByteReceive; }交换一个字节(模式0) CPOL0空闲状态时SCK为低电平 CPHA0SCK第一个边沿移入数据第二个边沿移出数据 交换一个字节的时序这里用的是模式0。起始信号之后先立刻将数据的最高位B7移出然后在SCK的第一个上升沿后读入B7然后在SCK的第一个下降沿移出次高位B6然后在SCK的第二个上升沿读入B6然后在SCK的第二个下降沿移出B5…如此循环8次最终在SCK的第八个上升沿读入B0完成一个字节的交换。 至于关于代码部分的按位与(提取字节中的每一位)和按位或(设置字节中的某位)以及左移、右移操作的解析在我之前的一篇文章里已经详细地分析过了如果有不懂的就翻回去看看就行了这里就不再累述了。 文章传送门计算机常见运算之左移操作、右移操作以及按位与、按位或 3.2 W25Q64模块 W25Q64模块主要由模块初始化函数、写使能、页编程(写入数据)、读取数据、忙等待、读取ID号以及扇区擦除等模块组成。 W25Q64模块初始化函数 void W25Q64_Init(void) {MySPI_Init(); }调用MySPI_Init()函数完成引脚配置和SPI的初始化。 写使能 void W25Q64_WriteEnable(void) {MySPI_Start();MySPI_SwapByte(W25Q64_WRITE_ENABLE);// 发送写使能命令MySPI_Stop(); }发送写使能命令以允许后续的写入或擦除操作。 页编程(写入数据) void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count) {uint16_t i;W25Q64_WriteEnable(); // 写使能MySPI_Start();MySPI_SwapByte(W25Q64_PAGE_PROGRAM); // 发送页编程命令MySPI_SwapByte(Address 16); // 发送地址高8位MySPI_SwapByte(Address 8); // 发送地址中8位MySPI_SwapByte(Address); // 发送地址低8位for (i 0; i Count; i ) { // 发送要写入的数据MySPI_SwapByte(DataArray[i]);}MySPI_Stop();W25Q64_WaitBusy(); // 等待存储器空闲 }页编程操作首先通过W25Q64_WriteEnable()函数启用写操作然后发送页编程命令W25Q64_PAGE_PROGRAM接着发送地址并逐字节将数据写入存储器。 关于依次提取3字节24位中的每一个字节的问题有几点要注意一下假设我传入的地址是Address 0x123456那么我们就需要依次发送0x12、0x34、0x56那如何提取呢 我们可以这样操作 原始值Address0x123456 0001 0010 0011 0100 0101 0110 右移十六位— 0x12 0000 0000 0000 0000 0001 0010 右移八位— 0x1234 0000 0000 0001 0010 0011 0100 可以看到如果是右移八位那么得到的是0x1234但是我们想要的是0x34才对啊但其实代码里这样写也是没问题的因为MySPI_SwapByte函数的形参是uint8_t传入0x1234就只会接收低八位的0x34但是这样的话理解起来就有点那啥了。 其实我们还可以这样做直接右移以后再做个按位与操作就可以了比如MySPI_SwapByte((Address 8) 0xFF);这样就直接得到0x34了当然第三位也需要执行按位与操作MySPI_SwapByte(Address 0xFF); 两种方法都可以我这里只是提一下。 读数据 void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count) {uint32_t i;MySPI_Start();MySPI_SwapByte(W25Q64_READ_DATA); // 发送读取数据命令MySPI_SwapByte(Address 16); // 发送地址高8位MySPI_SwapByte(Address 8); // 发送地址中8位MySPI_SwapByte(Address); // 发送地址低8位for (i 0; i Count; i ) { // 读取数据DataArray[i] MySPI_SwapByte(W25Q64_DUMMY_BYTE);}MySPI_Stop(); }读取数据命令W25Q64_READ_DATA发送要读取的地址然后通过SPI逐字节读取指定数量的数据到DataArray中。 忙等待 void W25Q64_WaitBusy(void) {uint32_t Timeout;MySPI_Start();MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);// 读取状态寄存器1Timeout 100000;while ((MySPI_SwapByte(W25Q64_DUMMY_BYTE) 0x01) 0x01){// 检查忙标志位Timeout --;if (Timeout 0){break;}}MySPI_Stop(); }发送读取状态寄存器1命令进入循环等待存储器空闲即状态寄存器的最低位变为0避免在存储器仍处于忙碌时进行新的操作。 读厂商、设备ID void W25Q64_ReadID(uint8_t *MID, uint16_t *DID) {MySPI_Start(); // 片选低电平开始通信MySPI_SwapByte(W25Q64_JEDEC_ID); // 发送读取ID命令*MID MySPI_SwapByte(W25Q64_DUMMY_BYTE); // 接收制造商ID*DID MySPI_SwapByte(W25Q64_DUMMY_BYTE); // 接收设备ID高8位*DID 8;*DID | MySPI_SwapByte(W25Q64_DUMMY_BYTE); // 接收设备ID低8位MySPI_Stop(); // 片选高电平结束通信 }首先调用MySPI_Start()开始SPI通信然后发送读取设备ID命令W25Q64_JEDEC_ID。随后通过MySPI_SwapByte函数接收制造商ID和设备ID。制造商IDMID为一个字节设备IDDID为两个字节。 扇区擦除 void W25Q64_SectorErase(uint32_t Address) {W25Q64_WriteEnable(); // 写使能MySPI_Start();MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB); // 发送扇区擦除命令MySPI_SwapByte(Address 16); // 发送地址高8位MySPI_SwapByte(Address 8); // 发送地址中8位MySPI_SwapByte(Address); // 发送地址低8位MySPI_Stop();W25Q64_WaitBusy(); // 等待存储器空闲 }扇区擦除命令W25Q64_SECTOR_ERASE_4KB用于擦除特定地址所在的扇区地址通过三次发送高、中、低8位地址来指定。 3.3 主程序 主程序整体代码逻辑大概是首先读取从机的ID信息并显示在OLED屏幕上然后执行一个扇区擦除操作接着在该扇区中写入4个字节的数据最后将写入的数据读取出来并在OLED上显示。 #include stm32f10x.h // Device header #include Delay.h #include OLED.h #include W25Q64.huint8_t MID;// 制造商ID (Manufacturer ID) uint16_t DID;// 设备ID (Device ID)uint8_t ArrayWrite[] {0x01, 0x02, 0x03, 0x04}; uint8_t ArrayRead[4];int main(void) {// 硬件初始化OLED_Init();W25Q64_Init();OLED_ShowString(1, 1, MID: DID:);OLED_ShowString(2, 1, W:);OLED_ShowString(3, 1, R:);// 读取并显示W25Q64的ID信息W25Q64_ReadID(MID, DID);OLED_ShowHexNum(1, 5, MID, 2);OLED_ShowHexNum(1, 12, DID, 4);// 擦除W25Q64的一个扇区并写入数据W25Q64_SectorErase(0x000000);W25Q64_PageProgram(0x000000, ArrayWrite, 4);// 读取数据并显示W25Q64_ReadData(0x000000, ArrayRead, 4);OLED_ShowHexNum(2, 3, ArrayWrite[0], 2);OLED_ShowHexNum(2, 6, ArrayWrite[1], 2);OLED_ShowHexNum(2, 9, ArrayWrite[2], 2);OLED_ShowHexNum(2, 12, ArrayWrite[3], 2);OLED_ShowHexNum(3, 3, ArrayRead[0], 2);OLED_ShowHexNum(3, 6, ArrayRead[1], 2);OLED_ShowHexNum(3, 9, ArrayRead[2], 2);OLED_ShowHexNum(3, 12, ArrayRead[3], 2);while (1){} }
http://www.w-s-a.com/news/76607/

相关文章:

  • 优秀网站开发商郑州网站建设套餐
  • 做伤残鉴约号网站购物网站建设新闻
  • 黄江网站建设公司自己房子做民宿挂什么网站
  • 手游网站做cpc还是cpm广告号宣武郑州阳网站建设
  • vs连接数据库做网站建立网站
  • 电商网站设计图片素材p2p网站建设石家庄
  • 莲塘网站建设如何文字推广一个婚恋网站
  • 医院网站建设工作汇报WordPress不发邮件了
  • 怎么做外语网站个人网页设计作品ps
  • 网站原型怎么做vps如何建两个网站
  • 商城网站建设源码嘉兴seo计费管理
  • 城乡建设网站证件查询系统wordpress 时间代码
  • php网站建设 关键技术做网站哪家正规
  • 网站开发用什么写得比较好谷歌的英文网站
  • 青岛网站建设公司在哪vivo手机商城
  • 兼职刷客在哪个网站做哪个网站做淘宝客
  • 眼科医院网站开发网络营销特点是什么
  • 提交网站给百度增加wordpress插件
  • 网站建设企业官网体验版是什么Wordpress哪个模板最快
  • 美丽说网站模板湖北可以做网站方案的公司
  • 北京西站进站最新规定建设网站的提成是多少
  • wordpress站点如何加速网站建设描述怎么写
  • 如何免费建造网站免费vi模板网站
  • 商丘做网站多少钱扬州大发网站建设
  • 网站建设哪家性价比高自己做项目的网站
  • 成立一个网站济宁营销型网站建设
  • 南通购物网站建设设计类平台网站
  • 专业网站建设咨询thinkphp网站源码下载
  • 怎么制作一个国外网站网站推广找哪家公司好
  • 免费做网站怎么做网站想在网上卖东西怎么注册