STM32——SPI接口

STM32——SPI接口


宗旨:技术的学习是有限的,分享的精神是无限的。


一、SPI协议【SerialPeripheral Interface

        串行外围设备接口,是一种高速全双工的通信总线。在ADC/LCD等与MCU间通信。

1SPI信号线

        SPI 包含 4 条总线,SPI 总线包含 4 条总线,分别为SS 、SCK、MOSI、MISO。

(1)SS(SlaveSelect):片选信号线,当有多个 SPI 设备与 MCU 相连时,每个设备的这个片选信号线是与 MCU 单独的引脚相连的,而其他的 SCK、MOSI、MISO 线则为多个设备并联到相同的 SPI 总线上,低电平有效。

(2)SCK (Serial Clock):时钟信号线,由主通信设备产生,不同的设备支持的时钟频率不一样,如 STM32 的 SPI 时钟频率最大为 f PCLK /2。

(3)MOSI (Master Output, Slave Input):主设备输出 / 从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入数据,即这条线上数据的方向为主机到从机。

(4)MISO(Master Input, Slave Output):主设备输入 / 从设备输出引脚。主机从这条信号线读入数据,从机的数据则由这条信号线输出,即在这条线上数据的方向为从机到主机。

2SPI模式

根据 SPI 时钟极性(CPOL)和时钟相位(CPHA) 配置的不同,分为 4 种 SPI 模式。时钟极性是指 SPI 通信设备处于空闲状态时(也可以认为这是 SPI 通信开始时,即SS 为低电平时),SCK 信号线的电平信号。CPOL=0 时, SCK 在空闲状态时为低电平,CPOL=1 时则相反。时钟相位是指数据采样的时刻,当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的奇数边沿被采样。当 CPHA=1 时,数据线在 SCK 的偶数边沿采样。

首先,由主机把片选信号线SS 拉低,意为主机输出,在SS 被拉低的时刻,SCK 分为两种情况,若我们设置为 CPOL=0,则 SCK 时序在这个时刻为低电平,若设置为 CPOL=1,则 SCK 在这个时刻为高电平。采样时刻都是在 SCK 的奇数边沿(注意奇数边沿有时为下降沿,有时为上升沿)。

CPHA=1时,数据信号的采样时刻为偶数边沿。

 

二、SPI特性及架构

(1)单次传输可选择为 8 或 16 位。

(2)波特率预分频系数(最大为 fPCLK/2) 。

(3)时钟极性(CPOL)和相位(CPHA)可编程设置 。

(4)数据顺序的传输顺序可进行编程选择,MSB 在前或 LSB 在前。

(5)可触发中断的专用发送和接收标志。

(6)可以使用 DMA 进行数据传输操作。

1SPI架构

MISO 数据线接收到的信号经移位寄存器处理后把数据转移到接收缓冲区,然后这个数据就可以由我们的软件从接收缓冲区读出了。

当要发送数据时,我们把数据写入发送缓冲区,硬件将会把它用移位寄存器处理后输出到 MOSI 数据线。

SCK 的时钟信号则由波特率发生器产生,我们可以通过波特率控制位(BR)来控制它输出的波特率。

控制寄存器 CR1 掌管着主控制电路,STM32 的 SPI 模块的协议设置(时钟极性、相位等)就是由它来制定的。而控制寄存器 CR2 则用于设置各种中断使能。

最后为 NSS 引脚,这个引脚扮演着 SPI 协议中的SS 片选信号线的角色,如果我们把 NSS 引脚配置为硬件自动控制,SPI 模块能够自动判别它能否成为 SPI 的主机,或自动进入 SPI 从机模式。但实际上我们用得更多的是由软件控制某些 GPIO 引脚单独作为SS信号,这个 GPIO 引脚可以随便选择。

 

三、SPI接口读取Flash

        各信号线相应连接到 Flash(型号 :W25X16/W25Q16)的 CS、CLK、DO 和 DIO 线,实现SPI 通信,对 Flash进行读写,其中 W25X16 和 W25Q16 在程序上不同的地方是 FLASH 的ID 不一样。

        读取 Flash 的 ID 信息,写入数据,并读取出来进行校验,通过串口打印写入与读取出来的数据,输出测试结果。

        不同的设备都会相应的有不同的指令,如 EEPROM 中会把第一个数据解释为存储矩阵的地址(实质就是指令)。而 Flash 则定义了更多的指令,有写指令、读指令、读ID 指令等。

SPI-FLASH通信:

1)配置 I/O端口,使能 GPIO

2)根据将要进行通信器件的 SPI模式,配置 STM32 SPI,使能 SPI时钟。

3)配置好 SPI后,根据各种 Flash定义的命令控制对它的读写。

注意在写操作前要先进行存储扇区的擦除操作,擦除操作前也要先发出“写使能”命令

1 main.c

int main(void)
{/* 配置串口 1 为:115200 8-N-1 */USART1_Config();printf("\r\n 这是一个 2M 串行 flash(W25X16)实验 \r\n");/* 2M 串行 flash W25Q16 初始化 */SPI_FLASH_Init();/* Get SPI Flash Device ID */DeviceID = SPI_FLASH_ReadDeviceID();Delay( 200 );/* Get SPI Flash ID */FlashID = SPI_FLASH_ReadID();printf("\r\n FlashID is 0x%X, Manufacturer Device ID is 0x%X\r\n",  FlashID, DeviceID);/* Check the SPI Flash ID */if (FlashID == sFLASH_ID)   /* #define sFLASH_ID 0xEF3015 */{printf("\r\n 检测到串行 flash W25X16 !\r\n");SPI_FLASH_SectorErase(FLASH_SectorToErase);SPI_FLASH_BufferWrite(Tx_Buffer, FLASH_WriteAddress,  BufferSize);printf("\r\n 写入的数据为:%s \r\t", Tx_Buffer);SPI_FLASH_BufferRead(Rx_Buffer, FLASH_ReadAddress, BufferSize);printf("\r\n 读出的数据为:%s \r\n", Tx_Buffer);/* 检查写入的数据与读出的数据是否相等 */TransferStatus1 = Buffercmp(Tx_Buffer, Rx_Buffer, BufferSize);if ( PASSED == TransferStatus1 ){printf("\r\n 2M 串行 flash(W25X16)测试成功!\n\r");}else{printf("\r\n 2M 串行 flash(W25X16)测试失败!\n\r");}}// if (FlashID == sFLASH_ID)else{printf("\r\n 获取不到 W25X16 ID!\n\r");}SPI_Flash_PowerDown();while (1);
}

(1)调用 USART1Confi g() 初始化串口。

(2)调用 SPI_FLASH_Init() 初始化 SPI 模块。

(3)调用 SPI_FLASH_ReadDeviceID() 读取 Flash 器件生产厂商的 ID 信息。

(4)调用 SPI_FLASH_ReadID() 读取 Flash 器件的设备 ID 信息

(5)若读取得的ID正确, 则调用 SPI_FLASH_SectorErase()把 Flash 的内 容擦除,擦除后调用SPI_FLASH_BufferWrite() 向Flash 写入数据,然后再调用SPI_FLASH_BufferRead()从刚刚写入的地址中读出数据。最后调用 Buffercmp() 函数对写入的数据与读取的数据进行比较,若写入的数据与读出的数据相同,则把标志变量TransferStatus1 赋值为 PASSED(自定义的枚举变量)。

(6)最后调用 SPI_Flash_PowerDown()函数关闭 Flash 设备的电源,因为数据写入到Flash 后并不会因断电而丢失,我们在使用它时才重新开启 Flash 的电源

 

2SPI初始化

#define SPI_FLASH_CS_HIGH() GPIO_SetBits(GPIOA, GPIO_Pin_4)
#define SPI_FLASH_CS_LOW() GPIO_ResetBits(GPIOA, GPIO_Pin_4)void SPI_FLASH_Init(void)
{SPI_InitTypeDef  SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);/* SCK */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);/* MISO */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_Init(GPIOA, &GPIO_InitStructure);/* MOS */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;GPIO_Init(GPIOA, &GPIO_InitStructure);/* CS  */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);SPI_FLASH_CS_HIGH();SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI1, &SPI_InitStructure);SPI_Cmd(SPI1, ENABLE);
}

(1)SPI_Mode :主机模式(SPI_Mode_Master)或从机模式(SPI_Mode_Slave),这两个模式的最大区别为 SPI 的 SCK 信号线的时序,SCK 的时序是由通信中的主机产生的。若被配置为从机模式,STM32 的 SPI 模块将接受外来的 SCK 信号。
(2)SPI_DataSize : SPI 每次通信的数据大小(称为数据帧)为 8 位还是 16 位。

(3)SPI_CPOL 和 SPI_CPHA :配置SPI的时钟极性(CPOL)和时钟相位CPHA),这两个配置影响到 SPI 的通信模式,该设置要符合将要互相通信的设备的要求。CPOL 分别可以取 SPI_CPOL_High(SPI 通信空闲时 SCK 为高电平)和SPI_CPOL_Low(SPI 通信空闲时 SCK 为低电平)。CPHA 则可以取 SPI_CPHA_1Edge(在 SCK 的奇数边沿采集数据) 和 SPI_CPHA_2Edge(在 SCK偶数边沿采集数据)。

(4)SPI_NSS :配置NSS引脚的使用模式,硬件模式(SPI_NSS_Hard)与软件模式(SPI_NSS_Soft),在硬件模式中的 SPI 片选信号由硬件自动产生,而软件模式则需要我们亲自把相应的 GPIO 端口拉高或置低产生非片选和片选信号。如果外界条件允许,硬件模式还会自动将 STM32 的 SPI 设置为主机。我们使用软件模式,向这个成员赋值为 SPI_NSS_Soft。

(5)SPI_BaudRatePrescaler:本成员设置波特率分频值,分频后的时钟即为 SPI 的 SCK信号线的时钟频率。这个成员参数可设置为 f PCLK 的 2、4、6、8、16、32、64、128、256 分频。赋值为 SPI_BaudRatePrescaler_4,即 f PCLK 的 4 分频。

(6)SPI_FirstBit:所有串行的通信协议都会有 MSB 先行(高位数据在前)还是 LSB先行(低位数据在前)的问题,而 STM32 的 SPI 模块可以通过这个结构体成员,对这个特性编程控制。据 Flash 的通信时序,我们向这个成员赋值为MSB先行(SPI_FirstBit_MSB)。

(7)SPI_CRCPolynomial:这是 SPI 的 CRC 校验中的多项式,若我们使用 CRC 校验时,就使用这个成员的参数(多项式)来计算 CRC 的值。由于本实验的 Flash 不支持 CRC校验,所以我们向这个结构体成员赋值为 7 实际上是没有意义的。

配置完这些结构体成员后,我们要调用 SPI_Init() 函数把这些参数写入寄存器中,实现SPI 的初始化,然后调用 SPI_Cmd() 来使能 SPI1。

 

2、读FLASHID

#define Dummy_Byte   0xFFu8 SPI_FLASH_SendByte(u8 byte)
{// 等待发送数据寄存器清空while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET);SPI_I2S_SendData(SPI1, byte); // 向从机发送数据while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET); // 等待接收数据寄存器非空return SPI_I2S_ReceiveData(SPI1); // 获取接收寄存器中的数据
}
u32 SPI_FLASH_ReadDeviceID(void)
{u32 Temp = 0;SPI_FLASH_CS_LOW();SPI_FLASH_SendByte(W25X_DeviceID);SPI_FLASH_SendByte(Dummy_Byte);SPI_FLASH_SendByte(Dummy_Byte);SPI_FLASH_SendByte(Dummy_Byte);Temp = SPI_FLASH_SendByte(Dummy_Byte);SPI_FLASH_CS_HIGH();return Temp;
}<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>

3、读取厂商ID

u32 SPI_FLASH_ReadID(void)
{u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;SPI_FLASH_CS_LOW();SPI_FLASH_SendByte(W25X_JedecDeviceID); // 0x9FTemp0 = SPI_FLASH_SendByte(Dummy_Byte);Temp1 = SPI_FLASH_SendByte(Dummy_Byte);Temp2 = SPI_FLASH_SendByte(Dummy_Byte);SPI_FLASH_CS_HIGH();Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;return Temp;
}

4、擦除FLASH内容

void SPI_FLASH_WriteEnable(void)
{SPI_FLASH_CS_LOW();SPI_FLASH_SendByte(W25X_WriteEnable); // 06HSPI_FLASH_CS_HIGH();
}void SPI_FLASH_WaitForWriteEnd(void)
{u8 FLASH_Status = 0;SPI_FLASH_CS_LOW();SPI_FLASH_SendByte(W25X_ReadStatusReg); // 05Hdo{FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);}while ((FLASH_Status & WIP_Flag) == SET);SPI_FLASH_CS_HIGH();
}void SPI_FLASH_SectorErase(u32 SectorAddr)
{SPI_FLASH_WriteEnable();SPI_FLASH_WaitForWriteEnd();SPI_FLASH_CS_LOW();SPI_FLASH_SendByte(W25X_SectorErase); // 20HSPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);SPI_FLASH_SendByte(SectorAddr & 0xFF);SPI_FLASH_CS_HIGH();SPI_FLASH_WaitForWriteEnd();
}

5、向Flash写数据——分页

void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{SPI_FLASH_WriteEnable();SPI_FLASH_CS_LOW();SPI_FLASH_SendByte(W25X_PageProgram); // 02HSPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);SPI_FLASH_SendByte(WriteAddr & 0xFF);if(NumByteToWrite > SPI_FLASH_PerWritePageSize){NumByteToWrite = SPI_FLASH_PerWritePageSize;}while (NumByteToWrite--){SPI_FLASH_SendByte(*pBuffer);pBuffer++;}SPI_FLASH_CS_HIGH();SPI_FLASH_WaitForWriteEnd();
}void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;Addr = WriteAddr % SPI_FLASH_PageSize;count = SPI_FLASH_PageSize - Addr;NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;if (Addr == 0){if (NumOfPage == 0){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);}else{while (NumOfPage--){SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);WriteAddr +=  SPI_FLASH_PageSize;pBuffer += SPI_FLASH_PageSize;}SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);}}else{if (NumOfPage == 0){if (NumOfSingle > count){temp = NumOfSingle - count;SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);WriteAddr +=  count;pBuffer += count;SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);}else{SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);}}else{NumByteToWrite -= count;NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);WriteAddr +=  count;pBuffer += count;while (NumOfPage--){SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);WriteAddr +=  SPI_FLASH_PageSize;pBuffer += SPI_FLASH_PageSize;}if (NumOfSingle != 0){SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);}}}
}

6、从Flash

void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
{SPI_FLASH_CS_LOW();SPI_FLASH_SendByte(W25X_ReadData); // 03HSPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);SPI_FLASH_SendByte((ReadAddr & 0xFF00) >> 8);SPI_FLASH_SendByte(ReadAddr & 0xFF);while (NumByteToRead--) {*pBuffer = SPI_FLASH_SendByte(Dummy_Byte);pBuffer++;}SPI_FLASH_CS_HIGH();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466567.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

这两种printf()函数重定向方法,太实用了

作者&#xff1a;echobright原文链接&#xff1a;https://blog.csdn.net/qq_29344757/article/details/75363639在前面学习了STM32的串口编程&#xff0c;通过USART1向计算机的串口调试助手打印数据&#xff0c;或者接收计算机串口调试助手的数据&#xff0c;接下来我们可以实现…

小时级的进度监控工具

一直在找具体到小时级别的进度监控工具&#xff0c;MS Project甘特图出现也都是天为单位&#xff0c;试用GVCGantt也不行。由于小时级别也适用于个人管理。找了些个人管理模板&#xff0c;不是很理想。直到最近接触到scrum中的burn down chart才忽然明白&#xff0c;这就是我想…

【转】oracle数据库中varchar2陷阱

转自&#xff1a;http://www.cnblogs.com/iyangyuan/p/3491215.html oracle数据库相信大家都比较熟悉&#xff0c;数据库中有一种非常常用的数据类型&#xff1a;字符串型。 对应该类型&#xff0c;在oracle中有三种比较常用的类型&#xff1a;varchar2(byte)、varchar2(char)、…

浅析Linux 64位系统虚拟地址和物理地址的映射及验证方法

前言有好久没更新了&#xff0c;这段时间发生了挺多大喜事哈。但是也还是有挺久没更新了&#xff0c;不得不意识到自己是个小菜鸡&#xff0c;就算是小菜鸡也要做一只快乐小菜鸡。就算更新慢但是我依然会持续更新&#xff0c;因为更文使我快乐。虚拟内存先简单介绍一下操作系统…

SPI、I2C、UART三种串行总线协议的区别

SPI、I2C、UART三种串行总线协议的区别 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 第一个区别当然是名字&#xff1a; SPI(Serial Peripheral Interface&#xff1a;串行外设接口); I2C(INTER IC BUS&#xff1a;意为IC之间总线) UART(…

FLEX组件AnyChart实例教程.

自己看吧&#xff0c;十分详细. 这是其中一个例子&#xff1a; http://www.anychart.com/products/anychart/docs/platforms/flex/samples/gauge_tank/GaugeTank.swf http://www.anychart.com/products/anychart/docs/platforms/flex/

C语言指针:从底层原理到花式技巧,用图文和代码帮你讲解透彻

一、前言二、变量与指针的本质三、指针的几个相关概念四、指向不同数据类型的指针五、总结一、前言如果问C语言中最重要、威力最大的概念是什么&#xff0c;答案必将是指针&#xff01;威力大&#xff0c;意味着使用方便、高效&#xff0c;同时也意味着语法复杂、容易出错。指针…

软件过程改进

对于软件企业来说&#xff0c;软件过程是整个企业最复 杂、最重要的业务流程&#xff0c;软件产品就是软件企业的生命&#xff0c;改进整个企业的业务流程&#xff0c;最重要的还是要改进它的软件过程。多年以来&#xff0c;人们认识到要想高效率、高质量 和低成本地开发软件&a…

ARM

ARM 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 1 、ARM处理器的特点 ARM 处理器具有耗电少&#xff0c;功能强大&#xff0c;16 位/32 位双指令集等众多优点。主要有以下六个主要特点&#xff1a; ① 体积小、低功耗&#xff0c;低成本和高性能&am…

Linux下精准踢掉登录用户-pkill命令

pkill -kill -t 用户的TTY pkill -9 用户的TTY 转载于:https://www.cnblogs.com/setart/p/8496165.html

解决一个I2C读写问题

之前写关于I2C相关的文章排查一个触摸屏驱动问题MTK 平台TP调试遇坑1、问题今天遇到一个问题&#xff0c;我们有一个芯片&#xff0c;I2C读写失败&#xff0c;导致录音有问题&#xff0c;而且是偶现的。log提示看到是返回 -6<3>[ 730.336308] (3)[2085:tinycap]es7243_…

用多媒体库 Bass.dll 播放 mp3 [9] - 绘制波形图

本例效果图:代码文件:unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, ExtCtrls, ComCtrls;typeTForm1 class(TForm)OpenDialog1: TOpenDialog;PaintBox1: TPaintBox;Button1: TButton;Button2: TBut…

我是如何使用wireshark软件的

长按二维码识别关注技术共享|资料共享|沟通交流01简介这篇文章介绍一个好用的抓包工具Wireshark&#xff0c; 用来获取网络数据封包&#xff0c;包括HTTP、TCP、UDP等网络协议包。开始界面wireshark是捕获机器上的某一块网卡的网络包&#xff0c;当你的机器上有多块网卡的时候&…

揩油

揩油&#xff0c;说的是老是有人送上来给我揩油&#xff0c;让我很没有心理准备&#xff0c;而且很不适应。 昨天去家乐福买东西&#xff0c;排队付钱的时候&#xff0c;我和前面一个女孩子的距离间隔<?xml:namespace prefix st1 ns "urn:schemas-microsoft-com:off…

AfxGetMainWnd( )函数

AfxGetMainWnd( )函数 版权声明&#xff1a;需要转载的请注明出处 https://blog.csdn.net/qq_22642239/article/details/52241405 AfxGetMainWnd( )&#xff1a; 使用AfxGetMainWnd函数获取MFC程序中的主框架类指针是一个常用作法。 就是获得应用程序主窗口的指针&#xff…

8086 汇编

8086 汇编速查手册 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神的无限的。 一、数据传输指令 ─────────────────────────────────────── 它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据. 1. 通用数…

BZOJ4681 [jsoi2010]旅行

时间限制&#xff1a; 3S空间限制&#xff1a; 256M具体思路:DPf[i][j][k]表示1-i,前L条路上用了 j条,L后的路上换了k条的最小代价枚举一下L就有了一个复杂度O(nlognk^3)的做法AC代码#include<bits/stdc.h> using namespace std; #define INF 100000000 #define P pair&l…

IIC踩过的坑

读取IT8563WE时&#xff0c;读取第一次正确&#xff0c;第二次错误&#xff0c;第三次正确&#xff0c;第四次错误。。。。。。看到读取成功之后&#xff0c;SDA信号没有被正确拉高&#xff0c;电平大概只有一半。再次读取&#xff0c;主机设置读模式时&#xff0c;从机会发送N…

PostMessage()

PostMessage函数 PostMessage是Windows API(应用程序接口) 中的一个常用函数&#xff0c;用于将一条消息放入到消息队列中。消息队列里的消息通过调用GetMessage和PeekMessage取得。 函数功能 该函数将一个消息放入&#xff08;寄送&#xff09;到与指定窗口创建的线程相联系…

ATT汇编指令总结

AT&T汇编指令总结 宗旨&#xff1a;技术的学习是有限的&#xff0c;分享的精神是无限的。 1.寄存器引用 引用寄存器要在寄存器号前加百分号%,如“movl %eax, %ebx”。 80386有如下寄存器&#xff1a; 8个32-bit寄存器 %eax&#xff0c;%ebx&#xff0c;%ecx&#xff0c;…