你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【原创】STM32F103的USART2配置代码, DMA方式发送!

[复制链接]
wjandsq 发布时间:2015-6-25 14:07
STM32电机培训online,大佬带你玩电机
# ?" T4 I+ Q, `5 H6 @7 Q* ^) ~# [; `/ ~) N( C2 B
" l  h" }8 Z. B# V
#include "stm32f10x.h"
% K2 y+ w% l5 y' V#include "stm32f10x_usart.h"
' v* ]0 Y0 R$ O0 T; P% X#include "stm32f10x_dma.h"
( }9 e: q+ b* |3 k' s& z
4 Q! x" P% A: yuint8_t HEX_CODE[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
0 p; g( i8 y0 x* d9 F# u, q' quint8_t USART2_DMA_TX_Buf[1024];: W* N* ]8 V' U. R+ P
uint8_t Flag_USART2_DMA_TX_Finished = 1;
. `9 x; S% z" r% huint8_t Flag_USART2_Send = 0;, i+ z/ {& P3 S: N4 k9 l6 o

% Y; Y. B+ j. l9 D0 z$ c9 O  o' J/**
( a5 Z8 M  C6 ^! M  * Function Name  : USART2_Config: p2 f9 ]" }" W" N0 P6 e
  * Description    : None" t: X  p2 K8 n2 O) A& l' p
  * Input          : None
8 c' s9 b( L  R7 Z$ g% T  * Output         : None; Q& X6 G, j+ ?- G( v( V% R* E
  * Return         : None/ o; F& d8 E$ M) U& L$ c: |9 J* z
  */
) u* I+ P3 w( Y/ g, ~7 z5 J# ^# Zvoid USART2_Config(void) {
* M( a! u6 l" ?6 y! a  GPIO_InitTypeDef GPIO_InitStructure;" k0 Q2 Z( k4 s/ V
  USART_InitTypeDef USART_InitStructure;/ d8 y$ X3 Q7 e
  DMA_InitTypeDef DMA_InitStructure;
% B- _; z) W1 A% `8 q  P0 v9 X  NVIC_InitTypeDef NVIC_InitStructure;
" N- g. q! \. I$ g: \$ F: q
* L8 ?/ _6 v% K- q# \  /* config USART2 clock */
) b; j- O8 J4 v: k  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
. T+ i2 b4 ~4 Q5 W3 w  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);% r! m9 o" j! I3 e- p: r- d/ P
0 a! [$ W' y4 k5 {! b+ B4 v! n
  /* *********************USART2 GPIO config **********************/
) i" v+ y# C) @& i  Q6 l. \  /* Configure USART1 Tx (PA.02) as alternate function push-pull */
# V! Z8 ~$ p$ ~' n; H  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 0 y0 {8 H+ c; S
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
3 u. Z/ e0 P4 v/ B- j  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;5 l/ ^6 ]" p5 J0 l% R# [( S0 M
  GPIO_Init(GPIOA, &GPIO_InitStructure);   
. x9 Z7 M0 Z5 o% l+ T  c5 w  /* Configure USART2 Rx (PA.03) as input floating */- W0 {) X/ {$ L) M; j3 M3 F
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
) ?3 y+ |. B. T' ~; |( M! y  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
7 o/ D  T/ K9 p1 F9 n! _) B% ]  GPIO_Init(GPIOA, &GPIO_InitStructure);7 t! X: ?* l: o4 I" c$ M, Q* Y, i: i. c

5 o% T- c( G/ L  /* USART2 mode config 115200 8-N-1*/
1 R& Q9 A) P6 \) q/ d, G  USART_InitStructure.USART_BaudRate = 115200;
% |6 B8 b3 }4 \) V: l$ K  USART_InitStructure.USART_WordLength = USART_WordLength_8b;& ^" n  E' f7 s1 ~
  USART_InitStructure.USART_StopBits = USART_StopBits_1;8 B% S0 A8 L' t2 w  S5 `5 ^
  USART_InitStructure.USART_Parity = USART_Parity_No ;- G5 D$ M0 A5 }/ Y
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;# \5 i' N% T9 u8 W# L: h
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
$ f5 {. {; o! H+ A& ?  USART_Init(USART2, &USART_InitStructure); # q$ H4 f6 L5 J, l' f0 E
  USART_Cmd(USART2, ENABLE);
8 U  s7 V6 |) \! p! ^/ y; U- z4 T: D: _: f5 P% F$ _% y7 n$ c, `1 o
9 L7 T0 Z4 L8 ?, P/ l4 a  S5 j; }
  USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
, \5 {) T% ?4 a/ y1 e/ X  /* Enable USART2 DMA TX request */# v; B2 Q0 D; B
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);; T  p0 v3 ^8 y8 I' q. M; V1 s0 z
/ [5 ]3 z0 ?% F! Y# N5 Q) M$ \( L
  DMA_DeInit(DMA1_Channel7);/ l2 _# d+ c. I2 J8 U* k
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);
  [! Z, S. B5 E8 W) d# _+ W5 }* s3 a  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_DMA_TX_Buf;
9 m8 n" |% O+ ~2 f! n# s6 D) I/ C  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  w" [8 ]  g! @8 ]' j9 k4 `/ U+ `0 G
  DMA_InitStructure.DMA_BufferSize = 0;
6 i. b% y, X' `" P7 D6 u3 A  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;' g8 n# j. W" f1 ^
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;) F+ A( ^5 [" G- x# z
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- O* P/ r& V+ j  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
) ^- f" D: _9 Z' \$ j; g  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;: |- x  H1 x2 E- i! g- H5 w1 S
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;+ W+ S6 e5 n7 v7 U
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
2 U, p7 {/ F  g5 I# N$ _- j  DMA_Init(DMA1_Channel7, &DMA_InitStructure);! k6 K9 {8 K# b2 r" Q! c
  DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);
# L% i) w. e6 ^" L6 u2 N. x) V, [% |/ X0 s! a6 a
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);' p, N% L8 }, ^" N8 e
8 h) @; V9 F& G8 X) \8 @
  /* Enable USART2 DMA TX Finish Interrupt */# `: o2 s3 u+ K
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;1 c+ V" V2 S) o4 u0 W9 P# K# v$ p$ U4 @
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
5 h2 K, m: ^0 F# j  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
* {* x0 x5 y( [; [  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
; B2 b7 T1 x  O2 m  NVIC_Init(&NVIC_InitStructure);
& d4 @# ?4 {' g. O# w# o3 ?+ }! Z) O& M
  /* Enable USART2 Interrupt */
5 Z0 X% v, w5 m! Q" G6 X  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
$ g, B  W7 v$ G  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
, F$ |  y% I# R3 Z, D7 J$ ~  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;6 u3 j. ^- ]' \- a6 j
  NVIC_Init(&NVIC_InitStructure);7 V1 K3 g5 v) o$ H% G1 h
}& O/ X8 o+ r- a2 R2 |, ^2 Z: `
/**2 S. S/ d" Z4 P* X( {# r9 B
  * Function Name  : USART2_Data_Load
- j7 C) s& l' x, p/ s  * Description    : None
5 w  _0 \2 f  [- W& l; A  * Input          : None
. `3 p) n0 E9 V4 P5 f4 h/ K) C8 X. K. i  * Output         : None
. g; u% i- ^, s0 X  * Return         : None
5 q3 }: C3 U" C, u5 Y& N2 a/ M  */
: E/ ~+ t. R; ^void USART2_Data_Load(uint16_t temp1, uint16_t temp2, uint8_t temp3){: b4 S; B) v/ n* f1 \8 S7 O
  USART2_DMA_TX_Buf[0] = HEX_CODE[temp1 >> 4];$ m7 T: a* u) U+ [; l) t
  USART2_DMA_TX_Buf[1] = HEX_CODE[temp1 & 0x0F];
6 ]7 l8 j1 j0 y  USART2_DMA_TX_Buf[2] = HEX_CODE[temp2 >> 4];
: F  S1 W0 M2 {# t7 c/ b  USART2_DMA_TX_Buf[3] = HEX_CODE[temp2 & 0x0F];
3 j! s% ?2 E6 R- s/ s  USART2_DMA_TX_Buf[4] = 0x20;
6 d- m6 y5 Q" J" ^- a: k! l  x  USART2_DMA_TX_Buf[5] = HEX_CODE[temp3];
# ]: y; f; ?9 o3 m- q  USART2_DMA_TX_Buf[6] = 0x0D;! k) U1 E# T6 l
  USART2_DMA_TX_Buf[7] = 0x0A;
7 A* D  F9 ^$ n  Flag_USART2_Send = 1;% z8 q# @9 i4 k3 D' J
}' C  e8 v6 }+ A" V
/**
2 `: F" `( z' _- \  y6 ]2 d  * Function Name  : USART2_Data_Send
, t0 t- k# E2 y  * Description    : None$ u- S! |* n9 q; e7 o
  * Input          : None3 m, r. s( ^# f7 {' q. J, A
  * Output         : None6 w* [& ?/ R1 o  z7 J' ^
  * Return         : None/ v9 u: D3 S8 I: F
  */5 k  k. W$ |9 I+ L; r
void USART2_Data_Send(uint16_t len) {, X* u6 K2 B  K1 k2 L1 b
  if(Flag_USART2_Send){
# G; b2 O* a' u5 l' W    if(Flag_USART2_DMA_TX_Finished == 1){
2 F# u$ f1 p- n8 [. f      Flag_USART2_DMA_TX_Finished = 0;
* h$ p* D' F" R  A7 d) k% Q/ Z- |( C      DMA1_Channel7->CMAR  = (uint32_t)&USART2_DMA_TX_Buf[0];7 d2 J$ t: `& b5 U2 ?7 O+ t+ c
      DMA1_Channel7->CNDTR = 8; // len
5 t0 J; x% O( W: E  T      DMA_Cmd(DMA1_Channel7, ENABLE);& C2 w! I- N- K+ ^  J
      Flag_USART2_Send = 0;! Z, z6 p! W! P2 t
    }( B: O; }& ~5 q1 X
  }
% s( U; T- u* C% R. b/ L0 n; W  m  w}
$ ]: q( @/ c9 i8 Z/**. X" }4 R: W: F9 m6 C, Z+ J
  * Function Name  : USART2_IRQHandler
- _8 U5 \& P6 u! D  * Description    : This function handles USART2 global interrupt request.) E, h. A5 j& Z
  * Input          : None
4 S) X8 H! o8 V& h8 ~  * Output         : None
' b* G) g  y2 k6 a* B  * Return         : None7 A7 A# Q' D7 Y. |8 C
  */
/ T7 T( O$ I4 [' R; R; {& `void USART2_IRQHandler(void) {8 y' {7 H7 c/ R3 D  i  }
  if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) {
( q6 C3 w. {' r) `# x+ J0 e    (void)USART_ReceiveData(USART2);% i4 Y0 d+ R; S# w& `: ]
  }
; y$ F3 x, n2 Y3 x& l# a  if (USART_GetITStatus(USART2, USART_IT_TC) != RESET) {
  C8 _  A  ]# {2 l    /* Disable the USART2 Transmit Complete interrupt */
' `4 m. F" S8 ~2 [    USART_ITConfig(USART2, USART_IT_TC, DISABLE);$ _! g0 f8 l5 z) C4 \# f
    Flag_USART2_DMA_TX_Finished = 1;
5 L. S( M3 F( E  }     
1 Z6 J, h$ r0 O% |  /* If overrun condition occurs, clear the ORE flag a.nd recover communication */    + J8 x* L6 ]' T
  if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) != RESET) {; J. c4 y& U8 U5 V
    (void)USART_ReceiveData(USART2);6 V% }; E) W. t) a: [
  }
0 ]/ T" U# B- J! Z% f}+ M* `/ }+ d) `1 L) }/ A
/**5 f) \; J* h( O- C: D
  * Function Name  : DMA1_Channel7_IRQHandler
' \# k" L5 d" h! K; b1 `4 \  * Description    : This function handles DMA1 Channel 7 interrupt request.' E* V  D; f& U
  * Input          : None
5 ?" P- d6 M# W  e1 w, m  * Output         : None
8 g& s. E/ y2 e) x( j) z/ _  * Return         : None
: e9 c: Y8 W6 o. p  */3 i3 U# G& n# Z9 y, ~- {( ?% i: P8 m
void DMA1_Channel7_IRQHandler(void)
; y$ c1 i' r/ B+ c! a{9 g; y" ]0 A" _5 L4 {+ u
  if(DMA_GetITStatus(DMA1_IT_TC7)) {3 d4 `( X6 O& l2 P, X
    /* USART2 DMA 传输完成 */$ i2 n/ v7 b% D2 u
    DMA_ClearITPendingBit(DMA1_IT_TC7);6 j9 O2 d$ y8 K; {& [+ x$ O. k- T) w
    DMA_Cmd(DMA1_Channel7, DISABLE);7 B8 Q1 m7 z$ Y0 i3 X8 Y
    /* Enable USART2 Transmit complete interrupt */6 M- f6 G$ _  u5 x, k
    USART_ITConfig(USART2, USART_IT_TC, ENABLE); 4 x& U0 p* ]2 A4 D! I0 @; Q% A& A
  }
  M$ L, h. Z" N, H; F}
- w) R+ M0 t3 J0 B# v' [$ u1 @. C& x9 c, s" p
收藏 4 评论7 发布时间:2015-6-25 14:07

举报

7个回答
沐紫 回答时间:2015-6-25 14:25:56
谢谢,要是有代码注释或者文字说明更好啦
wyxy163@126.com 回答时间:2015-6-25 17:05:13
提示: 作者被禁止或删除 内容自动屏蔽
wjandsq 回答时间:2015-6-25 20:37:02
本帖最后由 wjandsq 于 2015-6-25 20:45 编辑 5 I4 v4 o" ?+ f) N  K1 q0 Q
9 s+ C# F! Q! Q  ~% U2 Q
所谓STM32F103串口数据的DMA发送,其本质流程如下:
7 L$ Y3 G. S- L: W4 f& p1. 要发送的数据放在USART2_DMA_TX_Buf缓冲。
9 v- S" j/ |: u6 r2 h2 e2. STM32串口DMA发送和DSP相比的优势。
7 n6 R, @* i" P5 y- o. j   启动DMA传输后,USART2_DMA_TX_Buf缓冲中的数据通过DMA1_Channel7通道,$ T8 _/ z5 k! `8 _' o, t2 t: z
   自动传输到USART2->DR寄存器,这个工作不需要CPU干预,可以极大的节省CPU的资源。
7 l  `& w" @; T( W! E: K   和DSP的FIFO相比,这优势很大,因为DSP的FIFO只有16字节,这意味着DSP的串口通过6 K: `  Q/ S  o! C  S6 D
   FIFO发送数据时,如果FIFO缓冲为空,可以迅速填入16个字节,然后去处理其它的事务。
) e1 J* _, v6 G7 ]/ V# |   而STM32的DMA发送则没有此种限制。更具体的说,如果DSP发送的数据超过16字节,
3 g4 @. d! X, v  }# @* V   则必须等待前16个字节数据发送完毕,然后再继续发送后续的数据,需要第二次甚至
/ e  F4 V: v" j9 g2 O# }/ b3 _; N+ d   第N次处理。而STM32启动一次DMA就搞定(DMA最大传输65535个数据)。
. W1 ]/ }$ {. B# h2 |2 E3. 发送结束的一些事务处理
. I! b$ f8 K+ s$ T   DMA传输完毕,数据全部通过DMA1_Channel7通道依次传入USART2-DR,这里开启了# L# I0 m& ~& m! @, r
   DMA传输完毕中断,进这个中断时,USART2-DR寄存器是最后一个要发送的数据,
6 k: D: U& F& J: x   此时打开USART2发送完毕中断,进入USART2发送完毕中断后,可以设定标识,
2 _' l( H/ A2 F& W( \* l; ]/ B' p   也可以操作GPIO, 进行RS485的换向动作。
- j/ X! p1 B, ~, d+ }- `. d* u% o8 L" h' a$ B) x
最新的STM32F103的HAL库,几乎所有的通信,都可以启用DMA,HAL库函数抽象层次过高,灵活性不够,/ ~/ {# G& u/ v1 e
但比较适合使用操作系统的场合。可以把HAL库的宏定义拷贝过来使用,以提高标准外设驱动库的效率,
" B% c) d0 L' P6 G又保证标准外设驱动库的灵活性。: Z9 B4 R7 o9 f+ r

2 C: ^9 @6 B  `8 Z3 V( W) o+ X4 c1 a% B) G0 F6 z$ h) y* u% b7 e
# t  K- _$ e" `6 _
Paderboy 回答时间:2015-6-25 20:38:16
多谢分享。。。支持下。。
HenryChen 回答时间:2015-7-3 16:57:05
多谢分享。。。支持下。。
fanyao-367090 回答时间:2016-11-10 16:43:14
zengyi703-16313 回答时间:2016-11-11 08:13:25
学习一下
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版