
STM32电机培训online,大佬带你玩电机 # I* ]& o' u* V #include "stm32f10x.h" #include "stm32f10x_usart.h") D+ U! n. ?& L. ?5 } #include "stm32f10x_dma.h" , {) r/ h* G7 D6 P8 L# ~ uint8_t HEX_CODE[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};; Y$ ^! P# o) b" r4 i1 ?0 U6 n8 c( | uint8_t USART2_DMA_TX_Buf[1024]; uint8_t Flag_USART2_DMA_TX_Finished = 1;3 o# P/ u3 `; Y6 t1 O uint8_t Flag_USART2_Send = 0; /**3 g. I4 P; a* Y, F * Function Name : USART2_Config u1 s/ M5 q% N. | * Description : None * Input : None * Output : None" Q0 ]/ A; g# a * Return : None" k! g4 p0 z. K% V$ i# B */: E5 T. q6 C) D1 R void USART2_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; DMA_InitTypeDef DMA_InitStructure;8 L* z; G2 U; Q NVIC_InitTypeDef NVIC_InitStructure; /* config USART2 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); /* *********************USART2 GPIO config **********************/+ a' @$ L3 I7 Q# u /* Configure USART1 Tx (PA.02) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; ! T& r4 R' r+ L* T0 i GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;1 o0 V8 c3 N& a: w7 L% K. ` GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;: ]$ R' V' b- r/ w$ a+ e GPIO_Init(GPIOA, &GPIO_InitStructure); & X1 ]/ ?7 w% N, o( b' F /* Configure USART2 Rx (PA.03) as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;7 g9 M- v" n' L* b5 e' O a GPIO_Init(GPIOA, &GPIO_InitStructure);! v' {7 j* `. A7 Y! |( ?: I 6 X7 M3 I! o, R3 f5 t& j# l4 }% z /* USART2 mode config 115200 8-N-1*/ USART_InitStructure.USART_BaudRate = 115200;5 A& @1 Q. @, ~2 `$ f4 e/ n USART_InitStructure.USART_WordLength = USART_WordLength_8b;/ g, ~0 D! B4 T( q! @& Y3 }! ` USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No ;3 T; G2 j7 o# M) c+ h. c USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;9 p9 K. T, w+ d: W/ | USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); USART_Cmd(USART2, ENABLE);6 M/ `/ ~) q9 D D' v 5 s' I' ]! v3 Z5 A USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);) B! z+ o% A G7 z0 `5 g3 L. T /* Enable USART2 DMA TX request */% O: S2 E" p$ K$ z0 H5 |7 J RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);- k/ x/ W3 b0 j+ A) Z DMA_DeInit(DMA1_Channel7);" @$ ^8 }1 ?) z$ O, a DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);$ o7 F! h0 [0 q; o DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_DMA_TX_Buf;) a$ n! v2 Y7 T' \ DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;: j% t8 }4 b* n1 s+ t DMA_InitStructure.DMA_BufferSize = 0;4 Z+ S3 \& v+ `6 m7 G* g DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;2 {6 g; o) c0 R" t, c. h, w- A9 D4 S DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;4 }7 `9 f5 }" n3 J DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;5 Q1 t0 c1 X4 M8 p: e" U DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;! u" j) l: }6 g; _0 C: b DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel7, &DMA_InitStructure); DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);6 ^2 V4 B/ J9 T( r* U 1 k6 a$ i& a3 ]( | NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);& C. X z7 I# \7 q; R! |1 u7 N : i3 E5 h/ K- h% q# ]; s /* Enable USART2 DMA TX Finish Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;9 H# N3 S$ t; ~3 K NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;& p& X: N) Q1 e; f. z NVIC_Init(&NVIC_InitStructure); /* Enable USART2 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;) E% D3 s5 w, a P NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStructure);* {: h9 s- `4 }0 Z } /** * Function Name : USART2_Data_Load8 J+ p1 q5 n0 Z * Description : None * Input : None$ _3 N1 ?! s/ u2 Y8 c* M * Output : None * Return : None6 @' u& K# P1 ?& w$ o% y' X6 k */5 ]! F6 B( N3 f) h9 c- f) C void USART2_Data_Load(uint16_t temp1, uint16_t temp2, uint8_t temp3){ USART2_DMA_TX_Buf[0] = HEX_CODE[temp1 >> 4];% f3 D+ R- k% G8 t USART2_DMA_TX_Buf[1] = HEX_CODE[temp1 & 0x0F]; USART2_DMA_TX_Buf[2] = HEX_CODE[temp2 >> 4];! a1 i1 m% `+ `4 ]. ], w USART2_DMA_TX_Buf[3] = HEX_CODE[temp2 & 0x0F]; USART2_DMA_TX_Buf[4] = 0x20;! u5 Q7 m- B) q( n USART2_DMA_TX_Buf[5] = HEX_CODE[temp3]; USART2_DMA_TX_Buf[6] = 0x0D;1 d) m6 r$ N$ J T; r; O' E! i# e USART2_DMA_TX_Buf[7] = 0x0A; Flag_USART2_Send = 1; }; f. V0 _ N2 T /**- J8 O/ N) B3 ~0 U0 j * Function Name : USART2_Data_Send * Description : None) U" w+ ^: R6 o+ j) c9 R& p, P& h * Input : None * Output : None7 P d x3 {4 r) i, E$ ^9 z% @$ K * Return : None. `- N% F& j4 \ */ void USART2_Data_Send(uint16_t len) {5 e. n7 \# X4 o. L0 A2 M5 ?8 l if(Flag_USART2_Send){0 y" G0 q! K$ }9 V if(Flag_USART2_DMA_TX_Finished == 1){ Flag_USART2_DMA_TX_Finished = 0;9 S% x2 T- c6 Y DMA1_Channel7->CMAR = (uint32_t)&USART2_DMA_TX_Buf[0]; DMA1_Channel7->CNDTR = 8; // len% q1 \; f; P/ i DMA_Cmd(DMA1_Channel7, ENABLE);4 B) U6 U+ ^0 S7 | Flag_USART2_Send = 0;+ B+ p0 q2 G$ v. a) O/ A3 X+ E } } } /** * Function Name : USART2_IRQHandler * Description : This function handles USART2 global interrupt request.7 m1 V% [- _( |5 E* n4 m5 { * Input : None, a& D( x/ ?5 \( l( } * Output : None * Return : None */ void USART2_IRQHandler(void) { if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) { (void)USART_ReceiveData(USART2); } if (USART_GetITStatus(USART2, USART_IT_TC) != RESET) { /* Disable the USART2 Transmit Complete interrupt */" o( ]( B# `: M; \9 y USART_ITConfig(USART2, USART_IT_TC, DISABLE); Flag_USART2_DMA_TX_Finished = 1;2 X1 h1 T, y: v' l } 3 E) q0 H: c2 h: Y0 G /* If overrun condition occurs, clear the ORE flag a.nd recover communication */ * O d" G. D7 T' Y& T# K5 F if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) != RESET) {, v+ M% N, G: D$ J d (void)USART_ReceiveData(USART2);, W2 }7 s+ @1 D, U5 g; g } } /**7 n2 g+ Y6 C: T K' z * Function Name : DMA1_Channel7_IRQHandler * Description : This function handles DMA1 Channel 7 interrupt request.. ^) x+ r8 H1 B" ~: P' E, W * Input : None0 ?2 q. S* M9 f6 O' m. v: m * Output : None * Return : None */ void DMA1_Channel7_IRQHandler(void) {$ J6 J! n, R+ }0 X! L& m if(DMA_GetITStatus(DMA1_IT_TC7)) { /* USART2 DMA 传输完成 */ DMA_ClearITPendingBit(DMA1_IT_TC7); DMA_Cmd(DMA1_Channel7, DISABLE);4 z8 c, U7 x- P: q- i$ M0 ^# R /* Enable USART2 Transmit complete interrupt */ USART_ITConfig(USART2, USART_IT_TC, ENABLE); " B# Q# u6 N" V1 [ } }9 o8 A6 g5 K" o6 P1 @2 Y2 v |
所谓STM32F103串口数据的DMA发送,其本质流程如下:6 { L3 [- J3 a3 w! @/ ?
1. 要发送的数据放在USART2_DMA_TX_Buf缓冲。
2. STM32串口DMA发送和DSP相比的优势。2 f2 s0 |6 E4 C* w ]. L
启动DMA传输后,USART2_DMA_TX_Buf缓冲中的数据通过DMA1_Channel7通道,% s/ Y' r) x9 K! o: {* D: g( H
自动传输到USART2->DR寄存器,这个工作不需要CPU干预,可以极大的节省CPU的资源。" l7 e4 x# t* H5 X' u
和DSP的FIFO相比,这优势很大,因为DSP的FIFO只有16字节,这意味着DSP的串口通过2 s) k" c- D# y& q' m5 Q
FIFO发送数据时,如果FIFO缓冲为空,可以迅速填入16个字节,然后去处理其它的事务。
而STM32的DMA发送则没有此种限制。更具体的说,如果DSP发送的数据超过16字节,
则必须等待前16个字节数据发送完毕,然后再继续发送后续的数据,需要第二次甚至. o9 \, U- {% A" U* ^2 D6 O
第N次处理。而STM32启动一次DMA就搞定(DMA最大传输65535个数据)。! w. W% B8 n) |0 l; ?, L
3. 发送结束的一些事务处理
DMA传输完毕,数据全部通过DMA1_Channel7通道依次传入USART2-DR,这里开启了2 }8 |, q" E9 a0 y8 r( j
DMA传输完毕中断,进这个中断时,USART2-DR寄存器是最后一个要发送的数据,9 v _2 E% D+ Q6 r( Y# ~' W3 z
此时打开USART2发送完毕中断,进入USART2发送完毕中断后,可以设定标识,
也可以操作GPIO, 进行RS485的换向动作。: U- B7 n; Y" ]! z$ c& G( }
最新的STM32F103的HAL库,几乎所有的通信,都可以启用DMA,HAL库函数抽象层次过高,灵活性不够,
但比较适合使用操作系统的场合。可以把HAL库的宏定义拷贝过来使用,以提高标准外设驱动库的效率," O6 ?! s9 d- B. f1 E
又保证标准外设驱动库的灵活性。
. S8 a* I, i$ o