如何利用DW在网站首页制作导航栏并发布网上公告?

摘要:在dw上做网站首页导航栏,做网站网上怎么挂公告,哈尔滨专业建站免费咨询,网站头部怎样做有气势当使用单片机进行项目开发,涉及大量数据需要储存时(例如使用了屏幕作为显示设备&a
在dw上做网站首页导航栏,做网站网上怎么挂公告,哈尔滨专业建站免费咨询,网站头部怎样做有气势当使用单片机进行项目开发#xff0c;涉及大量数据需要储存时#xff08;例如使用了屏幕作为显示设备#xff0c;常常需要存储图片、动画等数据#xff09;#xff0c;单靠单片机内部的Flash往往是不够用的。 如STM32F103系列#xff0c;内部Flash最多只能达到512KByte涉及大量数据需要储存时例如使用了屏幕作为显示设备常常需要存储图片、动画等数据单靠单片机内部的Flash往往是不够用的。 如STM32F103系列内部Flash最多只能达到512KByte假设要储存240*240分辨率、64K彩色图片只够存储4张左右。如果使用外置储存器将图片等其他数据放置在外置储存器内部Flash只储存程序就能减小内部Flash的需求降低成本。              Flash种类有很多按其制程和制作工艺的不同可分为NOR Flash、NAND Flash。NAND的串行结构使得其容量很容易做的很大SD卡、U盘、硬盘大都采用该类Flash但是其读取速度却比不上并行结构的NOR Flash且可靠性要差些一旦出现数据块坏点是不可逆、无法修复的。由于其数据存储原理Flash在写入新的数据之前都需要将数据地址所在的块擦除NOR Flash的擦除速度比NAND慢很多。 Flash按其数据传输方式的不同可分为并口传输与串口传输。STM32的并口传输需使用FSMC接口虽然其读写速度很快但对于100PIN脚以下的封装是不带FSMC功能的。 所以使用更多的是串口传输方式。串口方式一般采用的是SPI通讯。 W25Q系列Flash是Winbond台湾华邦科技生产的SPI Flash系列是单片机开发中比较常用的外置Flash。其支持标准四线SPI、Dual SPI、Quad SPI、QPI其时钟频率分别可达到104MHz、208MHz、416MHz。对于STM32F103系列其主频最高72MHzSPI通信速率最高18Mbps所以标准SPI就已经是足够F103系列单片机使用了。这里我使用W25Q128FV来讲解Flash的使用。 先来了解其引脚定义上面展示的是SOP8封装还有SOP16封装的功能都是差不多的。 /CS: Flash的片选引脚。当/CS高时Flash的串行数据输出(DO或IO0、IO1、IO2、IO3)引脚处于高阻抗此时设备功耗将处于待机水平除非正在进行内部擦除、程序或写入状态寄存器周期。当/CS为低电平Flash将被选中功耗将增加到活动水平并且可以向该设备写入指令和从该设备读取数据。启动后/CS必须从高电平转换到低电平才能接受新的指令。 DO(IO1):DO指数据输出口(Data Out)一般连接到单片机SPI接口的数据输入端即MISO。IO1是其复用功能当启用SPI四位传输模式时该引脚功能为IO1. /WP:写保护(WP)引脚。可以用来防止状态寄存器被写入。与状态寄存器的块保护(CMP, SEC, TB, BP2, BP1和BPO)位和状态寄存器保护(SRP)位一起使用小到4KB扇区或整个内存阵列都可以被硬件保护。/WP引脚低电平有效。当状态寄存器2的QE位设置为Quad I/O时/WP引脚功能不可用因为该引脚用于IO2。如果不想使用该功能可以直接将该引脚接VCC。 GND:Flash的供电GND DI:DI指数据输入口(Data In)一般连接到单片机SPI接口的数据输出端即MOSI。IO0是其复用功能当启用SPI四位传输模式时该引脚为IO0 CLK:SPI时钟线。连接至单片机的SPI时钟接口。 /HOLD/RESET:/HOLD能让设备主动暂停数据传输。当/HOLD低时而/CS低时DO引脚将处于高阻抗Dl和CLK引脚上的信号将被忽略。当/HOLD调高时设备可以恢复运行。当多个设备共享相同的SPl信号时/HOLD就能发挥作用。 /RESET引脚用于设备复位。注意如果在写入数据时复位可能会造成数据丢失。所以如果不需要给Flash复位该引脚常常直接与VCC相接。 VCC:Flash供电电源3.3V。 不管何种存储器在进行数据读写时都需要知道数据的地址。数据存储在寄存器中所以数据的地址即寄存器地址。我们来看看W25Q128的内部原理图。 其内部是由数据存储单元和各种控制器组成。 存储单元的最小单位为一个寄存器每个寄存器可存储1个字节的数据。 每256个寄存器组成一页(Page)也就是一页能存储256Byte数据 每16页组成一个扇区(Sector)一个扇区能储存16x2564096Byte数据(近似4KB)。比如扇区0的数据地址范围为000000 h-0000FF h。 每16个扇区又组成一个块(Block)一个块能储存4096x1665536Byte数据(近似64K)。例如块0的数据地址范围为000000 h-000FFF h 。 整个存储单元共256个块所以其总存储容量为256x6553616777216Byte数据近似为16MByte。数据地址范围为000000 h-FFFFFF h。 不管何种外设都是通过发送命令与数据来控制的。Flash也不例外所以需要知道如何使用Flash只需在其技术手册上找到其命令表即可。 可用的命令有很多但常用的就一部分。 现在我们来讲解程序里如何实现STM32F103读写SPI Flash的数据。 这里我使用的是SPI2硬件连接如下。 再来看程序部分 1.SPI2初始化。为了将读出来的数据显示出来这里我使用串口将数据传输到电脑上。所以对usart1也初始化。 void SPI2_UserInit(void) {GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB的时钟GPIO_InitStructure.GPIO_Pin GPIO_Pin_13|GPIO_Pin_15; //PA13为SCK时钟PA15为MISOGPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //速度50MHzGPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOB, GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin GPIO_Pin_14; //PA14为MISOGPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //速度50MHzGPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOB, GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin GPIO_Pin_12; //PA12为片选GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //速度50MHzGPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //复用推挽输出GPIO_Init(GPIOB, GPIO_InitStructure);SPI_InitTypeDef SPI_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); //使能SPI时钟SPI_InitStructure.SPI_Direction SPI_Direction_2Lines_FullDuplex;//设置双向双线全双工SPI_InitStructure.SPI_Mode SPI_Mode_Master; //设置为SPI主站SPI_InitStructure.SPI_DataSize SPI_DataSize_8b; //设置为8位帧结构SPI_InitStructure.SPI_CPOL SPI_CPOL_High; //串行时钟的稳态为时钟高SPI_InitStructure.SPI_CPHA SPI_CPHA_2Edge; //位捕获的时钟活动沿为第1个时钟沿SPI_InitStructure.SPI_NSS SPI_NSS_Soft; //指定NSS信号由软件控制SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_2; //波特率预分频值SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB; //数据位从MSB开始SPI_InitStructure.SPI_CRCPolynomial 7; //CRC检验SPI_Init(SPI2, SPI_InitStructure); //按以上设置初始化SPI2SPI_Cmd(SPI2, ENABLE); //使能SPI2GPIO_SetBits(GPIOB,GPIO_Pin_12); //CS置高 }void USART1_Userinit(void) {GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; //PA9为USART1_TX将这个GPIO初始化GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //速度50MHzGPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; //复用推挽输出GPIO_Init(GPIOA, GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; //PA10为USART_RX将这个GPIO初始化GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //速度50MHzGPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOA, GPIO_InitStructure);USART_InitTypeDef USART_InitStructure; //定义USART配置结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //打开USART1时钟USART_InitStructure.USART_BaudRate 115200; //波特率USART_InitStructure.USART_WordLength USART_WordLength_8b; //数据帧位数 USART_InitStructure.USART_StopBits USART_StopBits_1; //停止位数目USART_InitStructure.USART_Parity USART_Parity_No; //奇偶模式(USART_Parity_No 无,USART_Parity_Even 偶SART_Parity_Odd奇USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; //硬件流控制模式USART_InitStructure.USART_Mode USART_Mode_Tx| USART_Mode_Rx; //发送、接收使能USART_Init(USART1, USART_InitStructure); //初始化USART_Cmd(USART1,ENABLE); //使能USART1串口 USART_ITConfig(USART1,USART_IT_RXNE, ENABLE); //使能USART1接收中断NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel USART1_IRQn; //中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority3; //抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority 3; //子优先级NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; //使能中断NVIC_Init(NVIC_InitStructure); //初始化中断} 2.发送命令或者读写数据都是通过最基本的发送数据、接受数据函数来实现。为了不出现数据丢失每次发送数据前都需要判断上次发送的数据是否已经发送玩这可以通过相关标志位来判断;同样为了不出现数据重复每次接收数据前都要判断接收缓存区是否为空。 void Flash_WriteData8(u8 Data) //写8位数据1个字节 {u8 Wait0; while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) RESETWait20) //检查指定的SPI标志位设置与否:发送缓存空标志位RESET表示正在发送数据{Wait;//循环计数200计数200此大概20us不管是否标志位为空都退出等待}SPI_I2S_ClearFlag(SPI2, SPI_I2S_FLAG_TXE); //清除发送完成标志位SPI_I2S_SendData(SPI2,Data); //发送Data}u8 Flash_ReadData( ) //读一个字节 { u8 Wait0;SPI_I2S_SendData(SPI2,0xff); //发送0x00产生时钟信号用来接收数据也可以发送其他无响应的命令while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) RESETWait200) //检查指定的SPI标志位设置与否:接受缓存非空标志位{Wait; } SPI_I2S_ClearFlag(SPI2, SPI_I2S_FLAG_RXNE); //清除标志位return SPI_I2S_ReceiveData(SPI2); //返回通过SPI2最近接收的数据 } 需要注意在接受数据的函数中之所以在SPI_I2S_ReceiveData(SPI2)函数之前要使用SPI_I2S_SendData(SPI2,0xff)函数是为了产生时钟信号。 SPI采用的是主从通信结构时钟信号只能由主设备产生主设备发送数据的过程中会产生时钟信号但是从设备发送数据时并不能自己产生时钟信号所以就无法将数据一位一位发送出去同步通信必须依靠时钟信号保持时序一致那就只能依靠主设备产生时钟信号。主设备发送的0xFF对从设备来说是无效的数据不会对该数据做出响应但是主设备发送0xFF这个数据的时候产生了时钟信号所以从设备就依靠这段时钟信号将数据发送给了主设备主设备接受会暂存在接收缓存寄存器中等接受到新的数据自动更新缓存器。 具体的通信时序可查阅W25Q128的技术手册W25Q128FV_PDF_数据手册_Datasheet这里就不一一列举了。 3.把W25Q128常用的命令封装成函数只要调用对应的函数就能实现命令的发送与数据的读写 #define Flash_CS_H() GPIO_SetBits(GPIOB,GPIO_Pin_12) //Flash 片选信号 #define Flash_CS_L() GPIO_ResetBits(GPIOB,GPIO_Pin_12) //低电平选中高电平取消选中/*****W25Q128常用命令定义*****/ #define W25X_WriteEnable 0x06 //写使能 #define W25X_WriteDisable 0x04 //写失能 #define W25X_ReadStatusReg 0x05 //读控制寄存器 #define W25X_WriteStatusReg 0x01 //写控制寄存器 #define W25X_ReadData 0x03 //写数据 #define W25X_FastReadData 0x0B //快速写数据 #define W25X_FastReadDual 0x3B // #define W25X_PageProgram 0x02 //页编程 #define W25X_BlockErase32 0x52 //32K块擦除 #define W25X_BlockErase64 0xD8 //64K块擦除 #define W25X_SectorErase 0x20 //4k扇区擦除 #define W25X_ChipErase 0xC7 //整片擦除 #define W25X_PowerDown 0xB9 // #define W25X_ReleasePowerDown 0xAB #define W25X_DeviceID 0xAB //读设备ID #define W25X_ManufactDeviceID 0x90 #define W25X_JedecDeviceID 0x9F //读取JEDECIDu8 Flash_ReadSR(void) //读状态寄存器 { u8 Byte0;Flash_CS_L(); //CS选中Flash_WriteData8(W25X_ReadStatusReg); //发送读取状态寄存器命令 ByteFlash_ReadData(); //读取一个字节 Flash_CS_H(); //CS取消选中return Byte; } void Flash_Write_SR(u8 Sr) { Flash_WriteData8(W25X_WriteStatusReg); //发送写状态寄存器命令 Flash_WriteData8(Sr); //写入一个字节 } void Flash_Write_Enable(void) //使能写入 { Flash_CS_L();Flash_WriteData8(W25X_WriteEnable); //发送写使能Flash_CS_H(); } void Flash_Write_Disable(void) //禁止写入 { Flash_WriteData8(W25X_WriteDisable); //发送写禁止指令 }u32 Flash_ReadID(void) //读取设备ID {u32 Temp ; u8 TempL,TempM,TempH; Flash_CS_L();Flash_WriteData8(W25X_JedecDeviceID); //发送读取ID命令 TempHFlash_ReadData(); //接收高8位TempMFlash_ReadData(); //接收中8位TempLFlash_ReadData(); //接收低8位TempTempH;Temp8; //左移8位Temp|TempM; //高8位与低8位合并成16位与运算后赋值Temp8; //左移8位Temp|TempL; //高8位与低8位合并成16位与运算后赋值Flash_CS_H();return Temp; } void Flash_ReadSector(u32 ReadAddr) //读一个扇区 {u16 i; Flash_WriteData8(W25X_ReadData); //发送读取命令 Flash_WriteData8((ReadAddr16)0xff); //发送24bit地址 Flash_WriteData8((ReadAddr8)0xff); Flash_WriteData8(ReadAddr0xff); for(i0;i4096;i) //一个扇区4096个Byte{ ARR2[i]Flash_ReadData(); //循环读取每个字节} }void Flash_EraseSector(u32 Dst_Addr) //擦除扇区 { Flash_Write_Enable(); //SET WEL while((Flash_ReadSR()0x01)0x01); // 等待BUSY位清空{}Flash_WriteData8(W25X_SectorErase); //发送扇区擦除指令 Flash_WriteData8((Dst_Addr16)0xff); //发送24bit地址 Flash_WriteData8((Dst_Addr8)0xff); Flash_WriteData8(Dst_Addr0xff); while((Flash_ReadSR()0x01)0x01); // 等待BUSY位清空{} } void Flash_WritePage(u32 WriteAddr,u8 NumByteToWrite) {u8 i; Flash_Write_Enable(); //写使能 Flash_CS_L();Flash_WriteData8(W25X_PageProgram); //发送写页命令 Flash_WriteData8((WriteAddr16)0xff); //发送24bit地址 Flash_WriteData8((WriteAddr8)0xff); Flash_WriteData8(WriteAddr0xff); for(i0;iNumByteToWrite;i){Flash_WriteData8(ARR1[i]);} Flash_CS_H(); }void Flash_WriteByte(u32 WriteAddr,u8 Data) //写入一个字节 {Flash_Write_Enable(); //写使能 Flash_CS_L();Flash_WriteData8(W25X_PageProgram); //发送写页命令 Flash_WriteData8((WriteAddr16)0xff); //发送24bit地址 Flash_WriteData8((WriteAddr8)0xff); Flash_WriteData8(WriteAddr0xff); Flash_WriteData8(Data); Flash_CS_H(); } 4.主函数。先读取设备ID然后将数组ARR1的数据写入Flash的扇区0再将扇区0的数据读取出来放在数组ARR2中通过串口将ARR2的数据显示到电脑串口调试助手。 #includestm32f10x.hu8 ARR1[10]{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A};//随意填入几个元素后面将其元素写入Flash中 u8 ARR2[10]; //后面将Flash的数据读出来复制到该数组中void USART_SendDatatoUSB( char ASCII[]) //串口发送字符串函数 {u8 i,j,Wait;for(i0;i12;i){u8 Wait0; while (USART_GetFlagStatus(USART1, USART_FLAG_TC) RESETWait200) {Wait;//循环计数200计数200此大概20us不管是否标志位为空都退出等待}USART_ClearFlag(USART1,USART_FLAG_TC);jASCII[i];USART_SendData(USART1,j);}Wait0;while (USART_GetFlagStatus(USART1, USART_FLAG_TC) RESETWait200) {Wait;//循环计数200计数200此大概20us不管是否标志位为空都退出等待}USART_ClearFlag(USART1,USART_FLAG_TC);USART_SendData(USART1,10); //换行 }int main() {SPI2_UserInit(); //SPI2初始化----控制SPI FlashUSART1_Userinit(); //USART1初始化--控制串口CH340Flash_Write_Enable(); //Flash写使能USART_SendDatatoUSB( Flash:ID)DataFlash_ReadID(); //读取ID(16位)while (USART_GetFlagStatus(USART1, USART_FLAG_TC) RESET){}USART_SendData(USART1,(Data16)0xFF);while (USART_GetFlagStatus(USART1, USART_FLAG_TC) RESET){}USART_SendData(USART1,(Data8)0xFF);Flash_EraseSector(0x000000); //擦除扇区USART_SendDatatoUSB( 扇区擦除完成);Flash_WritePage(0x000000,10); //写入数据USART_SendDatatoUSB( 数据写入成功);Flash_ReadSector(0x000000) //读数据USART_SendDatatoUSB( 数据读取成功);for(i0;i10;i){u8 Wait0; while (USART_GetFlagStatus(USART1, USART_FLAG_TC) RESETWait200) //检查指定的SPI标志位设置与否:发送缓存空标志位RESET表示正在发送数据{Wait;//循环计数200计数200此大概20us不管是否标志位为空都退出等待}USART_ClearFlag(USART1,USART_FLAG_TC);jARR2[i];USART_SendData(USART1,j);} } 最后接收到数据如下。