GPT2.0语言模型 Language Models are Unsupervised Multitask Learners

article/2025/8/21 23:19:56

在这里插入图片描述
论文链接:https://d4mucfpksywv.cloudfront.net/better-language-models/language-models.pdf
Tensorflow代码链接:https://github.com/openai/gpt-2
Pytorch代码链接:https://github.com/huggingface/pytorch-pretrained-BERT
参考文档:https://mp.weixin.qq.com/s/c0LXAj5tN_59eJKc8yBTLQ
参考文档:https://terrifyzhao.github.io/2019/02/18/GPT2.0%E8%AE%BA%E6%96%87%E8%A7%A3%E8%AF%BB.html

导读

今天阅读的是 OpenAI 的同学于 2019 年发表的论文《Language Models are Unsupervised Multitask Learners》,目前具有 300 多引用量。

在有了之前论文的基础后读这篇论文就比较简单了,论文介绍的是 OpenAI 对 GPT 的一个改进模型 GPT-2,其模型结构与 GPT 相比几乎没有什么变化,只是让模型变得更大更宽,并且取消了 Fine-tuning 的步骤。也就是说 GPT-2 采用了一阶段的模型(预训练)代替了二阶段的模型(预训练+微调),并且在语言模型(文本摘要等)相关领域取得了不错的效果。

GPT-2是GPT的升级版本,其最大的区别在于规模更多,训练数据更多,GPT是12层的transformer,BERT最深是24层的transformer,GPT-2则是48层,共有15亿个参数,其训练数据是一个称为WebText的数据集,该数据集做了一些简单的数据清理,并且覆盖领域十分广阔,论文中指出规模大的模型必须要用更多的数据才能收敛,并且实验结果表明目前模型仍然处于一个欠拟合的情况。其次,相比于BERT,其并没有采用双向的transformer,依旧采用单向transformer,不知道是因为open AI的大佬们头铁还是说有挑衅Google的意思。其次在预训练阶段,GPT-2采用了多任务的方式,不单单只在一个任务上进行学习,而是多个,每一个任务都要保证其损失函数能收敛,不同的任务是共享主体transformer参数的,该方案是借鉴了之前微软的MT-DNN,这样能进一步的提升模型的泛化能力,因此在即使没有fine-turning的情况下依旧有非常不错的表现。

这就是GPT-2的主要改进点,总结一下,多任务预训练+超大数据集+超大规模模型,说白了就是没钱你玩你XX。

1、引言

目前最好的 NLP 模型是结合无监督的 Pre-training 和监督学习的 Fune-tuning,但这种方法的缺点是针对某特定任务需要不同类型标注好的训练数据。作者认为这是狭隘的专家而不是通才,因此作者希望能够通过无监督学习训练出一个可以应对多种任务的通用系统。

作者认为目前的数据集往往都是针对某一特定任务,如 QA 领域的 SQuAD 2.0,机器翻译领域的 NIST04 和 WMT 2014 En-2-Fr等。而正是因为数据集的单一导致系统缺乏泛化性。作者想通过尽可能地构建和利用足够大的且多样化的数据集,以保证最终的模型能够应用于多个不同的 NLP 任务中。为此,作者专门爬了 Reddit 上 > 3 karma 的外链作为数据源,同时去除 wiki 数据,最终数据大小共 40G。由于 Reddit 上的数据会包括各个领域,所以既保证了数据质量、数量又保证了数据的多样性。

此外,据研究表明语言模型有望完成某些特定的任务,如常识推理和情感分析等,所以作者提出了去掉有监督的 Fine-tuning 阶段,仅采用无监督 Pre-training 的语言模型来直接应用到下游任务中。

在本文中,作者论证了这种方法的可行性,并证明了语言模型来相关领域具有很大的潜力。

2、GPT-2模型

2.1、Approach

作者从网上爬了一大堆语料,用来进行LM的pretrain,他们最后的数据集叫WebText,有800万左右的文档,40G的文本,并且还移除了Wikipedia的数据,因为后面要ZSL的任务里面有很多都是基于Wikipedia的语料的,这里其实就是保证了ZSL任务的前提。PS:ZSL就是Zero-shot Learning

GPT-2 的核心是语言模型,语言具有天然的顺序性,通常可以表示为: p ( x ) = ∏ i = 1 n p ( s n ∣ s 1 , ⋯ , s n − 1 ) p(x)=\prod_{i=1}^np(s_n|s_1,\cdots,s_{n-1}) p(x)=i=1np(sns1,,sn1)可以泛化成: p ( s n − k , ⋯ , s n ∣ s 1 , ⋯ , s n − k − 1 ) p(s_{n-k},\cdots,s_n|s_1,\cdots,s_{n-k-1}) p(snk,,sns1,,snk1)针对单个任务可以表示为估计一个条件分布: p ( o u t p u t ∣ i n p u t ) p(output|input) p(outputinput)对于一个通用的系统来说,可以适用于多种任务: p ( o u t p u t ∣ i n p u t , t a s k ) p(output|input,task) p(outputinput,task)

所以语言模型也能够学习某些监督学习的任务,并且不需要明确具体的监督符号。而监督学习由于数据量的关系通常只是无监督学习的一个子集,所以无监督学习的全局最小也必定是监督学习的全局最小,所以目前的问题变为了无监督学习是否能收敛。

作者通过初步论证指出,足够大的语言模型是能够进行多任务学习的,只是学习速度要比监督学习慢得多。

2.2、Input

在模型输入方面,GPT-2 采用的是 Byte Pair Encoding(以下简称 BPE)的 Subword 算法。BPE 是一种简单的数据压缩形式,可以有效地平衡词汇表大小和编码所需的 token 数量。它可以提高词表的空间使用效率,避免得到类似 ‘dog.’、‘dog!’、‘dog?’ 的词。

BPE 和我们之前的提到的 WordPiece 的区别在于,WordPiece 是基于概率生成 Subword 的,而 BPE 是基于贪心策略,每次都取最高频的字节对。

2.3、Model

在模型方面相对于 GPT 来说几乎没有什么修改,只是加入了两个 Layer normalization,一个加在每个 sub-block 输入的地方,另一个加在最后一个 self-attention block 的后面。

同时考虑到模型深度对残差路径的累积问题,GPT-2 采用了修正的初始化方法。在初始化时将残差层的权重缩放到 1 n \frac{1}{\sqrt{n}} n 1 倍, n n n 为残差层的数量。

此外,vocabulary 的大小扩展到了 50257,输入的上下文大小从 512 扩展到了 1024,并且使用更大的 batch size(512)。

GPT-2 提供了四种不同规模的模型:
在这里插入图片描述

2.4、与BERT模型的区别

简单对比下 GPT-2 和 BERT 的区别。

GPT-2 采用的 Transformer 的 Decoder 模块堆叠而成,而 BERT 采用的是 Transformer 的 Encoder 模块构建的。两者一个很关键的区别在于,GPT-2 采用的是传统的语言模型,一次只输出一个单词(多个 token)。

下图是一个训练好的模型来 “背诵” 机器人第一法则:
在这里插入图片描述
这种效果之所以好是因为采用了自回归机制(Auto-Regression):每生成一个新单词,该单词就被添加在生成的单词序列后面,这个序列会成为下一步的新输入。这个也是 RNN 的重要思想。
在这里插入图片描述
而 BERT 采用的是双向语言模型,虽然没有自回归,但也因为获得了结合上下文单词信息的能力,从而也取得了不错的效果。下图展示了 BERT 的 Self-Attention(左)和 GPT-2 的 Masked Self-Attention(右)的区别:
在这里插入图片描述

2.5、模型细节

虽然 GPT-2 相对 GPT 而言没有大改,但是在介绍 GPT 时我们没有介绍 GPT 的工作原理,所以在这我们补充看下 GPT-2 的工作原理。

2.5.1、Overview

为了简单起见,我们以单词为 token。(GPT-2 实际是以字符为 token)

首先GPT-2 可以处理 1024 个单词序列,在任务开始时输入一个起始字符 < s s s>,然后让他生成文字:(不同任务起始字符可能不一样)
在这里插入图片描述
然后将输出的单词添加到输入序列的尾部,重新构建一个新的输入序列,并让模型进行下一步的预测:
在这里插入图片描述
注意:第二个单词的路径是当前唯一活跃的路径了。GPT-2 的每一层都保留了它们对第一个单词的解释,并且将运用这些信息处理第二个单词,GPT-2 不会根据第二个单词重新解释第一个单词。(重新解释速度太慢了)

2.5.2、Input

对于模型的输入而言,分为 Token Embedding 和 Position Embedding。

Token Embedding 的 Vocabulary Size 为 50257,Embedding Size 随着不同模型而改变:
在这里插入图片描述
Position Embedding 的 Context Size 是 1024,Embedding Size 也随着不同模型而改变:
在这里插入图片描述
实际的输入由 Position Embedding 和 Token Embedding 相加得到:
在这里插入图片描述

2.5.3、Decoder

将输入送到模型后,首先通过 Masked Self-Attention,然后通过 Feed Forward Neural Network,第一个子模块处理完成后会传送到下一个模块进行的计算,每一个模型处理方式相同,但是各自独立。
在这里插入图片描述
每一层的 Self-Attention 都会融入了模型对于用来解释某个单词上文的相关单词的理解。具体做法是,给序列中每一个单词都赋予一个相关度得分,然后对他们的向量表征进行加权求和:
在这里插入图片描述
来自 Self-Attention 的输出作为 Feed Forward 的输入,并经过两层神经网络产生输出。
在这里插入图片描述
简单看下 GPT-2 SMALL 每一次的参数量:
在这里插入图片描述

2.5.4、Output

将模型最后的输出与 Token Embedding 矩阵相乘,并通过 Logits 回归得到最终的概率值,取最大值即为输出。
在这里插入图片描述
为了防止推荐单词陷入循环(一直点击以第一个单词有可能陷入循环),GPT-2 会从概率最大的 top-k 单词中选取下一个单词。

3、实验

作者用了几种不同size的模型,见下图:
在这里插入图片描述
作者指出的是,最小的模型就是GPT,第二小的与大BERT是一个量级,最大的模型称为GPT-2。所有的model,在LM训练的时候,都处于欠拟合的状态。说明他们爬的这个大数据还是很好的!

作者直接将这个pretrain的模型,不用finetune的跑了各个下游的NLP任务,即ZSL(Zero-Shot Learning)设定,结果如下:
在这里插入图片描述
这里的WikiText2、PTB、enwiki8、text8、WikiText103、1BW是几个测试语言模型的数据集;LAMBADA是测试建模长句子能力的数据集,用于预测一句话的最后一个词;CBT是用于检验在不同类型的词上LM的表现,主要是Cloze任务。

作者还测试了一些其他的任务,比如推理的任务Winograd Schema Challange,结果如下:
在这里插入图片描述
还有阅读理解CoQA、摘要、翻译、QA等任务,比如摘要的结果:
在这里插入图片描述
最后,作者还给出了一个说明训练难度的表格,用于说明这些任务的训练集与测试集的文本重合度比较高,所以SoTA的效果要打一些折扣,而GPT-2这里用到的训练数据则与测试集重合度较低,所以就更能说明GPT-2的提升效果啦!
在这里插入图片描述

4、Tensorflow代码实现

看源码的意思,好像与GPT一样,也是没有放出pretrain的训练代码,而且在例子上也只是给出了文本续写的部分。但依然不影响笔者想一探究竟,那么这里就从pretrain的模型结构和文本续写的generate来讲吧。其实,按照GPT-2本身论文的侧重点,是想证明pretrain的LM就可以用ZSL完成其他的任务,因此,这里给出的这两部分源码其实对于实际应用来说也足够了!

4.1、模型结构

在模型结构上,主体还是与GPT很像,都是transformer的decoder形式,只不过在规模上扩大了,其具体代码如下:

def model(hparams, X, past=None, scope='model', reuse=False):with tf.variable_scope(scope, reuse=reuse):results = {}batch, sequence = shape_list(X)# Embeddingwpe = tf.get_variable('wpe', [hparams.n_ctx, hparams.n_embd],initializer=tf.random_normal_initializer(stddev=0.01))wte = tf.get_variable('wte', [hparams.n_vocab, hparams.n_embd],initializer=tf.random_normal_initializer(stddev=0.02))past_length = 0 if past is None else tf.shape(past)[-2]h = tf.gather(wte, X) + tf.gather(wpe, positions_for(X, past_length))# Transformerpresents = []pasts = tf.unstack(past, axis=1) if past is not None else [None] * hparams.n_layerassert len(pasts) == hparams.n_layerfor layer, past in enumerate(pasts):h, present = block(h, 'h%d' % layer, past=past, hparams=hparams)presents.append(present)results['present'] = tf.stack(presents, axis=1)h = norm(h, 'ln_f')# Language model loss.  Do tokens <n predict token n?h_flat = tf.reshape(h, [batch*sequence, hparams.n_embd])logits = tf.matmul(h_flat, wte, transpose_b=True)logits = tf.reshape(logits, [batch, sequence, hparams.n_vocab])results['logits'] = logitsreturn results

代码整体还是很清晰的,一共分为三步:

  • embedding层:这里的wpe和wte分别代表的是position embedding和token embeeding。
  • Transformer层:这里的核心仍然是block这个函数,后面会细说。注意这里仍是没有传入长度的mask部分,这与之前GPT中的处理方式一样,还是很粗糙。
  • 输出层:在得到了每个timestep的表示之后,就是熟悉的softmax层,这里仍然用了tie的策略,在映射到词表的时候,仍然使用的是之前token embedding的参数。

至于block部分,就是transformer的decoder部分,其实现方式如下:

def block(x, scope, *, past, hparams):with tf.variable_scope(scope):nx = x.shape[-1].valuea, present = attn(norm(x, 'ln_1'), 'attn', nx, past=past, hparams=hparams)x = x + am = mlp(norm(x, 'ln_2'), 'mlp', nx*4, hparams=hparams)x = x + mreturn x, present

与GPT的主要不同就在于norm的地方不一样,GPT是在residual之后进行norm。

这里的两个细节实现attn和mlp如下:

def attn(x, scope, n_state, *, past, hparams):assert x.shape.ndims == 3  # Should be [batch, sequence, features]assert n_state % hparams.n_head == 0if past is not None:assert past.shape.ndims == 5  # Should be [batch, 2, heads, sequence, features], where 2 is [k, v]def split_heads(x):# From [batch, sequence, features] to [batch, heads, sequence, features]return tf.transpose(split_states(x, hparams.n_head), [0, 2, 1, 3])def merge_heads(x):# Reverse of split_headsreturn merge_states(tf.transpose(x, [0, 2, 1, 3]))def mask_attn_weights(w):# w has shape [batch, heads, dst_sequence, src_sequence], where information flows from src to dst._, _, nd, ns = shape_list(w)b = attention_mask(nd, ns, dtype=w.dtype)b = tf.reshape(b, [1, 1, nd, ns])w = w*b - tf.cast(1e10, w.dtype)*(1-b)return wdef multihead_attn(q, k, v):# q, k, v have shape [batch, heads, sequence, features]w = tf.matmul(q, k, transpose_b=True)w = w * tf.rsqrt(tf.cast(v.shape[-1].value, w.dtype))w = mask_attn_weights(w)w = softmax(w)ga = tf.matmul(w, v)return awith tf.variable_scope(scope):c = conv1d(x, 'c_attn', n_state*3)qg, k, v = map(split_heads, tf.split(c, 3, axis=2))present = tf.stack([k, v], axis=1)if past is not None:pk, pv = tf.unstack(past, axis=1)k = tf.concat([pk, k], axis=-2)v = tf.concat([pv, v], axis=-2)a = multihead_attn(q, k, v)a = merge_heads(a)a = conv1d(a, 'c_proj', n_state)return a, presentdef mlp(x, scope, n_state, *, hparams):with tf.variable_scope(scope):nx = x.shape[-1].valueh = gelu(conv1d(x, 'c_fc', n_state))h2 = conv1d(h, 'c_proj', nx)return h2

这里在feed forward里面仍然使用的是gelu激活函数。

4.2、文本续写

这里其实主要是用的LM的自动生成下一个功能,主体的part就在于下面这个函数:

def body(past, prev, output):next_outputs = step(hparams, prev[:, tf.newaxis], past=past)logits = next_outputs['logits'][:, -1, :]  / tf.to_float(temperature)logits = top_k_logits(logits, k=top_k)samples = tf.multinomial(logits, num_samples=1, output_dtype=tf.int32)return [tf.concat([past, next_outputs['presents']], axis=-2),tf.squeeze(samples, axis=[1]),tf.concat([output, samples], axis=1),]def step(hparams, tokens, past=None):lm_output = model.model(hparams=hparams, X=tokens, past=past, reuse=tf.AUTO_REUSE)logits = lm_output['logits'][:, :, :hparams.n_vocab]presents = lm_output['present']presents.set_shape(model.past_shape(hparams=hparams, batch_size=batch_size))return {'logits': logits,'presents': presents,}

可见其流程是:

  1. 根据当前的上下文生成下一个输出(step函数);
  2. 选择出Top-k的输出;
  3. 根据当前的概率分布采样一个作为下一个续写的输出。

5、结论

GPT-2 在 GPT 的基础上采用单向语言模型,并舍去 Fine-tuning 阶段,利用高质量多样化的大文本数据训练得到一个巨型模型,最终在语言模型相关的任务中取得了不错的成绩。

但我总觉得 BERT 要是也用同样的数据和模型规模会比 GPT-2 要更好,毕竟 BERT 打败 GPT 是因为其采用了双向语言模型的结构。

虽然没钱做实验,但 GPT-2 还是给我们带来了一个不错启发:多任务是有机会用一个模型解决的,无监督学习的语言模型在 NLP 领域的潜力还很大。

最后放上一个 OpenAI 和 ELMo、Bert 的参数对比图:
在这里插入图片描述

6、个人总结

6.1、优势

  • 收集了一个大语料库WebText,即使像GPT-2这样的大模型,也依然处于欠拟合的状态
  • 最大的GPT-2模型,有1.5B的参数量,用ZSL在很多任务上进行测试,发现有7/8的任务上都达到了SoTA。
  • 给出了预训练好的参数,虽然只有TensorFlow的,但转成别的应该也不难

6.2、不足

  • 没有放出pretrain的训练代码,并且finetune的部分也只列举了续写的部分
  • 只给出了一个小的117M的预训练参数,可能是怕用于不正当用途吧,也可以理解

http://chatgpt.dhexx.cn/article/Ij5PxaWm.shtml

相关文章

论文阅读《Language Models are Unsupervised Multitask Learners》

论文地址&#xff1a;《Language Models are Unsupervised Multitask Learners》 代码地址&#xff1a;https://github.com/openai/gpt-2 文章目录 论文介绍模型框架实验分析结论 论文介绍 本文将常识推理和情感分析两项任务联系起来&#xff0c;采取更一般的方法。证明了语言…

MulT: An End-to-End Multitask Learning Transformer 多任务共享注意力

文章 同时学习多个高级视觉任务&#xff0c;包括深度估计、语义分割、reshading表面法线估计、2D 关键点检测和边缘检测。 与单个任务Transformer相比&#xff0c;跨任务联合培训的Transformer模型能否提高每个任务的性能&#xff1f;在基于Transformer的框架中&#xff0c;可…

Paper | Multitask learning

目录 1. MTL的定义2. MTL的机制 2.1. Representation Bias2.2. Uncorrelated Tasks May Help&#xff1f;3. MTL的用途 3.1. Using the Future to Predict the Present3.2. Time Series Prediction3.3. Using Extra Tasks to Focus Attention3.4. Quantization Smoothing3.5. S…

GPT2(Language Models are Unsupervised Multitask Learners)论文阅读

1. 论文阅读 论文地址&#xff1a;Language Models are Unsupervised Multitask Learners 1.1 背景介绍 2019年OpenAI发布的模型&#xff0c;OpenAI在2018年的GPT1中给出了一种半监督的训练方法&#xff0c;在GPT2中针对如下问题做了升级&#xff1a; 以前机器学习训练代价大…

#Paper Reading# Language Models are Unsupervised Multitask Learners

论文题目: Language Models are Unsupervised Multitask Learners 论文地址: https://life-extension.github.io/2020/05/27/GPT技术初探/language-models.pdf 论文发表于: OpenAI 2019 论文所属单位: OpenAI 论文大体内容&#xff1a; 本文主要提出了GPT-2&#xff08;Gener…

【论文阅读】Multitask Prompted Training Enables Zero-shot Task Generalization

前言 本文源自 ICLR 2022 原文地址&#xff1a;Multitask Prompted Training Enables Zero-shot Task Generalization Discussion 中提到的 FLAN 参考博文 【论文阅读】Finetuned Language Models Are Zero-Shot Learners_长命百岁️的博客-CSDN博客 Abstract 大模型在多种…

MultiTask Learning Survey

目录 一、常见Multi-Task 架构 二、MTL的一些优化方法 三、ExperimentConclusion 原文链接&#xff1a;MultiTask Survey 一、常见Multi-Task 架构 Hard和Soft区分&#xff1a;Hard共享底层参数&#xff0c;在高层提取中相互独立&#xff1b;Soft使用十字绣的形式&#xf…

Multitask Learning

参考 Multitask Learning - 云社区 - 腾讯云 1、单任务学习VS多任务学习 单任务学习&#xff1a;一次只学习一个任务&#xff08;task&#xff09;&#xff0c;大部分的机器学习任务都属于单任务学习。多任务学习&#xff1a;把多个相关&#xff08;related&#xff09;的任务…

Multi-Task 多任务学习, 那些你不知道的事

作者 | 三和厂妹 来源 | 文末『阅读原文』处 概念 当在一个任务中要优化多于一个的目标函数[1] &#xff0c;就可以叫多任务学习 一些例外 「一个目标函数的多任务」&#xff1a;很多任务中把loss加到一起回传&#xff0c;实质优化的是一个目标函数, 但优化的是多个任务&…

多任务学习综述:推荐系统多任务学习(multitask)的实战总结和常见问题(一)

多任务学习算法系列的主要内容是回顾和总结自己2019-2021间在深度学习多任务学习算法(multitask)的工业实践和遇到的常见问题&#xff0c;欢迎更多同学讨论和指正&#xff0c;同时也宣传一波我们组在推荐方向的工作成果——大规模推荐算法库PaddleRec&#xff08;https://githu…

VS2012下载和安装

1.下载链接 https://pan.baidu.com/s/1YR7Xk9Zlv7zQWCsERdVgIQ 提取码&#xff1a;stvi 2.鼠标右击【Visual Studio2012】压缩包选择【解压到Visual Studio2012】。 3.打开解压后的文件夹&#xff0c;鼠标右击【vs_ultimate】选择【以管理员身份运行】。 4.点击【…】可更改安…

Visual Studio 2013 详细安装教程(安装+注册)

转载自&#xff1a;安装注册&#xff1a;https://jingyan.baidu.com/article/09ea3ede3b2496c0afde3944.html IE10报错解决办法&#xff1a;https://jingyan.baidu.com/article/ff42efa92f79cac19e2202cd.html 1.还是老样子&#xff0c;首先要下载安装文件&#xff0c;这里提供…

使用cubemx工具的STM32对外部flash(W25Q64)的简单编程

SPI SPI简介 SPI通信原理 SPI是串行外设接口&#xff08;Serial Peripheral Interface&#xff09;的缩写&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在芯片的管脚上只占用四根线&#xff0c;节约了芯片的管脚&#xff0c;同时为…

stm32 W25QXX系列驱动 W25Q80 W25Q16 W25Q32 W25Q64 W25Q128 W25Q256

头文件 #ifndef W25QXX__H #define W25QXX__H #include "sys.h"#define W25Q80 0XEF13 #define W25Q16 0XEF14 #define W25Q32 0XEF15 #define W25Q64 0XEF16 #define W25Q128 0XEF17 #define W25Q256 0XEF18#define W25QXX_CS PAout(4)//指令表 #define W25X…

SPI专题(二)——STM32驱动FLASH(W25Q64)

前言&#xff1a; 为了方便查看博客&#xff0c;特意申请了一个公众号&#xff0c;附上二维码&#xff0c;有兴趣的朋友可以关注&#xff0c;和我一起讨论学习&#xff0c;一起享受技术&#xff0c;一起成长。 github&#xff1a;my github 注&#xff1a;博客所涉及的关于 st…

STM32系列(HAL库)——F103C8T6通过SPI方式读写W25Q64—(Flash存储模块)

1.软件准备 (1)编程平台&#xff1a;Keil5 (2)CubeMX (3)XCOM(串口调试助手) 2.硬件准备 (1)W25Q64模块 (2)F1的板子&#xff0c;本例使用经典F103C8T6 (3)ST-link 下载器 (4)USB-TTL模块 (5)杜邦线若干 3.模块资料 (1)模块简介&#xff1a; W25Q64(64M-bit)&#xff0c…

SPI协议学习Cubmx——读写Flash W25Q64

这是最好的时代&#xff0c;这是最坏的时代&#xff1b; 这是智慧的时代&#xff0c;这是愚蠢的时代&#xff1b; 这是信仰的时期&#xff0c;这是怀疑的时期&#xff1b; 这是光明的季节&#xff0c;这是黑暗的季节&#xff1b; 这是希望之春&#xff0c;这是失望之冬&#xf…

STM32使用QUADSPI读写外部Nor Flash(以W25Q64为例)

使用QUADSPI读写W25Q64 QUADSPI介绍硬件连接双闪存模式禁止双闪存模式使能 QUADSPI命令序列指令阶段地址阶段交替字节阶段空指令周期阶段数据阶段 QUADSPI主要信号接口协议模式单线SPI模式双线SPI模式四线SPI模式 使用QUADSPI操作W25Q64发送命令函数状态轮询函数读ID函数QUADSP…

W25Q64内部结构

和STM32片上一样 我们分析 函数接口&#xff1a; 擦除1个扇区 【参数必须是4096的倍数】 void SPI_FLASH_SectorErase(uint32_t SectorAddr) 擦除芯片全部 void SPI_FLASH_BulkErase(void) 写入一页【数据比256小】 pBuffer&#xff1a;待写入数据的指针 WriteAddr&#xff…

基于STM32F401RET6字库烧录(SPIW25Q64驱动)

目录 一、SPI&W25Q64 1-SPI介绍 2-初始化SPI 3-SPI数据接收和发送函数 4-验证SPI是否配置正确&#xff08;读W25Q64的ID&#xff09; 二、W25Q64简介与API函数 1 - W25Q64芯片介绍 2- W25Q64芯片管脚说明 3- W25Q64芯片工作原理 4- W25Q64芯片操作时序 三、字库烧…