
STM32电机培训online,大佬带你玩电机; `3 n3 c$ l* Y" `! i8 O$ d3 |- ] & X+ {0 R5 |% h3 k t, B3 {$ o" K) Z 6 l4 F5 W* c2 a" M8 } #include "stm32f10x.h"2 J" x" V) [5 j% P R #include "stm32f10x_usart.h" #include "stm32f10x_dma.h" P7 D7 |! t4 D. D1 R% H( Q uint8_t HEX_CODE[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};1 U2 { l9 r! h$ N1 [ uint8_t USART2_DMA_TX_Buf[1024]; uint8_t Flag_USART2_DMA_TX_Finished = 1; uint8_t Flag_USART2_Send = 0; /**+ P! C3 ]3 ^% y( D * Function Name : USART2_Config * Description : None * Input : None5 c# E; X) M) q) z$ `& P1 g2 c! X$ G * Output : None * Return : None */ void USART2_Config(void) {# W: ~4 m! Y8 d9 O8 q Y, G, s: J GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure;- }4 D* j- F- X DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; /* config USART2 clock */1 S# h% ]/ |. ~" U/ ~ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);# }; w1 S. ~" { u! m RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);# v; `0 l* X3 P% }7 F /* *********************USART2 GPIO config **********************/$ Q/ {/ p8 m+ b9 u% Z4 \( v /* Configure USART1 Tx (PA.02) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; ' D# N4 w* |# S) { GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;; Z* B1 F0 d; E$ Y( Y5 p5 M: x GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART2 Rx (PA.03) as input floating */7 p, Z0 {+ E& w3 M9 s* u GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;& } u" p- C% i3 [5 A* E: I) z GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; a. Y8 j7 H U/ m# o+ i GPIO_Init(GPIOA, &GPIO_InitStructure); /* USART2 mode config 115200 8-N-1*/8 H! y8 D* f: a; C* `+ p) ] USART_InitStructure.USART_BaudRate = 115200;% `( N8 Y4 `! s USART_InitStructure.USART_WordLength = USART_WordLength_8b; Q% [+ s, g! p) D USART_InitStructure.USART_StopBits = USART_StopBits_1;* b& r* X. v f, e7 l; i; T USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); USART_Cmd(USART2, ENABLE);9 t3 A- O9 `1 s/ z" b3 E' o& g; p USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);. H9 ~0 F. A2 z2 Z6 H! n8 Q$ Q% Q# ] /* Enable USART2 DMA TX request */) x7 W$ u- k6 C2 M RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 7 }* U; v& P% K3 e+ G DMA_DeInit(DMA1_Channel7); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);6 R( L& h$ t$ z DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_DMA_TX_Buf; H3 A7 N' [+ |: ~) q DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;2 V0 W, L- w Z! u) @) {9 q DMA_InitStructure.DMA_BufferSize = 0; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;9 V3 j# U4 L* | DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;' J: z& k$ | {9 g% f* y+ d) i DMA_Init(DMA1_Channel7, &DMA_InitStructure); DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);7 O6 \$ }" H. c ( y5 t( Y/ x) W0 Y NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);# r! y3 c7 d! k' ~2 m; \, Z( h 3 w+ f8 Q7 K" w8 l" R# r( O/ _ /* Enable USART2 DMA TX Finish Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;! a2 }4 P* Z) H NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;; J3 y% [* F6 C- j* K* W$ N( A NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);4 [9 ^' E* @7 `3 H ' p6 b7 U2 L8 G8 b3 c /* Enable USART2 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;+ v. N; G( m, W W% ~ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;) P2 e, A- y5 q( ?1 `1 H NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStructure); }% A4 ?4 m; r. h$ I4 Z /*** \- c1 i5 y9 J* |/ S1 F. q( |) N$ n0 D * Function Name : USART2_Data_Load * Description : None * Input : None * Output : None4 z" D* ~% i8 p) ~5 G1 E( x * Return : None */6 z; q! j" ?& Q void USART2_Data_Load(uint16_t temp1, uint16_t temp2, uint8_t temp3){- H6 \9 x& ?4 T+ i USART2_DMA_TX_Buf[0] = HEX_CODE[temp1 >> 4]; USART2_DMA_TX_Buf[1] = HEX_CODE[temp1 & 0x0F];8 a- x3 v6 ^8 b. f' } USART2_DMA_TX_Buf[2] = HEX_CODE[temp2 >> 4]; USART2_DMA_TX_Buf[3] = HEX_CODE[temp2 & 0x0F]; USART2_DMA_TX_Buf[4] = 0x20; USART2_DMA_TX_Buf[5] = HEX_CODE[temp3];( _& p/ w; p( d USART2_DMA_TX_Buf[6] = 0x0D; USART2_DMA_TX_Buf[7] = 0x0A; Flag_USART2_Send = 1;& G2 [9 i# j* o1 j$ p2 o( P }1 o5 l9 f+ J) H: M6 \, ]) \. F /**2 A0 W; J2 N% @ * Function Name : USART2_Data_Send; E1 d% H0 C: W. n5 n * Description : None * Input : None: {5 z3 L) x9 t! H+ ?: n5 @ * Output : None * Return : None */ void USART2_Data_Send(uint16_t len) {& k; C1 x% T* B- S! J if(Flag_USART2_Send){ if(Flag_USART2_DMA_TX_Finished == 1){ Flag_USART2_DMA_TX_Finished = 0;$ _. `# z2 s$ x2 f DMA1_Channel7->CMAR = (uint32_t)&USART2_DMA_TX_Buf[0]; DMA1_Channel7->CNDTR = 8; // len DMA_Cmd(DMA1_Channel7, ENABLE); Flag_USART2_Send = 0; R* S- _4 }1 M& ~" ^ } } }) X# N. j% p- ] M& h; | /** * Function Name : USART2_IRQHandler) \! B2 R0 C' c+ I * Description : This function handles USART2 global interrupt request.5 k5 e K) x7 K; X6 A * Input : None0 n6 x# z& X6 m* S * Output : None# h3 A/ K- z8 {0 `; e5 g& } w * Return : None */3 b4 m' d- S- u! ` U void USART2_IRQHandler(void) {+ {) {' `9 b+ N" }- g+ s% _ if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET) {! R) m3 H5 I" c (void)USART_ReceiveData(USART2); }8 Y0 `$ O* B# u* b; G8 y4 @ if (USART_GetITStatus(USART2, USART_IT_TC) != RESET) { /* Disable the USART2 Transmit Complete interrupt */% b2 A- g6 C# O3 c: f, D+ M USART_ITConfig(USART2, USART_IT_TC, DISABLE);9 t1 ^' W+ _; z2 R& A$ c6 d( l) D5 m Flag_USART2_DMA_TX_Finished = 1;1 d) u; [. c/ l! R( z3 I& W } 3 `: X% s# q2 ~' }# }: [- B9 \; x /* If overrun condition occurs, clear the ORE flag a.nd recover communication */ ' a9 j* ]4 [: M* q- r! W* ^ if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) != RESET) {1 H4 b" U9 m* E" l) T (void)USART_ReceiveData(USART2);% Z1 K$ `# |) {0 o }% y+ w4 b2 g# b( R% S } /** * Function Name : DMA1_Channel7_IRQHandler * Description : This function handles DMA1 Channel 7 interrupt request. * Input : None: |( F$ F- L9 N * Output : None+ {/ j3 o! L) z, T; q3 t5 L * Return : None0 ~9 M0 q# p' [ */3 D2 C; U6 T$ g( f0 ~9 P void DMA1_Channel7_IRQHandler(void) {+ ]5 k1 c. e8 V1 [! S" c if(DMA_GetITStatus(DMA1_IT_TC7)) {% @ [1 A& _+ W% V9 ]6 ^0 w* A1 c /* USART2 DMA 传输完成 */- Z4 C2 j, g1 ?+ u DMA_ClearITPendingBit(DMA1_IT_TC7); DMA_Cmd(DMA1_Channel7, DISABLE); /* Enable USART2 Transmit complete interrupt */) R- N; |. P+ b USART_ITConfig(USART2, USART_IT_TC, ENABLE); }* J9 |* u5 R' C; t5 R0 R } 1 d) v3 ^- D& \9 T* o |
所谓STM32F103串口数据的DMA发送,其本质流程如下:
1. 要发送的数据放在USART2_DMA_TX_Buf缓冲。
2. STM32串口DMA发送和DSP相比的优势。
启动DMA传输后,USART2_DMA_TX_Buf缓冲中的数据通过DMA1_Channel7通道,
自动传输到USART2->DR寄存器,这个工作不需要CPU干预,可以极大的节省CPU的资源。8 R0 t* C4 q9 M$ t V! A; A
和DSP的FIFO相比,这优势很大,因为DSP的FIFO只有16字节,这意味着DSP的串口通过# d, a* I4 o9 j( x7 P; o' l
FIFO发送数据时,如果FIFO缓冲为空,可以迅速填入16个字节,然后去处理其它的事务。
而STM32的DMA发送则没有此种限制。更具体的说,如果DSP发送的数据超过16字节,
则必须等待前16个字节数据发送完毕,然后再继续发送后续的数据,需要第二次甚至
第N次处理。而STM32启动一次DMA就搞定(DMA最大传输65535个数据)。
3. 发送结束的一些事务处理; f( p- x# k8 n
DMA传输完毕,数据全部通过DMA1_Channel7通道依次传入USART2-DR,这里开启了
DMA传输完毕中断,进这个中断时,USART2-DR寄存器是最后一个要发送的数据,
此时打开USART2发送完毕中断,进入USART2发送完毕中断后,可以设定标识,9 d& k: x$ l5 s
也可以操作GPIO, 进行RS485的换向动作。
( M' N8 ^0 N; U5 D: x* {8 `7 `
最新的STM32F103的HAL库,几乎所有的通信,都可以启用DMA,HAL库函数抽象层次过高,灵活性不够,
但比较适合使用操作系统的场合。可以把HAL库的宏定义拷贝过来使用,以提高标准外设驱动库的效率,
又保证标准外设驱动库的灵活性。
& g5 a# d' u! I) O' q4 o
b0 D1 Q9 P% X$ b* a/ W- j
2 z8 Y$ j+ w8 K3 x8 b. o