对于STM32的ADC模数转换器的介绍以及配置在文章《STM32单片机(六). 传感器的使用》中已经详细介绍,在本章节中主要介绍DAC数模转换器以及DMA的使用。& T. Y7 Y) o1 _/ L1 ^8 z9 M
- }# y1 _6 ?; q* B1、DAC转换
1 X6 B! L! x# m5 z1.1 数模转换器的介绍
3 [( V6 j# Q1 C* p# k1 d" oDAC(Digital to analog converter),数字模拟转换器,可以将数字信号转换为模拟信号。DAC可以输出电压模拟信号,用来去驱动其它器件。STM32F1中的DAC模块是由12位电压输出数模转换器,可以配置为8位或12位模式,也可以与DMA控制器配合使用。在12位模式下,数据可使用左对齐或右对齐方式;8位模式下,数据只有右对齐方式。DAC含有两个输出通道,每个通道各对应一个转换器。在双通道模式下,每个通道可进行单独的转换;当两个通道组合在一起同步执行更新操作时,也可同时进行转换。DAC可通过输入参考电压引脚VREF+来提高转换后的数据精度,对于DAC通道的模块框图如下所示:) F3 c+ Z: T- U R
7 M0 C. X- D) |$ c k0 @, a
+ \7 }+ S0 N7 q5 z6 E0 H
: Q( Z3 m" R4 x$ A3 m0 G7 x
1.2 DAC的配置步骤4 J, t# S4 B, ~, e W0 O, l
使用库函数对DAC进行配置需要使用到库文件stm32f10x_dac.h和stm32f10x_dac.c,详细的步骤如下:9 F, n7 E& z# `7 a* Z+ b
/ n7 e- A* S: b3 o- I1、 使能端口及DAC时钟,设置引脚为模拟输入模式;
/ A/ k; p, G+ x$ s8 s. L% @在STM32F103中DAC两个通道对应的是PA4和PA5引脚,因此需要使能GPIOA以及DAC时钟,DAC是挂载在APB1总线上的设备,GPIOA是挂载在APB2总线上的设备。调用函数:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使DA时钟8 h8 l) c1 h9 n5 B- M
g# |' v9 c9 F2、 初始化DAC,设置DAC工作模式;
$ W" f; L5 G1 g5 y! z w, y调用函数:void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct);2 a! k% o; a; c7 Z
第一个参数选取DAC通道(DAC_Channelx),第二个参数结构体DAC_InitTypeDef的成员变量如下:
+ _! ?: l( H [0 c+ [; `' `. u# M) g- D6 T
- typedef struct
h7 k9 \/ B4 ^ - {
- n6 W+ y( t1 [ - uint32_t DAC_Trigger; //DAC触发选择2 B6 z! [/ i, S3 E6 Y! d4 N* b
- uint32_t DAC_WaveGeneration; //DAC波形发生
- r# l# C. z# ? ?) Z5 }: `% W - uint32_t DAC_LFSRUnmask_TriangleAmplitude; //屏蔽/幅值选择器
- y# M+ l6 `: R2 m - uint32_t DAC_OutputBuffer; //DAC输出缓存
* a# ?2 D) r: x7 o4 S - }DAC_InitTypeDef;
复制代码 ! P4 `- x0 z' {1 t
3、 使能DAC输出通道;7 Q. D2 W F& @4 h9 B; W
调用函数:void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState);3 ?( I& x7 C% I* n) Z# O
4、 设置DAC输出值;$ O1 g% @% b, y" l9 ?$ t3 g1 J$ x
在使用12位数据右对齐的工作模式下,通过设置DHR12R1就可已在DAC输出引脚得到不同的电压值,调用函数:DAC_SetChannel1Data(DAC_Align_12b_R, 0);# y' d3 I! m2 {2 E* O/ ^+ x' o
读取DAC对应通道最后一次转换值调用函数:uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel);
3 e- |" R& J: W% Q9 C- [$ |) _, q. h( G
1.3 应用示例+ x2 }& i! D: X$ X7 X" n
STM32使用按键控制DAC输出电压的大小,并将该数据通过串口输出,详细的代码模块如下:. S5 v% H6 C/ d( i
dac.h
) n" Z! r. p, G, o: q- #ifndef _dac_H7 P5 ^1 U8 O( P# U
- #define _dac_H u3 X6 _7 O/ n, r- [8 P* Q
- [9 I1 h9 t; z. Y; {! |6 G: u1 l
- #include "system.h"( p. O4 M ]) H/ p# s6 I% D. j0 y: b
- void DAC1_Init(void);
3 h7 {0 @* r |9 n* `* K/ L
5 F# y7 V0 H& `( B- #endif
复制代码 ; R+ F0 V4 d0 Z) a
dac.c$ Z8 D2 b }. [% c9 s+ s
- #include "dac.h"
$ i. d$ F' D" k" B @/ I0 F! J - 8 p0 O& ]$ T( P5 s; t
- void DAC1_Init(void)
1 F! V8 C+ M6 i% C5 D4 { - {/ _" v: G. n. U5 a/ {: T
- GPIO_InitTypeDef GPIO_InitStructure;
2 a6 d) E3 b& t( Y - DAC_InitTypeDef DAC_InitStruct;
& }5 P- W7 u3 h+ E0 k# e - 4 [0 f) B/ t* w, j4 o+ ~* f
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);: g* H$ d7 L2 z0 K" A
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
0 m; k5 F% {( F. i
s; M6 M9 `$ H6 k8 `6 @* N) b- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
. y& n; v; |% T, j - GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
4 ~0 D, [) c1 W - GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;5 @3 I L! V3 b& |
- GPIO_Init(GPIOA,&GPIO_InitStructure);) \9 N4 r; D6 e& g) t
7 [! z9 f" u& L, G% t# X- DAC_InitStruct.DAC_Trigger=DAC_Trigger_None; //不使用触发6 E2 \0 F5 g/ C. o( L8 P+ l/ ]7 B" y, _
- DAC_InitStruct.DAC_WaveGeneration=DAC_WaveGeneration_None; //不使用波形输出/ M( x. a: \% c
- DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;0 Y% E. j' }. d( o* A2 [
- DAC_InitStruct.DAC_OutputBuffer=DAC_OutputBuffer_Disable; //关闭输出缓存& G K' e! d' [# v( J
- DAC_Init(DAC_Channel_1,&DAC_InitStruct);7 X. S9 ^, z2 S) a/ M
- 8 ~7 h6 S0 O' ~4 Z
- DAC_Cmd(DAC_Channel_1, ENABLE);
! Q; E8 D6 U6 z5 |5 Q5 {" e2 [9 O - DAC_SetChannel1Data(DAC_Align_12b_R,0); //初始电压值设置为0+ ~9 z! a( y+ w0 ` P
- }
复制代码
- j X/ F c# d5 F: h# Hmain.c! m# a' ~2 \% I$ f$ H* e1 g
- #include "system.h"+ y& [, G+ U9 u" C2 {+ Y
- #include "led.h"% B) A* n) f' _( D, K. f
- #include "SysTick.h"
, y9 i) }. i/ v - #include "usart.h"
! P2 C6 `0 s7 p - #include "key.h"
. g( C2 O4 A; W+ s$ w4 M4 \ - #include "dac.h"* d4 j# U1 R$ M2 N2 X
/ J" r8 U" I. L& V9 v: R0 r! Y- int main()
8 D; \/ r7 J$ W% [" D/ p& m - {# A% |- S) D3 q8 |
- u8 i=0;
9 ^. K' E# V, T& T X6 \) F. m - u8 key;
8 @5 f C: v8 l/ k( D# G+ J - u16 dacVal;
, s3 Q1 u- U0 _2 g3 ]% ] - u16 dac_value;
' G& g- N9 t0 i! ]0 }6 d: f z0 A. I - float U;
- {$ C! j4 t" q - SysTick_Init(72);
; k4 J2 {0 k- C - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);8 \; F1 r7 z2 Q; |1 i
- LED_Init();
/ s3 x5 q. f I1 q9 p8 R! D* G6 O - USART1_Init(9600);' S! t. p- g# _+ q
- DAC1_Init();" F. N5 T% C6 r1 Q; N: M' |
- KEY_Init();
. Q$ |. K& ~ |0 c- `3 w) i -
3 A5 S1 `0 U! \" m& d0 x - while(1)" D' m6 R L0 X- b# J
- {
! d6 D% P" |' V7 E# G - key=KEY_Scan(0);
; K8 {) ]% F) T3 q1 r - if(key==KEY_UP)
# I1 N [9 R0 D2 [' ] - {
1 u; I7 v6 V- f3 b1 E6 T - dacVal+=400;" ^; l5 f C% {. j$ U3 Y4 T: K
- if(dacVal>=4095)* }1 {8 V5 ~2 Z) z! C
- {
3 a p* l" W3 p - dacVal=4095;
. j( Q" R# U4 a - }
; W+ Q4 M: x$ h9 b6 g$ F- d - DAC_SetChannel1Data(DAC_Align_12b_R,dacVal); //更新电压
, d% p- F5 J4 Q - }. n) \3 f# m% b O' } u2 y
- else if(key==KEY_DOWN)
" m: w6 h- N8 `! L - {" Y6 U# O- f* v2 @' n! u
- dacVal-=400;2 P8 x: H: p" o, ^. T' h, K2 ~7 @
- if(dacVal<=0)0 f5 g/ H9 H \; O# b2 M" `
- {
5 J/ y' Z. ?/ h6 {2 c- @- v - dacVal=0;, G) C. r1 q$ o- F: Z. n. o3 B
- }0 {6 ]5 j' V# B/ x- ]2 O
- DAC_SetChannel1Data(DAC_Align_12b_R,dacVal);
: ~" B- h- b! s* @ ^4 [ - }
2 @# a8 _9 ?8 Y% y - i++;
/ } Z% M1 b# ?1 {9 @ - if(i%20==0)
1 t7 t- d4 O5 j( O4 [ - {
" _( z" T( G/ F - led1=!led1;* I' p2 w6 q6 N3 {( h" f
- }
+ X" I% N$ I" }8 e" W+ [ - if(i%50==0)
9 y! R2 z( ~. F# Q$ c - {
7 H: Y5 j6 i( @. h1 n2 |# A% W - dac_value=DAC_GetDataOutputValue(DAC_Channel_1);; S$ h6 G y0 x+ I) h
- U=(float)dac_value*(3.3/4096);% g1 b9 h, J8 |
- printf("输出电压为:%.2f\n",U);4 H) v) o! P. s% Y' X! O. Z/ J
- }
& E$ a: f0 a2 t% v! V) q - delay_ms(10);" z3 n4 U% K& x8 [! `
-
, H! N8 f$ P& `3 a - }' | p0 d/ { W4 x& d$ m9 e0 ]% z6 I
- }+ p; {: v5 }" ?' y$ K
复制代码 2、DMA数据传输; L' q# ?3 a* E$ {! V& q. ?
2.1 DMA的介绍
. I8 B* w1 }8 `; R. n2 \3 z" KDMA,Direct Memory Access,直接存储器访问。STM32中DMA可以实现外设与寄存器之间,存储器与存储器之间高效的数据传输,DMA传输数据的过程不需要CPU直接操作可以节省对CPU的占用。DMA是RAM和IO设备之间数据传输的通路,外设和存储器之间,存储器和存储器之间可以直接在通道上进行数据传输。在STM32F1中最多有2个DMA控制器(DMA2仅存在于大容量产品系列),DMA1有7个通道,DMA2有5个通道,每个通道可管理来自于一个或者多个外设对存储器访问的请求,面对这些请求通过一个仲裁器来协调其优先权。对于DMA的结构框图如下所示:4 ?. }* ~! L7 D6 q1 ~! _8 \9 b4 t
% K: Y! H' w( n. R* E. X6 N* W# c1 b" I
. b& a& Y2 d$ q6 F9 M- pDMA和Cortex-M3内核共享系统数据总线,当CPU和DMA同时访问相同的目标时,DMA会请求暂停CPU访问系统总线若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线带宽。( Q' I1 Y& b& A% n
DMA的处理过程: 当发生一个事件后,外设向DMA控制器发送一个请求信号,DMA控制器根据通道优先权处理请求。当DMA控制器开始访问发出请求的外设时,DMA控制器立即给其发送一个应答信号。外设从DMA得到应答信号后,外设立即释放请求,请求一旦被释放,DMA控制器同时撤销硬打信号。当有更多的请求时,外设可以启动下一个周期。4 [' F9 u& h) A/ ]7 A7 j5 J
DMA的数据配置: 外设到存储器,使用外设到存储器传输时,DMA外设寄存器的地址为外设的数据寄存器地址,DMA存储器的地址为用户自定义变量的地址;存储器到外设,使用存储器到外设的传输时,DMA外设寄存器地址对应的是其数据寄存器地址,DMA存储器地址为用户自定义变量(缓冲区,存储通过外设的数据)的地址;存储器到存储器,DMA外设寄存器地址为内部存储器(如Flash,可将其看作是外设)的地址,DMA存储器地址为用户自定义的变量(缓冲区,存储来自内部Flash的数据)的地址。DMA的传输完成分为两种模式,一次传输和循环传输。如果使用一次传输后DMA停止,若要在此传输,必须失能DMA后在重新配置方可继续传输;当使用循环传输时,一次传输完成后又再次恢复第一次传输时的配置进行数据传输,不断重复。
, ^( z& E0 e) s( o: Y3 Z( S% H& Y |) o' y* t
2.2 DMA的配置步骤
6 L; k: U. ]; {( N4 r q对于DMA的配置,需要使用到库函数文件stm32f10x_dma.h和stm32f10x_dma.c,详细的步骤如下所示:
) M1 m" j2 T# A7 h5 f4 B7 \) e6 n1、 使能DMA控制器时钟; e. X. R9 b( d" }+ I- R
使能DMA时钟,需要通过AHB1ENR寄存器控制,调用函数:void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);0 a1 }, d- N. z; u1 `4 ^
2、 初始化DMA通道;
* K/ `$ e$ }& @' u需要配置DMA的通道、外设和内存地址、通道优先级以及传输数据量等,调用函数:void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);* T" r6 m+ P6 T8 L- v; f6 O
其中第一个参数用于选择哪个DMA的通道x,第二个参数是一个结构体变量包含的成员变量如下:
9 }9 F. E8 l n* x; |8 E& }0 d& o1 a6 s6 q; G" e0 x. b h7 ^
- typedef struct{
, t7 D. \8 ?1 M8 n! j |' f - uint32_t DMA_PeripheralBaseAddr; // 外设地址
$ [% v& C: g- z) B' v& g5 e - uint32_t DMA_MemoryBaseAddr; // 存储器地址7 V" t2 E) \0 k8 [$ A7 j$ y! H. n
- uint32_t DMA_DIR; // 传输方向% D& q0 z4 Y' c: x
- uint32_t DMA_BufferSize; // 传输数目( o8 M0 e; ^- b) s _! ?' E
- uint32_t DMA_PeripheralInc; // 外设地址增量模式
~) k: Y0 ]- }# ^/ R - uint32_t DMA_MemoryInc; // 存储器地址增量模式
7 C; {3 i5 S+ |- Q - uint32_t DMA_PeripheralDataSize; // 外设数据宽度+ O% z0 q6 Q+ |1 v& J( ]
- uint32_t DMA_MemoryDataSize; // 存储器数据宽度
1 D/ s$ H8 {3 v! P/ y `" m# H - uint32_t DMA_Mode; // 模式选择
) R a5 d+ s+ V9 F9 j. ^$ e - uint32_t DMA_Mode; // 模式选择
, K$ D+ N4 [! h' Y6 y" ` - uint32_t DMA_M2M; // 存储器到存储器模式
: }& R# b& i8 A - } DMA_InitTypeDef;
复制代码
6 h: }) V8 d, ~) y& F5 ^3、 使能外设DMA功能;+ @9 W' ]6 b J/ M3 i8 r) R# |
配置好DMA后,需要使能外设的DMA功能,根据使用外设的不同调用相应的函数,如使能串口DMA的发送功能需要调用:USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);* z5 p4 u' c* P# S C
4、 开启DMA通道传输;1 b7 {) d& ]) q$ \# `" G
调用函数:void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Chammelx, FunctionalState NewState);/ _; ?& O- n4 U; _" t% H. l
5、 查询DMA传输状态。
5 P6 i& a% k& T! E6 t& m7 S' Y2 g查询状态调用函数:FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);7 t- t! H, j/ D4 C8 ]
获取当前传输剩余数据量大小调用函数:uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);2 X! J# x4 W6 H8 Q) U
设置传输数据量大小调用函数:void DMA_SeyCurrDatatCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber);
' b( m4 [1 x4 V7 B2 |9 g0 `* g8 d) ]2 I; S& _4 E
2.3 应用示例+ q: y3 Q0 E" h4 ?: I
STM32使用按键控制DMA串口USART1的数据传送,详细的代码模块如下: s: I/ g8 Z* `9 s ?6 W3 h( b
2 ?! _: |2 g8 S# L3 B2 g. n
dma.h
7 ~- @, S: Z% z- #ifndef _dma_H) B* c7 ^7 p( f
- #define _dma_H
T4 N' C! Q5 R5 x
, ]/ N6 a# l. v* \3 p! @- #include "system.h"7 |: R+ z, L) H& t. n0 p1 X
- void DMAx_Init(u32 paddr,u32 maddr,u16 buffsize,DMA_Channel_TypeDef* DMAy_Channelx);5 ^! q1 t, G; W F9 z
- void DMAx_Enable(DMA_Channel_TypeDef* DMAy_Channelx,u16 ndtr);# ?7 O( F% `9 n3 Y
- #endif
复制代码 3 w3 l* b; Y j* ]
dma.c/ ?: @3 B( }$ N6 \+ |) _$ q$ V
5 p/ V3 f$ m) ?6 f+ j- #include "dma.h"0 p3 ^, T2 v; v1 T
' s6 Q- g" k/ j, c( x- void DMAx_Init(u32 paddr,u32 maddr,u16 buffsize,DMA_Channel_TypeDef* DMAy_Channelx)5 u1 n S2 J$ T9 a1 J7 }; @
- {) P( }3 Q2 f& n1 e$ C5 G
-
7 W. c4 f$ p l1 V' K i, a" K( @" q - DMA_InitTypeDef DMA_InitStruct;
, s, D C/ ~8 T% ?; e) \ -
! _+ t2 k5 K& S; R8 `& w* e* s. H - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
; T. \9 o1 t2 m& u) y' K7 X# R - ( c! d' T( d1 d$ d* ^% ?* c
- DMA_InitStruct.DMA_PeripheralBaseAddr=paddr; //外设地址
( f) v" `- G. U/ l; L1 \" N. k - DMA_InitStruct.DMA_MemoryBaseAddr=maddr; //内存地址 a. P* p: F4 b
- DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralDST; //存储器到外设' J: K9 K! c- l" X3 g) P
- DMA_InitStruct.DMA_BufferSize=buffsize; //传输数据量大小
1 u) |7 u9 N* n4 y - DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable; //外设地址不增
& p* U5 Q5 r( R) @6 @3 n8 o7 e - DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable; //内存地址自增
8 E: B6 F- [& L# N& z - DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte; //外设数据单位
# C! N* J& c, U1 W% t - DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte; //内存数据单位
) f- B% {* b2 b% W - DMA_InitStruct.DMA_Mode=DMA_Mode_Normal; //一次传输' P8 n4 L( i1 S$ a2 M
- DMA_InitStruct.DMA_Priority=DMA_Priority_Medium; //通道优先级中
; \! {# c5 P C) I - DMA_InitStruct.DMA_M2M=DMA_M2M_Disable; //存储器到存储器失能
, p- @! K1 P% V( U' u4 @0 y5 D- M4 j -
6 S# T6 D5 W9 |% y/ [! ? D% a - DMA_Init(DMAy_Channelx,&DMA_InitStruct);+ @5 h$ V7 u* A. J
-
: ^" a R- D T; Z: ] - }3 r/ i: I* c% L& K: t8 \" P
- void DMAx_Enable(DMA_Channel_TypeDef* DMAy_Channelx,u16 ndtr)
5 h$ c1 c3 O* F; q, ]6 b9 R M( Y - {
, L) N* W/ R' Q! j4 @8 [+ `0 z$ g - DMA_Cmd(DMAy_Channelx, DISABLE);
' ?$ ^7 k0 ]- g" b. r1 } - DMA_SetCurrDataCounter(DMAy_Channelx,ndtr);, T. b8 h5 A# q2 s% @
- DMA_Cmd(DMAy_Channelx, ENABLE);
7 U' ^" o- }, H1 I/ @' `+ F - }
复制代码
7 N- R- d$ e/ }( Y. nmain.c
6 L4 J0 C, r0 J! t# F# I; W
# R9 A z8 D5 J; Q6 |, ^- #include "system.h"
5 Q$ h4 r. V) y - #include "led.h"
. h5 l- K# J$ K7 n - #include "SysTick.h"
- m- f8 x, t' B! J0 I% m0 e - #include "usart.h"
2 c m! {' k% Q6 k! m - #include "key.h"
8 v F7 L, a0 Z7 g - #include "dma.h"
: {1 B8 R3 K# U! w+ V - #define buf_len 5000
4 L7 e) b! O2 [9 A
3 n" |2 t S1 k* Y( S- / \6 A; q3 E% V+ t6 @. x# [ j: R' a' W
- u8 sendBuffer[buf_len];. A. a7 h. W2 j M5 E
& z& n# N) m% J- d$ e6 u3 N X- void send_Data(u8 *p)
5 C9 x. v6 A" I5 H - {
1 c9 l. E" ]/ ^# j9 R0 J - u16 i; P0 p) F+ L8 A' J8 k2 u
- for(i=0;i<buf_len;i++)
! i, y0 R$ @; o& y - {
9 T2 E0 |' V" z, }8 o, F - *p='5';3 a; _- P+ {, @# o& Z
- p++;1 d" g+ O6 q7 g
- }
7 J' t3 }- E) v - }
; w0 l! W5 f' I# i" d - ; B( A- m7 n0 B8 V* K: {
- int main()8 T# m) ]! n# v
- {, L6 U: y7 w! K4 G3 y
- u8 i=0;5 A- P p8 p4 F( O* R
- u8 key;
5 s1 u0 x3 Q* `. Q2 L7 ? - 4 `- a3 J( i7 R9 R( d
- SysTick_Init(72);
& l3 F" a- L1 h7 j* @ - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
( p" N' Y3 A1 k# g - LED_Init();/ ?2 `! k6 o7 b7 p s' J! E
- USART1_Init(9600);# X) U7 `, j. N9 v) c+ V- o, z5 \
- KEY_Init();; w+ G# W8 E) ]* I6 A; C/ U9 k% x
- DMAx_Init((u32)&USART1->DR,(u32)sendBuffer,buf_len,DMA1_Channel4);0 |% _ w( c2 C6 e+ y5 p
- send_Data(sendBuffer);+ O" F- F ]9 o8 @+ C" U( I: i/ W
-
4 z" C+ U( O7 k - while(1)2 T4 h" \$ E t% U* h2 g: `
- {
& M! P5 Z1 Y( g& Y - key=KEY_Scan(0);, A$ F9 a! \8 i! W3 O* ?# h$ y6 `0 j
- if(key==KEY_UP)
1 [6 o% ^' ~& J- `9 h6 I1 l% W - {
+ P7 w& f, j9 p& l' f! q/ t - USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //开启外设DMA功能& n& W, v% ]1 f
- DMAx_Enable(DMA1_Channel4,buf_len);# U. J- f' n4 q5 A; u
-
* t8 g- y/ b' |* v - while(1)
5 _) n( h( b$ E0 } W - {, e/ j" S+ a) E0 {
- if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=0) //判断DMA数据是否发送完成
& }# n; [# m* M - {
$ h9 L9 x3 F" _; e. X' R - DMA_ClearFlag(DMA1_FLAG_TC4);
3 g |( w8 v& y+ _ - break;
! A5 `- Q+ s1 K4 I ~1 N - }( P, `, A8 {4 r; P
- led2=!led2;
2 ]6 W5 _! g& } - delay_ms(300);
5 ?& B% A! k+ w V - }' r F: Q* f3 _+ V. H% V0 @6 X
- }
! q! Q7 A _5 B - i++;
0 S$ h% t: o1 D - if(i%20==0)) ?* c' w6 f9 L/ A0 g- x! E; {& S
- {" }! V1 C& r. S' V& r' G2 B! j3 P
- led1=!led1;
- Z( q8 b, G$ y6 _9 q - }
4 H, l; q; @) l - delay_ms(10);% ?1 ?: C" w. r. G$ A: U
- }( V2 \5 x& u; k6 }, U# k' c) Q
- }
复制代码 , W& U! r2 o% k8 g
+ j/ K3 T2 @( b+ {
) r( e' M" w" S0 s. ?( n
; w* u1 {# O: w. m q" } y% G ]; `5 Q) ]6 D4 u9 A4 C) C
4 |/ ^% U5 n! y! F& _& z( t
) [# a0 v3 k( b- }
! p& o' ]7 _: o+ }9 n
& T. _8 ^0 U8 y; O# w
% G( M7 Q: O* C |