对于STM32的ADC模数转换器的介绍以及配置在文章《STM32单片机(六). 传感器的使用》中已经详细介绍,在本章节中主要介绍DAC数模转换器以及DMA的使用。1 F: Q+ Q4 j% J3 ^- \; i6 H( J
& `: ~! e8 T3 ~$ S1 O/ ?
1、DAC转换" h, W8 Y; i9 H2 |" `; o* S0 ~
1.1 数模转换器的介绍) ^8 s& J4 |1 c. i" @- l p: @3 a
DAC(Digital to analog converter),数字模拟转换器,可以将数字信号转换为模拟信号。DAC可以输出电压模拟信号,用来去驱动其它器件。STM32F1中的DAC模块是由12位电压输出数模转换器,可以配置为8位或12位模式,也可以与DMA控制器配合使用。在12位模式下,数据可使用左对齐或右对齐方式;8位模式下,数据只有右对齐方式。DAC含有两个输出通道,每个通道各对应一个转换器。在双通道模式下,每个通道可进行单独的转换;当两个通道组合在一起同步执行更新操作时,也可同时进行转换。DAC可通过输入参考电压引脚VREF+来提高转换后的数据精度,对于DAC通道的模块框图如下所示:
! A* `( z5 d2 g; `$ b: u; F6 g, c7 m' j
2 V, ?. T# v% I! X0 R# s
! M% y5 i9 y1 ~2 E( d3 x A1.2 DAC的配置步骤( {2 ?2 ]+ W9 {' Z9 Y% S3 y3 Y
使用库函数对DAC进行配置需要使用到库文件stm32f10x_dac.h和stm32f10x_dac.c,详细的步骤如下:4 M7 Z8 \. P9 K8 } o; @. V: P' j
. H6 Y9 e' p+ G: C
1、 使能端口及DAC时钟,设置引脚为模拟输入模式;. ]9 n- R( A, \3 N' O3 B+ C' C9 |
在STM32F103中DAC两个通道对应的是PA4和PA5引脚,因此需要使能GPIOA以及DAC时钟,DAC是挂载在APB1总线上的设备,GPIOA是挂载在APB2总线上的设备。调用函数:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使DA时钟
; H4 x8 C# d' ?; N# Z
) l+ Q) D' \% ^9 E2、 初始化DAC,设置DAC工作模式;. K6 E: L7 d+ M7 M
调用函数:void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct);% l; {" R/ Z, F6 {0 x1 r+ u+ a4 N- L
第一个参数选取DAC通道(DAC_Channelx),第二个参数结构体DAC_InitTypeDef的成员变量如下:; w/ z! Q# {( f: H8 V
8 N, A5 ]3 L& L% f2 m7 n6 X5 u
- typedef struct
3 s- z* J+ B% Q. Z - {
) C: }; o1 L+ W0 u( A4 G - uint32_t DAC_Trigger; //DAC触发选择
X' I B! Z( W+ I3 M6 N; D m. { - uint32_t DAC_WaveGeneration; //DAC波形发生3 _* u7 f, g6 g/ o8 B
- uint32_t DAC_LFSRUnmask_TriangleAmplitude; //屏蔽/幅值选择器4 ?( `8 O2 Q' j
- uint32_t DAC_OutputBuffer; //DAC输出缓存, L- E2 _ d* d. K; n R
- }DAC_InitTypeDef;
复制代码
I7 |: R" @2 F* ^" {9 F3、 使能DAC输出通道;
. {% y W* J. i1 m调用函数:void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState);5 M, K0 x- i6 e3 O
4、 设置DAC输出值;5 y6 p T3 K3 J; T8 w& c
在使用12位数据右对齐的工作模式下,通过设置DHR12R1就可已在DAC输出引脚得到不同的电压值,调用函数:DAC_SetChannel1Data(DAC_Align_12b_R, 0);
+ S7 Q' N# y5 y A( D/ e读取DAC对应通道最后一次转换值调用函数:uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel);. d: o% c3 B4 S! ~" q/ S: E0 Z; X
5 n) N- A. a" o }$ d4 S1 R
1.3 应用示例$ } P# R+ U2 l ]* Q, n
STM32使用按键控制DAC输出电压的大小,并将该数据通过串口输出,详细的代码模块如下:
: p9 }/ e3 u& X' F( idac.h
; o/ W9 a" R5 }5 n6 U- #ifndef _dac_H
+ x4 p" l: A4 X* M4 y8 H - #define _dac_H
& W; y5 w6 r5 H0 N
' X: ^/ I) R0 [8 t" V/ B- F- #include "system.h"
& q# R. A8 \. ~7 k& B4 K' k - void DAC1_Init(void);
$ q& C* K2 v* O - W6 O+ t& A( X7 x
- #endif
复制代码 % H( ]! q( v: ]6 w- H1 _
dac.c1 w, V) _5 P5 L6 H1 _
- #include "dac.h"
& [4 q7 K g4 B% _# W$ P
! l6 G6 F9 t7 G0 |: B$ ?+ |; U! H0 [- void DAC1_Init(void)5 _# Q5 q$ E7 K, Y8 O
- {+ Q7 \2 B5 L$ z. t3 W7 l2 P
- GPIO_InitTypeDef GPIO_InitStructure;3 P8 L4 i% \ v0 O/ ~# u! [. v% E! Y
- DAC_InitTypeDef DAC_InitStruct;
+ D- k+ T5 X! \8 c - 5 r) G9 O4 G* ?& h0 N
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);; K# a; a- o8 M# P3 ]7 h& l
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC,ENABLE);
* J, j1 \, G& S9 x5 r: {5 E b! q, R+ }" g
/ _; K* E0 l% r; o- Q" Y- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
; M# V7 U$ E, f! e9 q! ~ - GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;6 V; r# S6 g* [9 T
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;3 n6 Y# f; |1 Z2 T# p `8 z N
- GPIO_Init(GPIOA,&GPIO_InitStructure);3 s! @4 m( N) P8 p- X
8 y+ J( i- Z! U) U" y# @- DAC_InitStruct.DAC_Trigger=DAC_Trigger_None; //不使用触发: J9 A. t! h6 \! ^3 L% @
- DAC_InitStruct.DAC_WaveGeneration=DAC_WaveGeneration_None; //不使用波形输出
" B( f, x# g& r - DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;
: o- q6 G" ]1 g& K7 [, A - DAC_InitStruct.DAC_OutputBuffer=DAC_OutputBuffer_Disable; //关闭输出缓存
/ r, t8 `* g; Z$ T( D; l - DAC_Init(DAC_Channel_1,&DAC_InitStruct);
0 M. b g8 R" s9 l; ^
2 r/ T4 [6 X, Z% B2 ]+ ]% l- DAC_Cmd(DAC_Channel_1, ENABLE);! P% k; v2 C: `; h- v
- DAC_SetChannel1Data(DAC_Align_12b_R,0); //初始电压值设置为0
( b- s5 }4 i1 H8 w - }
复制代码
- I/ d; s% e7 [# emain.c; D1 a- b! }+ [; ^7 _2 P8 N- n3 c1 h
- #include "system.h": g0 I7 ^$ }- V5 M; z
- #include "led.h"& e& Q; l% V% N! O2 E. S* E& Z
- #include "SysTick.h"
$ R- u. c5 ]! Z+ f) x: ^: F - #include "usart.h"
6 p. {% g) V) L1 [2 C, u. E u - #include "key.h"
% e, {1 z; d! C/ H3 V; { - #include "dac.h"
4 u% w3 |! v* B2 P3 y; ~9 V
9 g0 l& `6 e3 ]& [- int main()- y4 a: S2 T8 ~: _: F
- {3 o4 t, q# ~5 i) s3 y
- u8 i=0;! H. @$ T6 C r5 w9 y1 ~
- u8 key;
, }" i& d! i6 J6 A - u16 dacVal;5 I4 C5 F3 u( d
- u16 dac_value;: h1 b& `* l9 G0 ~' Y) W
- float U;* J1 f( u& v8 U4 A: s* A
- SysTick_Init(72);* X# ~# b7 F/ |3 V/ i
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);9 J! a) }8 V1 I/ ?, Q; L
- LED_Init();% o/ V& y& @* i# E- H
- USART1_Init(9600);
4 G5 j8 O5 y+ B v* X+ S - DAC1_Init();
+ F. l o6 m7 Q2 E% K. w+ v - KEY_Init();
. ^4 k) L c; Z: z& a8 E - - U6 z8 ]$ Q' O7 c
- while(1)
( V& G2 T. M, u- N1 V6 {2 F - {
; D& ]9 o; N# M. ]4 o - key=KEY_Scan(0);
$ |7 g2 {* t: ?3 E, O% J - if(key==KEY_UP)- }* d( o; |: W+ N- i P6 z3 I
- {) C& `. u \& K: {: x: v0 M
- dacVal+=400;
9 `+ H( q, f9 m% n# O: j - if(dacVal>=4095)
# @& I7 `4 R4 h* f/ j/ F; ~8 S - {1 Z5 P+ R4 F: d) S% X
- dacVal=4095;" y" |6 S/ F! S- m
- }" s& I. Z5 O* k( Y p& M; c, J
- DAC_SetChannel1Data(DAC_Align_12b_R,dacVal); //更新电压
# s% j! X( ~ i Y# O - } n* k6 k- y, j# {$ E
- else if(key==KEY_DOWN)
5 `0 Q7 k( P0 E8 O - {5 a* j8 E$ z% q' y+ {
- dacVal-=400;
* E) W2 z; d# y" |/ D, a - if(dacVal<=0)5 x0 w3 h7 p _8 |" q0 l9 C
- {
1 I8 V" {: [8 l) K - dacVal=0;5 M! G1 m6 E* f8 w$ C
- }" B. f1 h! ]9 ~8 _
- DAC_SetChannel1Data(DAC_Align_12b_R,dacVal);
+ u: @3 \/ z- @% q X - }
% k! y( r: g1 U - i++;: s( E- s! s) E# U/ U# q4 K7 p
- if(i%20==0)
3 k+ n1 d( X7 U* A+ l @( N - {
- B. l& q' U/ _5 J - led1=!led1;
5 G# ]- I5 e7 A( P+ n - }
3 R3 Y6 m) c8 n: K2 i& G7 O - if(i%50==0)
3 P1 q* q) [) g) Q( {. G4 j - {
% L; X4 {3 K- G - dac_value=DAC_GetDataOutputValue(DAC_Channel_1);. {5 i5 |& O: `. [1 x
- U=(float)dac_value*(3.3/4096);& N( G) E( ^$ v. ]) A2 p3 d9 A
- printf("输出电压为:%.2f\n",U);4 {" p8 x% U4 Z" ]2 K8 A M
- }
; k* E5 N+ @+ ~ - delay_ms(10);9 o8 u; b1 g, ~0 L9 \0 [1 t
- 6 b* `0 J7 V7 l6 P" U- ~$ F, D' ^
- }
g5 t4 w) x* _9 w1 Z - }" U* J) [) q) J
复制代码 2、DMA数据传输
3 U# Z9 e( r% i4 S, O7 [2.1 DMA的介绍
: [+ R, `+ r5 mDMA,Direct Memory Access,直接存储器访问。STM32中DMA可以实现外设与寄存器之间,存储器与存储器之间高效的数据传输,DMA传输数据的过程不需要CPU直接操作可以节省对CPU的占用。DMA是RAM和IO设备之间数据传输的通路,外设和存储器之间,存储器和存储器之间可以直接在通道上进行数据传输。在STM32F1中最多有2个DMA控制器(DMA2仅存在于大容量产品系列),DMA1有7个通道,DMA2有5个通道,每个通道可管理来自于一个或者多个外设对存储器访问的请求,面对这些请求通过一个仲裁器来协调其优先权。对于DMA的结构框图如下所示:
R, F$ r% ]" b$ t
" U7 E* x+ U. @; w7 y4 F
( Q/ \2 x/ k& N+ F
DMA和Cortex-M3内核共享系统数据总线,当CPU和DMA同时访问相同的目标时,DMA会请求暂停CPU访问系统总线若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线带宽。$ g6 O X$ @' G) R1 C0 \4 S. x+ ?" H
DMA的处理过程: 当发生一个事件后,外设向DMA控制器发送一个请求信号,DMA控制器根据通道优先权处理请求。当DMA控制器开始访问发出请求的外设时,DMA控制器立即给其发送一个应答信号。外设从DMA得到应答信号后,外设立即释放请求,请求一旦被释放,DMA控制器同时撤销硬打信号。当有更多的请求时,外设可以启动下一个周期。! H8 k6 h# M% ~4 r( {
DMA的数据配置: 外设到存储器,使用外设到存储器传输时,DMA外设寄存器的地址为外设的数据寄存器地址,DMA存储器的地址为用户自定义变量的地址;存储器到外设,使用存储器到外设的传输时,DMA外设寄存器地址对应的是其数据寄存器地址,DMA存储器地址为用户自定义变量(缓冲区,存储通过外设的数据)的地址;存储器到存储器,DMA外设寄存器地址为内部存储器(如Flash,可将其看作是外设)的地址,DMA存储器地址为用户自定义的变量(缓冲区,存储来自内部Flash的数据)的地址。DMA的传输完成分为两种模式,一次传输和循环传输。如果使用一次传输后DMA停止,若要在此传输,必须失能DMA后在重新配置方可继续传输;当使用循环传输时,一次传输完成后又再次恢复第一次传输时的配置进行数据传输,不断重复。& O, w) g; A2 o4 h1 r' h
$ o, N- K, a* Y2.2 DMA的配置步骤5 i0 X0 ^9 O, {# s% n
对于DMA的配置,需要使用到库函数文件stm32f10x_dma.h和stm32f10x_dma.c,详细的步骤如下所示:
$ u0 w+ p( J2 N1、 使能DMA控制器时钟;% v# D [- \& l( k; M9 m
使能DMA时钟,需要通过AHB1ENR寄存器控制,调用函数:void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);( }: K& ~2 _! F2 d6 M, l. a" [
2、 初始化DMA通道;
- Y) k/ u- c8 S8 H需要配置DMA的通道、外设和内存地址、通道优先级以及传输数据量等,调用函数:void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);5 Q2 Q0 ]/ l u. \, ]' X
其中第一个参数用于选择哪个DMA的通道x,第二个参数是一个结构体变量包含的成员变量如下:
B1 D E" @ x1 k u: ^ ~0 W' ^% @+ t% M4 |/ k
- typedef struct{
& {, F6 q+ I V% ~4 C$ u& Y j - uint32_t DMA_PeripheralBaseAddr; // 外设地址' u* W) D- c& M, U
- uint32_t DMA_MemoryBaseAddr; // 存储器地址
, R7 y+ E0 n7 d/ \- k2 q" G* L3 H - uint32_t DMA_DIR; // 传输方向
4 c( ~ N0 H s2 a( _ - uint32_t DMA_BufferSize; // 传输数目
) y9 I' Z9 x' y6 U" \ - uint32_t DMA_PeripheralInc; // 外设地址增量模式
8 z0 M `7 @, q/ a - uint32_t DMA_MemoryInc; // 存储器地址增量模式
/ f+ h H Q; R$ g/ A - uint32_t DMA_PeripheralDataSize; // 外设数据宽度
# y5 @* v- P) ]6 n) q4 Z. M - uint32_t DMA_MemoryDataSize; // 存储器数据宽度
% U N& V* Q( s3 [ - uint32_t DMA_Mode; // 模式选择0 V6 i4 ]) E* L
- uint32_t DMA_Mode; // 模式选择 K2 k9 I3 _0 g9 a' Q `% D
- uint32_t DMA_M2M; // 存储器到存储器模式3 F7 k' U) c4 R1 u# O$ l
- } DMA_InitTypeDef;
复制代码
' L0 G0 U" \: J9 |& e X3、 使能外设DMA功能;
C. ~6 W" ^3 r% z% y' D配置好DMA后,需要使能外设的DMA功能,根据使用外设的不同调用相应的函数,如使能串口DMA的发送功能需要调用:USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);1 C$ x. z4 n3 S
4、 开启DMA通道传输;# j+ a2 P+ T! `! {! \, n
调用函数:void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Chammelx, FunctionalState NewState);
( b) n# m& o' V- r% \8 H5、 查询DMA传输状态。
( f: `' J# t6 } @; g2 k查询状态调用函数:FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);6 H8 {+ Y. E! H* C9 q, e2 l0 f+ N, ?
获取当前传输剩余数据量大小调用函数:uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
: S6 A W( N8 {& q U! K设置传输数据量大小调用函数:void DMA_SeyCurrDatatCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber);- ~* y ] G, z/ [
% s) L- }; A1 U* v8 A2.3 应用示例4 H! Y4 I5 O1 T- a* e
STM32使用按键控制DMA串口USART1的数据传送,详细的代码模块如下: S6 }: R4 W& e! I5 N3 e
: ]0 [! s2 I- ]$ h+ M; U
dma.h7 |+ W3 m, V+ c' a L
- #ifndef _dma_H) @7 O, k) O' v4 T& m! f. K
- #define _dma_H
& `) D3 X* b9 R/ H
' P7 X- X) }! k5 C6 A- #include "system.h"
) s+ y' ?. g8 _; `$ }9 a, T - void DMAx_Init(u32 paddr,u32 maddr,u16 buffsize,DMA_Channel_TypeDef* DMAy_Channelx);8 R4 z# a6 i/ T3 s
- void DMAx_Enable(DMA_Channel_TypeDef* DMAy_Channelx,u16 ndtr);
Z y' ]& E" x( M3 U - #endif
复制代码
% E) S0 [. p$ M) B v& E$ D6 _dma.c
# ]5 J) h9 }- N" V8 V. U. ?/ ]. p% P7 v
- #include "dma.h"- L1 \# Y, q, N8 V
- 7 j2 u/ W) f; N
- void DMAx_Init(u32 paddr,u32 maddr,u16 buffsize,DMA_Channel_TypeDef* DMAy_Channelx)
7 z3 \3 ?6 `" s/ |/ ?6 K - {
% ]' G5 H$ A% T/ O -
: g$ _2 c4 c: I I - DMA_InitTypeDef DMA_InitStruct;
( [& j8 ]3 J+ @. I) y - ( E2 Q2 k# O+ H- M- n
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
% s5 U' w* ?7 a' P* J6 j1 c -
2 z0 u# S4 m( F" x - DMA_InitStruct.DMA_PeripheralBaseAddr=paddr; //外设地址) e a1 h) F% w; e8 Q' O& }
- DMA_InitStruct.DMA_MemoryBaseAddr=maddr; //内存地址 I1 e$ L3 q* k7 T
- DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralDST; //存储器到外设
6 d/ c! r* P& P3 O( M" x& p w - DMA_InitStruct.DMA_BufferSize=buffsize; //传输数据量大小. K/ X! F' x" V3 P% t1 G- I L
- DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable; //外设地址不增
. @4 }, n. @% @ - DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable; //内存地址自增: d4 M3 l: ?8 W* w$ B2 J$ c
- DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte; //外设数据单位6 A m# R) q4 K
- DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte; //内存数据单位
; X/ I- C! @+ s. ~; V - DMA_InitStruct.DMA_Mode=DMA_Mode_Normal; //一次传输0 f$ s$ x2 U$ N: U
- DMA_InitStruct.DMA_Priority=DMA_Priority_Medium; //通道优先级中
) m* z9 ~7 W+ o2 j4 E - DMA_InitStruct.DMA_M2M=DMA_M2M_Disable; //存储器到存储器失能
- l: _/ V; \( m' ^; I. w5 L -
* e& x2 s+ Q/ R/ G - DMA_Init(DMAy_Channelx,&DMA_InitStruct);
6 o+ m I( ?1 P+ Q% I* D -
6 L3 b# e: I; O& W8 S" I - }' u0 u6 c6 [- r! N! X$ q8 E
- void DMAx_Enable(DMA_Channel_TypeDef* DMAy_Channelx,u16 ndtr)
6 n: M! p, K" I1 |: } - {' U& I' g: i3 r1 a4 ]
- DMA_Cmd(DMAy_Channelx, DISABLE);
- x" T7 r, k. R7 r0 r - DMA_SetCurrDataCounter(DMAy_Channelx,ndtr);$ @: z/ s5 I7 i4 N# C+ i
- DMA_Cmd(DMAy_Channelx, ENABLE);
7 i! e. M6 U+ o, {* H3 G - }
复制代码
) x0 G0 a7 T Z' K. r+ Pmain.c4 A* O! f8 Z/ @( p. W+ N2 V2 A
: m# D1 `- Y# i! X* J- a
- #include "system.h"9 W/ I+ v- g' t; c5 v
- #include "led.h"$ M* ]9 Z# p8 e% O' ^( P. c, h
- #include "SysTick.h"6 U2 B1 _1 @1 }( G
- #include "usart.h"
, e ~6 @* Z: }* E. v - #include "key.h"
" @2 z( A" G j2 v) y' g3 h+ c - #include "dma.h"1 G( y4 e8 S( R* {% K
- #define buf_len 5000$ S; u) \9 Y7 I
& R7 X; s e9 T' g- 9 ^: z# N# S% C$ y3 O- d3 @8 D
- u8 sendBuffer[buf_len];, ^0 q1 A D8 |) O/ H
p, ~; y2 ~( s' z4 U% D- void send_Data(u8 *p)
* N" c. w% `/ D$ h - {0 t7 `( g; t3 V# y) m1 q
- u16 i;
I4 \. [% n% R5 Z - for(i=0;i<buf_len;i++)* q/ m, b" l* d& B. [4 |
- {
) u- A( O. p) O' @ - *p='5';+ {8 x4 v( o0 ^# y' t
- p++;+ Z# ^4 e2 @9 ^0 d
- }
) B2 ]% p k% r X4 \ - }
5 ?% Y" g3 G: x - , M0 N% F" w" L
- int main()
: j8 U }# a3 f! z3 g* a1 z: S - {# j: A {! v% w" h* D* E, h
- u8 i=0;3 a5 [+ e4 O8 t, g2 H
- u8 key;
/ U/ ]4 J1 e9 ~* K" t& Q - 7 T* o; R5 d' B8 P: y- [
- SysTick_Init(72);7 p7 W$ {' b, z
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
; M/ q, U- ]% I7 u+ D - LED_Init();" A/ K7 b9 T6 i9 ^
- USART1_Init(9600);6 X1 M( A3 V; ]" ?+ L! p8 P& T
- KEY_Init();7 S/ s% R* }6 P' Y7 p4 s1 P
- DMAx_Init((u32)&USART1->DR,(u32)sendBuffer,buf_len,DMA1_Channel4);
# u# H3 y( X0 n% q: V* g" \ - send_Data(sendBuffer);3 ^9 b5 a! l, c+ `+ C3 i6 z2 a
-
* Y; n' L* @6 s H9 V, u( X& l - while(1)0 b8 r2 q4 m3 o/ a
- {
7 N1 d( g/ a% Y: S! {1 [) w$ x - key=KEY_Scan(0);. \1 U/ {6 |( z6 W# S
- if(key==KEY_UP)) x" L) p4 C1 T1 m0 M
- {
+ ?/ J8 M' C1 q" s$ N* m" x - USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //开启外设DMA功能, U0 T/ K6 a% K' y; ]5 v7 p7 E
- DMAx_Enable(DMA1_Channel4,buf_len);1 V3 q% d8 U0 s6 T$ ]% k
-
- X" J; X) `) ^: [ - while(1)
; i# z! i" u) q& K- [1 T) b" N - {
& |( I5 x) e- R - if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=0) //判断DMA数据是否发送完成
. F3 ]0 B8 w5 [1 v5 J - {
& h; w% Z& t4 t9 V9 x3 f- y7 Z - DMA_ClearFlag(DMA1_FLAG_TC4);
$ B! B, e5 K c: T6 _6 a- K - break;
7 j2 R7 ], Q% A1 M& X8 \% P5 P - }
. o) e7 I3 ?0 Y" M4 ` - led2=!led2;
& |6 s2 P p7 g7 H: W - delay_ms(300);
! {- F4 |3 [/ y - }; _( I: Q* G; [1 c
- }* ^: V" b" c. r/ C$ P. }5 q8 j$ m3 T0 h
- i++;
$ L/ C, Y) @: F9 m$ \8 U - if(i%20==0). {1 E: D3 C& Z- T
- {: p+ p! k- B) C4 ]0 f
- led1=!led1;
4 i% m$ f+ R5 W" E/ k: d - }
: R5 i; }- Q7 _ - delay_ms(10);, e/ Z4 v2 B+ r1 _* ^2 a: T
- }
4 o; V1 Z8 k/ \+ v7 Y7 t6 }3 J+ c - }
复制代码
% I% I6 ` M# a5 I w2 Z
& p1 _- [. {9 E
" ^# [6 r' [6 R- E' M3 l+ Q* N) R \! H3 R( I, `& L
. D. o6 [! v0 l# e% J
5 ^" N- s7 S8 u. h) [1 ]
/ N8 S; d; R$ K" n
% v- L0 o. S. F }( Y! ~
0 G' n8 Z1 ~, j* _; E/ G" _
7 C" L. B6 F% }$ m4 N x
|