DMA学习笔记

啃手册的过程~
DMA(Derict Memory Access,直接存储器存储),回顾STM32的运行架构,数据的转移时常发生,需要内核操作,比较浪费计算资源,而DMA代CPU完成数据的转移可以减轻CPU的工作量,使之专注于计算工作,大大提升效率,这大概就是DMA的重要意义。
![](https://img-blog.csdnimg.cn/img_convert/ea0dee3a35c4e263ba382510477ef61c.png#clientId=u6aa98445-78e2-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ub35dfed4&margin=[object Object]&originHeight=565&originWidth=798&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u3eb92b3a-a925-4e4d-9986-6be7769df60&title=)

DMA处理

参考手册可知

在发生一个事件后,外设向DMA控制器发送一个请求信号。 DMA控制器根据通道的优先权处理
请求。当DMA控制器开始访问发出请求的外设时, DMA控制器立即发送给它一个应答信号。当
从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求, DMA控制
器同时撤销应答信号。如果有更多的请求时,外设可以启动下一个周期。

总之,每次DMA传送由3个操作组成:

  • 从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传
    输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。
  • 存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输
    时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元。
  • 执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目

过程还是比较好理解的,而且这样来说我们也大概知道需要哪些参数了。

仲裁器

仲裁器根据通道请求的优先级来启动外设/存储器的访问。
优先权管理分2个阶段:
● 软件:每个通道的优先权可以在DMA_CCRx寄存器中设置,有4个等级:
─ 最高优先级
─ 高优先级
─ 中等优先级
─ 低优先级
● 硬件:如果2个请求有相同的软件优先级,则较低编号的通道比较高编号的通道有较高的优
先权。举个例子,通道2优先于通道4。
_注意: 在大容量产品和互联型产品中, DMA1控制器拥有高于DMA2控制器的优先级 _

因为目前是用的大容量产品,我特意加粗了注意事项,以避免意想不到的优先级问题。
有个小疑惑:DMA1高于DMA2的优先级究竟是软件层面还是硬件层面?
有待深究。

DMA通道

勾画一下重点。

每个通道都可以在有固定地址的外设寄存器和存储器地址之间执行DMA传输。 DMA传输的数据
量是可编程的,最大达到65535。包含要传输的数据项数量的寄存器,在每次传输后递减。
可编程的数据量
外设和存储器的传输数据量可以通过DMA_CCRx寄存器中的PSIZE和MSIZE位编程。
指针增量
通过设置DMA_CCRx寄存器中的PINC和MINC标志位,外设和存储器的指针在每次传输后可以
有选择地完成自动增量。当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量
值,增量值取决与所选的数据宽度为1、 2或4。第一个传输的地址是存放在DMA_CPARx
/DMA_CMARx寄存器中地址。在传输过程中,这些寄存器保持它们初始的数值,软件不能改变
和读出当前正在传输的地址(它在内部的当前外设/存储器地址寄存器中)。
当通道配置为非循环模式时,传输结束后(即传输计数变为0)将不再产生DMA操作。要开始新的
DMA传输,需要在关闭DMA通道的情况下,在DMA_CNDTRx寄存器中重新写入传输数目。
在循环模式下,最后一次传输结束时, DMA_CNDTRx寄存器的内容会自动地被重新加载为其初
始数值,内部的当前外设/存储器地址寄存器也被重新加载为DMA_CPARx/DMA_CMARx寄存器
设定的初始基地址。
通道配置过程
下面是配置DMA通道x的过程(x代表通道号):

  1. 在DMA_CPARx寄存器中设置外设寄存器的地址。发生外设数据传输请求时,这个地址将
    是数据传输的源或目标。
  2. 在DMA_CMARx寄存器中设置数据存储器的地址。发生外设数据传输请求时,传输的数
    据将从这个地址读出或写入这个地址。
  3. 在DMA_CNDTRx寄存器中设置要传输的数据量。在每个数据传输后,这个数值递减。
  4. 在DMA_CCRx寄存器的PL[1:0]位中设置通道的优先级。
  5. 在DMA_CCRx寄存器中设置数据传输的方向、循环模式、外设和存储器的增量模式、外
    设和存储器的数据宽度、传输一半产生中断或传输完成产生中断。
  6. 设置DMA_CCRx寄存器的ENABLE位,启动该通道。
    一旦启动了DMA通道,它既可响应连到该通道上的外设的DMA请求。
    当传输一半的数据后,半传输标志(HTIF)被置1,当设置了允许半传输中断位(HTIE)时,将产生
    一个中断请求。在数据传输结束后,传输完成标志(TCIF)被置1,当设置了允许传输完成中断位
    (TCIE)时,将产生一个中断请求。

循环模式
循环模式用于处理循环缓冲区和连续的数据传输(如ADC的扫描模式)。在DMA_CCRx寄存器中
的CIRC位用于开启这一功能。当启动了循环模式,数据传输的数目变为0时,将会自动地被恢
复成配置通道时设置的初值, DMA操作将会继续进行。
存储器到存储器模式
DMA通道的操作可以在没有外设请求的情况下进行,这种操作就是存储器到存储器模式。
当设置了DMA_CCRx寄存器中的MEM2MEM位之后,在软件设置了DMA_CCRx寄存器中的EN
位启动DMA通道时, DMA传输将马上开始。当DMA_CNDTRx寄存器变为0时, DMA传输结
束。存储器到存储器模式不能与循环模式同时使用

中间的部分比较偏向底层的原理,我们使用库开发,了解机制即可。
循环是我们需要了解的,感觉手册说的也比较清楚。

可编程的数据传输宽度、对齐方式和数据大小端

比较不起眼的一个知识点,但是很有用。
当PSIZE和MSIZE不相同时, DMA模块按照下表进行数据对齐。

![image.png](https://img-blog.csdnimg.cn/img_convert/5e357f9474be6a9d990938d932fd2019.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u371d051d&margin=[object Object]&name=image.png&originHeight=706&originWidth=1304&originalType=binary&ratio=1&rotation=0&showTitle=false&size=249986&status=done&style=none&taskId=u6991d5eb-eb78-4c0d-839e-55a3fd2bf1d&title=)
![image.png](https://img-blog.csdnimg.cn/img_convert/cdd843d2bc8fd3725441b291a5d15c65.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u84450d2d&margin=[object Object]&name=image.png&originHeight=517&originWidth=1271&originalType=binary&ratio=1&rotation=0&showTitle=false&size=231540&status=done&style=none&taskId=u91fcc3cb-8294-431c-ad7e-ad78c3a78f4&title=)
我们会发现对于长数据的传输也是分段的这样以来大于八位的数据对八位目标就会多次写入而只保留最后8位。

操作一个不支持字节或半字写的AHB设备

可以说是非常智能了

当DMA模块开始一个AHB的字节或半字写操作时,数据将在HWDATA[31:0]总线中未使用的部
分重复。因此,如果DMA以字节或半字写入不支持字节或半字写操作的AHB设备时(即HSIZE不
适于该模块),不会发生错误, DMA将按照下面两个例子写入32位HWDATA数据:
● 当HSIZE=半字时,写入半字’0xABCD’, DMA将设置HWDATA总线为’0xABCDABCD’。
● 当HSIZE=字节时,写入字节’0xAB’, DMA将设置HWDATA总线为’0xABABABAB’。
假定AHB/APB桥是一个AHB的32位从设备,它不处理HSIZE参数,它将按照下述方式把任何
AHB上的字节或半字按32位传送到APB上:
● 一个AHB上对地址0x0(或0x1、 0x2或0x3)的写字节数据’0xB0’操作,将转换到APB上对地址
0x0的写字数据’0xB0B0B0B0’操作。
● 一个AHB上对地址0x0(或0x2)的写半字数据’0xB1B0’操作,将转换到APB上对地址0x0的写
字数据’0xB1B0B1B0’操作。
例如,如果要写入APB后备寄存器(与32位地址对齐的16位寄存器),需要配置存储器数据源宽
度(MSIZE)为’16位’,外设目标数据宽度(PSIZE)为’32位’。

错误管理

读写一个保留的地址区域,将会产生DMA传输错误。当在DMA读写操作时发生DMA传输错误
时,硬件会自动地清除发生错误的通道所对应的通道配置寄存器(DMA_CCRx)的EN位,该通道
操作被停止。此时,在DMA_IFR寄存器中对应该通道的传输错误中断标志位(TEIF)将被置位,
如果在DMA_CCRx寄存器中设置了传输错误中断允许位,则将产生中断。

中断

每个DMA通道都可以在DMA传输过半、传输完成和传输错误时产生中断。为应用的灵活性考
虑,通过设置寄存器的不同位来打开这些中断。

中断事件事件标志位使能控制位
传输过半HTIFHTIE
传输完成TCIFTCIE
传输错误TEIFTEIE

注意: 在大容量产品中, __DMA2__通道__4__和__DMA2__通道__5__的中断被映射在同一个中断向量上。在互联型产品
__中, __DMA2__通道__4__和__DMA2__通道__5__的中断分别有独立的中断向量。所有其他的__DMA__通道都有自己的
__中断向量。

这个注意十分受用,我在例程编写时使用的是UART4其TX位于DMA2的5通道上,所以是DMA2_Channel4_5_IRQn。

DMA请求映像

DMA1

外设通道1通道2通道3通道4通道5通道6通道7
ADC1ADC1
SPI/I2SSPI1_RXSPI1_TXSPI/I2S2_RXSPI/I2S2_TX
USARTUSART3_TXUSART3_RXUSART1_TXUSART1_RXUSART2_RXUSART2_TX
I2CI2C2_TXI2C2_RXI2C1_TXI2C1_RX
TIM1_TX4
TIM1_TRIG
TIM1_COMTIM1TIM1_CH1TIM1_CH2TIM1_UPTIM1_CH3
TIM2TIM2_CH3TIM2_UPTIM2_CH1TIM2_CH2
TIM2_CH4
TIM3TIM3_CH3TIM3_CH4
TIM3_UPTIM3_CH1
TIM3_TRIG
TIM4TIM4_CH1TIM4_CH2TIM4_CH3TIM4_UP

DMA2

外设通道1通道2通道3通道4通道5
ADC3(1)ADC3
SPI/I2S3SPI/I2S3_RXSPI/I2S3_TX
UART4UART4_RXUART4_TX
SDIO(1)SDIO
TIM5_CH4
TIM5_TRIGTIM5_CH3
TIM5_UPTIM5TIM5_CH2TIM5_CH1
TIM6/
DAC通道1TIM6_UP/
DAC通道1
TIM7/
DAC通道2TIM7_UP/
DAC通道2
TIM8_CH4
TIM8_TRIG
TIM8_COMTIM8_CH3
TIM8_UPTIM8(1)TIM8_CH1TIM8_CH2

DMA库函数

根据库手册DMA函数如下:
![image.png](https://img-blog.csdnimg.cn/img_convert/693f598a5e86be1df1f72bfaa35e6f6c.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u4db6a163&margin=[object Object]&name=image.png&originHeight=441&originWidth=1172&originalType=binary&ratio=1&rotation=0&showTitle=false&size=204681&status=done&style=none&taskId=ue945127d-9465-468a-8e8b-558ef9ee44e&title=)

DMA_DeInit

![image.png](https://img-blog.csdnimg.cn/img_convert/a81c0c43b7fe7db639bb0b97f9bdd817.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u3a5bf931&margin=[object Object]&name=image.png&originHeight=571&originWidth=1332&originalType=binary&ratio=1&rotation=0&showTitle=false&size=147980&status=done&style=none&taskId=uc936dd47-96b0-49ed-ad70-20639947ca5&title=)
用于设置为缺省值。

DMA_Init

![image.png](https://img-blog.csdnimg.cn/img_convert/3751f5a5550a1410faf970528a402916.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u8a573cb9&margin=[object Object]&name=image.png&originHeight=455&originWidth=1307&originalType=binary&ratio=1&rotation=0&showTitle=false&size=163398&status=done&style=none&taskId=ua40ca81a-b9b3-4c4c-96b8-1c00e0f5af7&title=)
重要的初始化函数,我们有必要了解其结构体参数。
![image.png](https://img-blog.csdnimg.cn/img_convert/b542638cf8565dc9142adb4feeb653a9.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=247&id=ub60d57b1&margin=[object Object]&name=image.png&originHeight=494&originWidth=1239&originalType=binary&ratio=1&rotation=0&showTitle=false&size=123277&status=done&style=none&taskId=u439474a3-322e-4f7a-81c0-307dd9f472c&title=&width=619.5)
这个DMA外设基地址是得自定义的,取决于使用的串口寄存器地址。
![image.png](https://img-blog.csdnimg.cn/img_convert/cbeb3862d901f4aa6a81a7603ed856e1.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=25&id=u9ed9140d&margin=[object Object]&name=image.png&originHeight=49&originWidth=363&originalType=binary&ratio=1&rotation=0&showTitle=false&size=6931&status=done&style=none&taskId=u71bb5685-f101-4508-9fe6-8afe0cd6884&title=&width=181.5)
这个同理。
![image.png](https://img-blog.csdnimg.cn/img_convert/731ca7339f077ec0e19abf36c7d2f2d5.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u99cddfdc&margin=[object Object]&name=image.png&originHeight=244&originWidth=1171&originalType=binary&ratio=1&rotation=0&showTitle=false&size=88608&status=done&style=none&taskId=u771a19c7-3677-4b8e-a664-04cda8e9ac9&title=)
这个比较有意思,DMA传输方向是可以从内存到外设或外设到内存的。
![image.png](https://img-blog.csdnimg.cn/img_convert/69539a6f3bf9d637abb0ed5d36443c26.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u49f31360&margin=[object Object]&name=image.png&originHeight=190&originWidth=1328&originalType=binary&ratio=1&rotation=0&showTitle=false&size=96509&status=done&style=none&taskId=u40ccfff8-6033-4708-81f9-f3031a1dab1&title=)
![image.png](https://img-blog.csdnimg.cn/img_convert/c418de2a4fd5060be973713649bc795d.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u79a10efd&margin=[object Object]&name=image.png&originHeight=675&originWidth=1237&originalType=binary&ratio=1&rotation=0&showTitle=false&size=238033&status=done&style=none&taskId=u00bbe9f7-4086-4777-a81e-ec38e86470c&title=)
![image.png](https://img-blog.csdnimg.cn/img_convert/0af1d768e1b95517f1c870bd835af32c.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u477cab5e&margin=[object Object]&name=image.png&originHeight=264&originWidth=1296&originalType=binary&ratio=1&rotation=0&showTitle=false&size=102556&status=done&style=none&taskId=u90960f9f-0ca8-414d-a26f-2365e346c3a&title=)
![image.png](https://img-blog.csdnimg.cn/img_convert/1960a98292627522f509ded383ee346e.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u25e9fde4&margin=[object Object]&name=image.png&originHeight=462&originWidth=1227&originalType=binary&ratio=1&rotation=0&showTitle=false&size=150725&status=done&style=none&taskId=u73f968b9-8b58-4a76-9b69-26dcf677959&title=)
![image.png](https://img-blog.csdnimg.cn/img_convert/d6867c0e9a3220e9dea6208bb5519c98.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u88e7573a&margin=[object Object]&name=image.png&originHeight=781&originWidth=1287&originalType=binary&ratio=1&rotation=0&showTitle=false&size=224192&status=done&style=none&taskId=uc6232373-1985-48ec-831a-d37ed310ca0&title=)
![image.png](https://img-blog.csdnimg.cn/img_convert/5841c2d552ab628aa5cb2fdd00fbb3a8.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ue1a8e923&margin=[object Object]&name=image.png&originHeight=48&originWidth=1200&originalType=binary&ratio=1&rotation=0&showTitle=false&size=10554&status=done&style=none&taskId=u74087581-581a-477e-878e-76ba6f1db88&title=)

DMA_Cmd

![image.png](https://img-blog.csdnimg.cn/img_convert/d2366da9e1fd8c24d51c866e66b3bdee.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=uddb7f559&margin=[object Object]&name=image.png&originHeight=550&originWidth=1299&originalType=binary&ratio=1&rotation=0&showTitle=false&size=155747&status=done&style=none&taskId=u300bb726-5c9f-4feb-a6df-88fb538c927&title=)

DMA_ITConfig

![image.png](https://img-blog.csdnimg.cn/img_convert/a6b1ea2650e3e7b77ef8970149787400.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u623a6392&margin=[object Object]&name=image.png&originHeight=525&originWidth=1302&originalType=binary&ratio=1&rotation=0&showTitle=false&size=195768&status=done&style=none&taskId=u4630de64-4099-42a5-bc51-672b306e884&title=)
![image.png](https://img-blog.csdnimg.cn/img_convert/4662eb4eee9d17a6af18ca97468df72e.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u5b38af22&margin=[object Object]&name=image.png&originHeight=291&originWidth=1293&originalType=binary&ratio=1&rotation=0&showTitle=false&size=88895&status=done&style=none&taskId=u28143784-6c05-4499-82aa-c9c26a9afde&title=)

DMA_GetCurrDataCounte

![image.png](https://img-blog.csdnimg.cn/img_convert/3a0c7aeae23d909fe0db4f515bff7aa7.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ua666f5d5&margin=[object Object]&name=image.png&originHeight=364&originWidth=1310&originalType=binary&ratio=1&rotation=0&showTitle=false&size=131248&status=done&style=none&taskId=u02ed218b-bb24-4afd-ba74-18514ba1fe1&title=)

DMA_GetFlagStatus

![image.png](https://img-blog.csdnimg.cn/img_convert/a0658f20da4044f5fd3d756efdb1df2c.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u6caaaf36&margin=[object Object]&name=image.png&originHeight=362&originWidth=1325&originalType=binary&ratio=1&rotation=0&showTitle=false&size=131949&status=done&style=none&taskId=u0af5fdb0-a140-407f-b91f-6feabd49d16&title=)

DMA_FLAG描述
DMA_FLAG_GL1通道 1 全局标志位
DMA_FLAG_TC1通道 1 传输完成标志位
DMA_FLAG_HT1通道 1 传输过半标志位
DMA_FLAG_TE1通道 1 传输错误标志位
DMA_FLAG_GL2通道 2 全局标志位
DMA_FLAG_TC2通道 2 传输完成标志位
DMA_FLAG_HT2通道 2 传输过半标志位
DMA_FLAG_TE2通道 2 传输错误标志位
DMA_FLAG_GL3通道 3 全局标志位
DMA_FLAG_TC3通道 3 传输完成标志位
DMA_FLAG_HT3通道 3 传输过半标志位
DMA_FLAG_TE3通道 3 传输错误标志位
DMA_FLAG_GL4通道 4 全局标志位
DMA_FLAG_TC4通道 4 传输完成标志位
DMA_FLAG_HT4通道 4 传输过半标志位
DMA_FLAG_TE4通道 4 传输错误标志位
DMA_FLAG_GL5通道 5 全局标志位
DMA_FLAG_TC5通道 5 传输完成标志位
DMA_FLAG_HT5通道 5 传输过半标志位
DMA_FLAG_TE5通道 5 传输错误标志位
DMA_FLAG_GL6通道 6 全局标志位
DMA_FLAG_TC6通道 6 传输完成标志位
DMA_FLAG_HT6通道 6 传输过半标志位
DMA_FLAG_TE6通道 6 传输错误标志位
DMA_FLAG_GL7通道 7 全局标志位
DMA_FLAG_TC7通道 7 传输完成标志位
DMA_FLAG_HT7通道 7 传输过半标志位
DMA_FLAG_TE7通道 7 传输错误标志位

DMA_ClearFlag

![image.png](https://img-blog.csdnimg.cn/img_convert/4ef6db59e91b7f47c3e43f649acbdb78.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u6284f786&margin=[object Object]&name=image.png&originHeight=431&originWidth=1295&originalType=binary&ratio=1&rotation=0&showTitle=false&size=141647&status=done&style=none&taskId=uf9218f04-09ad-4635-8f3f-19d23bcda40&title=)

DMA_GetITStatus

![image.png](https://img-blog.csdnimg.cn/img_convert/63cf52a5ae2c63eb94f6c9323ebc2239.png#clientId=ubffd8cfc-888a-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=185&id=u85272b5d&margin=[object Object]&name=image.png&originHeight=369&originWidth=1299&originalType=binary&ratio=1&rotation=0&showTitle=false&size=122150&status=done&style=none&taskId=uf4e235ce-0ad4-4b72-98d5-41ac2a8643a&title=&width=649.5)

DMA_ClearITPendingBit

函数名DMA_ClearITPendingBit
函数原形void DMA_ClearITPendingBit(u32 DMA_IT)
功能描述清除 DMA 通道 x 中断待处理标志位
输入参数DMA_IT:待清除的 DMA 中断待处理标志位
参阅 Section: DMA_IT 查阅更多该参数允许取值范围
输出参数
返回值
先决条件
被调用函数

例程

工程文件:DMA_Test.7z

工程描述

使用DMA方式,将内存中的数据发送到UART4串口。发送的同时关闭LED1。


Update 2022.1.3

其他程序:

*以下程序全部支持不定长收发

用于蓝牙的DMA串口收发

工程文件:DMA_Bluetooth_V1.0.7z

工程描述:

创建缓存区存储收发数据,全局结构体用于重置DMA(有待改进,可以用寄存器直接操作)

DMA串口收发改进版

工程文件:USARTDMA.7z

工程描述:

在上一版的基础上做了改进,函数使用更加合理,全局结构体也改掉了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

McDuck_Spirit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值