6、stroge模块和按键模块

6、stroge模块和按键模块6 1 存储模块 存储模块使用的是 P25Q32H 封装 USON3 2 引脚定义如下所示 该芯片共有 64 个块 每块 16 个扇区 每扇区 4KB 合计 4MB 通信方式采用标准的 4 线 SPI 通讯 具体配置如下所示 该芯片的驱动程序和 W25QXX 系列基本一致

大家好,我是讯享网,很高兴认识大家。
6.1、存储模块

存储模块使用的是P25Q32H,封装USON3*2,引脚定义如下所示。
在这里插入图片描述
讯享网

具体配置如下所示
在这里插入图片描述
该芯片的驱动程序和W25QXX系列基本一致,移植于之前的W25Q128驱动,主要内容几乎没变化。

#ifndef __SPI_FLASH__H #define __SPI_FLASH__H #include "spi.h" typedef enum { 
    SPI_FLASH_OK = 0, SPI_FLAHS_BUSY = 1, SPI_FLASH_TIMEOUT = 2, SPI_FLASH_ERR = 3, SPI_FLASH_UNKNOW }spi_flash_status_t; #define P25Q32H_Enable() HAL_GPIO_WritePin(F_CS_GPIO_Port, F_CS_Pin, GPIO_PIN_RESET) #define P25Q32H_Disable() HAL_GPIO_WritePin(F_CS_GPIO_Port, F_CS_Pin, GPIO_PIN_SET) #define PRINTF_DEBUG rt_kprintf #define P25Q32H_REMS 0x8515  #define P25Q32H_RDID 0x #define P25Q32H_FLASH_SIZE (P25Q32H_SECTOR_SIZE*64) //4MB #define P25Q32H_SECTOR_SIZE (P25Q32H_SUBSECTOR_SIZE*16) #define P25Q32H_SUBSECTOR_SIZE (4096) #define P25Q32H_PAGE_SIZE (256) #define P25Q32H_PAGE_ERASE 0X81 #define P25Q32H_SECTOR_ERASE 0X20 #define P25Q32H_BLOCK_32K_ERASE 0X52 #define P25Q32H_BLOCK_64K_ERASE 0XD8 #define P25Q32H_CHIP_ERASE 0X60 #define P25Q32H_READ_BYTE 0X03 #define P25Q32H_READ_QUICK_BYTE 0X0B  #define P25Q32H_WRITE_PGAE_PROGRAM 0X02 #define P25Q32H_WRITE_ENABLE 0X06 #define P25Q32H_WRITE_DISABLE 0X04 #define P25Q32H_READ_STATU_REG 0X05 #define P25Q32H_READ_CONFIG_REG 0X35 #define P25Q32H_WRITE_STATU_RES 0X01 #define P25Q32H_WRITE_CONFIG_RES 0X11 #define P25Q32H_RESET_ENABLE 0X66 #define P25Q32H_RESET 0X99 #define P25Q32H_READ_DEV_ID 0X9F #define P25Q32H_READ_EMS_ID 0X90 #define P25Q32H_DEEP_POWER_DOWN 0XB9 #define P25Q32H_RELEASE_PWOER_DOWN 0XAB #define SR_WIP_BUSY_BIT (0X0001) #define SR_WEL_ENABLE_BIT (0X0002) #define SR_BLOCK1_4_ENABLE_BIT (0X007C) #define SR_SRP0_1_ENABLE_BIT (0X0180) #define SR_QUAD_SPI_ENABLE_BIT (0X0200) #define SR_SUS2_BIT (0X0400) #define SR_LB1_3_BIT (0X3800) #define SR_CMP_BIT (0X4000) #define SR_SUS1_BIT (0X8000) uint8_t BSP_P25Q30H_Init(void); void BSP_P25Q32H_Write(uint8_t* _p_buff,uint32_t _ui_addr,uint16_t _us_num); uint8_t BSP_P25Q32H_Read(uint8_t *_p_buff,uint32_t _uc_addr,uint32_t _uc_num); void BSP_P25Q32H_EraseSector(uint32_t _ui_addr); void BSP_P25Q32H_EarseChip(void); void BSP_P25Q32H_PowerDown(void) ; void BSP_P25Q32H_WAKEUP(void) ; void BSP_P25Q32H_TestProcess(void); #endif 

讯享网
讯享网#include "spi_flash.h" #define DUMMY_BYTE 0xFF uint8_t SPI_FLASH_ReadWriteByte(uint8_t _uc_byte) { 
    uint8_t uc_read,uc_send=_uc_byte; if (HAL_SPI_TransmitReceive(&hspi2,&uc_send,&uc_read,1,100)!=HAL_OK) uc_read = 0X55; return uc_read; } uint32_t BSP_P25Q30H_ReadDevID(void) { 
    uint32_t ui_temp = 0; P25Q32H_Enable(); SPI_FLASH_ReadWriteByte(P25Q32H_READ_DEV_ID);//发送读取ID命令  ui_temp|=SPI_FLASH_ReadWriteByte(DUMMY_BYTE)<<16; ui_temp|=SPI_FLASH_ReadWriteByte(DUMMY_BYTE)<<8; ui_temp|=SPI_FLASH_ReadWriteByte(DUMMY_BYTE); P25Q32H_Disable(); return ui_temp; } uint32_t BSP_P25Q30H_ReadID(void) { 
    uint32_t ui_temp = 0; P25Q32H_Enable(); SPI_FLASH_ReadWriteByte(P25Q32H_READ_EMS_ID);//发送读取ID命令  SPI_FLASH_ReadWriteByte(0); SPI_FLASH_ReadWriteByte(0); SPI_FLASH_ReadWriteByte(0); ui_temp |= SPI_FLASH_ReadWriteByte(DUMMY_BYTE)<<8; ui_temp |= SPI_FLASH_ReadWriteByte(DUMMY_BYTE); P25Q32H_Disable(); return ui_temp; } uint32_t P25Q30H_ID = 0; uint8_t BSP_P25Q30H_Init(void) { 
    spi_flash_status_t res = SPI_FLASH_OK; P25Q30H_ID = BSP_P25Q30H_ReadID(); if(P25Q30H_ID != P25Q32H_REMS) { 
    res = SPI_FLASH_ERR; } P25Q30H_ID = BSP_P25Q30H_ReadDevID(); if(P25Q30H_ID != P25Q32H_RDID) { 
    res = SPI_FLASH_ERR; } else { 
    res = SPI_FLASH_OK; } return res; } /* BIT0: wip 1:正在操作 BIT1: WEL 1:写保护 BIT2-6: BP0_BP4 块保护 BIT7-8: SRP0_1 状态寄存器保护 BIT9: QE quad spi 使能位 BIT10: SUS2 program suspend 将会把该位置1(only read) BIT11-13:LB1-3 OTP区相关 BIT14: CMP BIT15: SUS1 erase_suspend 将会把该位置1(only read) */ uint16_t BSP_P25Q32H_ReadSR(void) { 
    uint16_t us_byte=0; P25Q32H_Enable(); //使能器件  SPI_FLASH_ReadWriteByte(P25Q32H_READ_STATU_REG); //发送读取状态寄存器命令  us_byte |= SPI_FLASH_ReadWriteByte(0Xff); //读取一个字节  P25Q32H_Disable(); //取消片选  return us_byte; } uint8_t BSP_P25Q32H_WaitBusy(void) { 
    return (BSP_P25Q32H_ReadSR()&0X01); } uint8_t BSP_P25Q32H_WriteSR(uint8_t _uc_reg) { 
    return 0; } uint8_t BSP_P25Q32H_WriteEnable(void) { 
    P25Q32H_Enable(); SPI_FLASH_ReadWriteByte(P25Q32H_WRITE_ENABLE); P25Q32H_Disable(); return 0; } uint8_t BSP_P25Q32H_WriteDisable(void) { 
    P25Q32H_Enable(); SPI_FLASH_ReadWriteByte(P25Q32H_WRITE_DISABLE); P25Q32H_Disable(); return 0; } void BSP_P25Q32H_EraseSector(uint32_t _ui_addr) { 
    //监视falsh擦除情况,测试用  // printf("fe:%x\r\n",Dst_Addr);  _ui_addr*=P25Q32H_SUBSECTOR_SIZE; BSP_P25Q32H_WriteEnable(); //SET WEL  BSP_P25Q32H_WaitBusy(); P25Q32H_Enable(); //使能器件  SPI_FLASH_ReadWriteByte(P25Q32H_SECTOR_ERASE); //发送扇区擦除指令  SPI_FLASH_ReadWriteByte((uint8_t)((_ui_addr)>>16)); //发送24bit地址  SPI_FLASH_ReadWriteByte((uint8_t)((_ui_addr)>>8)); SPI_FLASH_ReadWriteByte((uint8_t)_ui_addr); P25Q32H_Disable(); //取消片选  BSP_P25Q32H_WaitBusy(); //等待擦除完成 } uint8_t BSP_P25Q32H_Read(uint8_t *_p_buff,uint32_t _uc_addr,uint32_t _uc_num) { 
    uint16_t i = 0; spi_flash_status_t res = SPI_FLASH_OK; P25Q32H_Enable(); SPI_FLASH_ReadWriteByte(P25Q32H_READ_BYTE); SPI_FLASH_ReadWriteByte((uint8_t)(_uc_addr >> 16)); SPI_FLASH_ReadWriteByte((uint8_t)(_uc_addr >> 8)); SPI_FLASH_ReadWriteByte((uint8_t)(_uc_addr >> 0)); for(i=0;i<_uc_num;i++) { 
    _p_buff[i]=SPI_FLASH_ReadWriteByte(DUMMY_BYTE); //循环读数  } P25Q32H_Disable(); return res; } uint8_t BSP_P25Q32H_WritePage(uint8_t *_p_buff,uint32_t _uc_addr,uint32_t _uc_num) { 
    uint16_t i = 0; spi_flash_status_t res = SPI_FLASH_OK; BSP_P25Q32H_WriteEnable(); P25Q32H_Enable(); SPI_FLASH_ReadWriteByte(P25Q32H_WRITE_PGAE_PROGRAM); SPI_FLASH_ReadWriteByte((uint8_t)((_uc_addr&0XFF0000)>>16)); SPI_FLASH_ReadWriteByte((uint8_t)((_uc_addr&0X00FF00)>>8)); SPI_FLASH_ReadWriteByte((uint8_t)((_uc_addr&0X0000FF)>>0)); for(i=0;i<_uc_num;i++) { 
    SPI_FLASH_ReadWriteByte(_p_buff[i]); } P25Q32H_Disable(); BSP_P25Q32H_WaitBusy(); return res; } void BSP_P25Q32H_WriteNoCheck(uint8_t* _p_buff,uint32_t _ui_addr,uint16_t _us_num) { 
    uint16_t pageremain; pageremain = P25Q32H_PAGE_SIZE - _ui_addr % P25Q32H_PAGE_SIZE; if(_us_num<=pageremain) pageremain=_us_num; while(1) { 
    BSP_P25Q32H_WritePage(_p_buff,_ui_addr,pageremain); if(_us_num==pageremain)break; //写入结束了 else //NumByteToWrite>pageremain { 
    _p_buff+=pageremain; _ui_addr+=pageremain; _us_num-=pageremain; //减去已经写入了的字节数 if(_us_num > P25Q32H_PAGE_SIZE) pageremain = P25Q32H_PAGE_SIZE; //一次可以写入256个字节 else pageremain = _us_num; //不够256个字节了 } } } uint8_t BSP_P25Q32H_BUFFER[P25Q32H_SUBSECTOR_SIZE]; void BSP_P25Q32H_Write(uint8_t* _p_buff,uint32_t _ui_addr,uint16_t _us_num) { 
    uint32_t secpos; uint16_t secoff; uint16_t secremain; uint16_t i; uint8_t * p_buf; p_buf=BSP_P25Q32H_BUFFER; secpos = _ui_addr / P25Q32H_SUBSECTOR_SIZE;//扇区地址  secoff = _ui_addr % P25Q32H_SUBSECTOR_SIZE;//在扇区内的偏移 secremain = P25Q32H_SUBSECTOR_SIZE - secoff;//扇区剩余空间大小  if(_us_num<=secremain)secremain=_us_num;//不大于4096个字节 while(1) { 
    BSP_P25Q32H_Read(p_buf,secpos*P25Q32H_SUBSECTOR_SIZE,P25Q32H_SUBSECTOR_SIZE);//读出整个扇区的内容 for(i=0;i<secremain;i++)//校验数据 { 
    if(p_buf[secoff+i]!=0XFF)break;//需要擦除  } if(i<secremain)//需要擦除 { 
    BSP_P25Q32H_EraseSector(secpos); //擦除这个扇区 for(i=0;i<secremain;i++) //复制 { 
    p_buf[i+secoff]=_p_buff[i]; } BSP_P25Q32H_WriteNoCheck(p_buf,secpos*P25Q32H_SUBSECTOR_SIZE,P25Q32H_SUBSECTOR_SIZE);//写入整个扇区  }else BSP_P25Q32H_WriteNoCheck(_p_buff,_ui_addr,secremain);//写已经擦除了的,直接写入扇区剩余区间.  if(_us_num==secremain)break;//写入结束了 else//写入未结束 { 
    secpos++;//扇区地址增1 secoff=0;//偏移位置为0  _p_buff+=secremain; //指针偏移 _ui_addr+=secremain; //写地址偏移  _us_num-=secremain; //字节数递减 if(_us_num>4096)secremain=4096;//下一个扇区还是写不完 else secremain=_us_num; //下一个扇区可以写完了 } }; } void BSP_P25Q32H_EarseChip(void) { 
    BSP_P25Q32H_WriteEnable(); //SET WEL  BSP_P25Q32H_WaitBusy(); P25Q32H_Enable(); SPI_FLASH_ReadWriteByte(P25Q32H_CHIP_ERASE); //发送片擦除命令  P25Q32H_Disable(); BSP_P25Q32H_WaitBusy(); //等待芯片擦除结束 } //进入掉电模式 void BSP_P25Q32H_PowerDown(void) { 
    P25Q32H_Enable(); //使能器件  SPI_FLASH_ReadWriteByte(P25Q32H_DEEP_POWER_DOWN); //发送掉电命令  P25Q32H_Disable(); //取消片选  } //唤醒 void BSP_P25Q32H_WAKEUP(void) { 
    P25Q32H_Enable(); //使能器件  SPI_FLASH_ReadWriteByte(P25Q32H_RELEASE_PWOER_DOWN); // send W25X_PowerDown command 0xAB  P25Q32H_Disable(); //取消片选  } void BSP_P25Q32H_TestProcess(void) { 
    // uint8_t res = SPI_FLASH_OK; // res = BSP_P25Q30H_Init(); // if(res == SPI_FLASH_OK) // { 
    // BSP_P25Q32H_Write(&w_buff[0],0,sizeof(w_buff)); //从倒数第100个地址处开始,写入SIZE长度的数据 // HAL_Delay(100); // BSP_P25Q32H_Read(&r_buff[0],0,100); // HAL_Delay(100); // } } 

后续的存储线程只需要调用这里面的读写函数就可以了。比较简单,参考W25QXX系列驱动和本芯片datasheet即可。

6.2、按键模块

在这里插入图片描述

一共是7种触发按键的事件。其中,双击按键,长按时间都是通过修改文件内的宏定义修改时间的,但是LONG_PRESS_HOLD这个事件的触发间隔确实写死的(一个button_ticks出发一次)。这不符合我的要求,于是将头文件内部宏定义修改为如下所示。

#define TICKS_INTERVAL 5 //ms //心跳间隔 #define DEBOUNCE_TICKS (20/TICKS_INTERVAL) //MAX 8次 40ms 滤波时间 #define SHORT_TICKS (200 /TICKS_INTERVAL) //双击的时间间隔 #define LONG_TICKS (500 /TICKS_INTERVAL) //长按的时间判断 #define LONG_HOLD_EVENT (200/TICKS_INTERVAL) //触发长按后,多长时间触发一次LONG_PRESS_HOLD事件 

之后在button_handler()函数添加如下内容。
在这里插入图片描述到这对于LONG_PRESS_HOLD事件的修改就做完了。

小讯
上一篇 2025-01-15 13:48
下一篇 2025-03-17 19:04

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/121735.html