直接上代码 /********************************************************************************. t T+ _/ G" t! _* j2 J- E. j * 函 数 名: USART_Config()$ W* R# G0 d, \. U" A6 Z G * 功能描述: 配置USART的GPIO口4 S; p5 Z' \3 q! v9 t& f% B) F. a& P * 输入参数: bau 串口波特率9 J. k+ q# M# m | * 输出参数: void( F g! b( ?' T * 注 释: 配置USART串口参数( s1 l# [) F! H0 B* g/ S" a- H S ********************************************************************************/ void USARTx_Config(USART_TypeDef* USARTx,unsigned int bar)! c3 z( I" }/ q( M1 ? { USART_InitTypeDef USART_InitStructure; //USART1 初始化设置 USART_InitStructure.USART_BaudRate = bar; //波特率设置8 v% d$ d: k- ~! M( B USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位 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(USARTx, &USART_InitStructure); //初始化串口1! l G" v% Q+ |; P0 J% W8 i8 X2 Q; c } /******************************************************************************** * 函 数 名: USARTx_IT_Config() * 功能描述: 配置USART的GPIO口5 T) U# \6 ]( l( l+ h7 f$ | * 输入参数: irq 中断通道号$ h1 i/ W% r! t& c * Pre 抢占优先级0 g: T, a$ T! @8 B- V * Sub 子优先级 * 输出参数: void * 注 释: 配置串口中断6 U9 s( `, y% y& w' M" Y# {" K- V ********************************************************************************/ void USARTx_IT_Config(unsigned char irq,unsigned char Pre,unsigned char Sub) { NVIC_InitTypeDef NVIC_InitStructure; //Usart1 NVIC 配置" }. q& h) ` G0 ^: m8 Q1 | NVIC_InitStructure.NVIC_IRQChannel = irq; //串口1中断通道; @ d* r8 Q. C NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=Pre;//抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority =Sub; //子优先级* U( S- E5 O2 F; m! U. E1 [4 X NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、 } t/ N' u7 h) q /********************************************************************************' }+ I4 A, @ f- J: J7 f! b * 函 数 名: USARTx_DMA_Config()4 U4 { I. }% \$ d! L+ f2 e3 `; B * 功能描述: 配置USART的DMA通道 * 输入参数: DMAy_Channelx 通道号+ X$ q$ {6 f7 p# R3 I8 x/ O * paddr 外设地址 (串口的DR地址,详情配置见Init代码)9 w: h& k( w* s* b* f8 M! x * Maddr 存储器地址8 k4 G i M: L: n' n4 K * dir 模式 DMA_DIR_PeripheralDST(存储器到外设) DMA_DIR_PeripheralSRC(外设到存储器)" \, O. K% T) Q0 [, C5 G * size 传输数据量 U2 R* j' p8 q, h2 d; F+ Y * 输出参数: void * 注 释: 配置串口中断 ********************************************************************************/0 a# g5 f8 C$ \9 c* _6 P9 T void USARTx_DMA_Config(DMA_Channel_TypeDef* DMAy_Channelx,unsigned int paddr,unsigned int Maddr,unsigned int dir,unsigned int size) { DMA_InitTypeDef DMA_InitStructure;* m( z$ K$ c! d8 }9 A& ]9 ] # l1 c3 C9 K% P8 |" ^! D, a DMA_DeInit(DMAy_Channelx);3 a2 y+ T" D% O! e /* 配置 DMA 发送通道*/ DMA_InitStructure.DMA_PeripheralBaseAddr = paddr; //DMA外设地址 DMA_InitStructure.DMA_MemoryBaseAddr = Maddr; //DMA 存储器地址 DMA_InitStructure.DMA_DIR = dir; //存储器到外设模式 DMA_InitStructure.DMA_BufferSize = size; //数据传输量 * P T5 b* @" ^2 P H8 Y1 ] DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度:8位 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //使用普通模式 $ |2 a$ j0 Y+ I' g. i DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //中等优先级. H2 w9 p) H* V0 n# H, [( w% A DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 DMA_Init(DMAy_Channelx, &DMA_InitStructure); //初始化DMA 7 u. g9 o3 n x# W }+ P E# P0 ]8 B! q /******************************************************************************** * 函 数 名: USART_Init() * 功能描述: 配置USART * 输入参数: void * 输出参数: void * 注 释: 配置USART串口参数! ^0 }% }$ z0 ` ********************************************************************************/ void USARTx_Init(void) { /*USART1 config*/. q0 J+ p3 D: G3 b y USARTx_Config(USART1,115200); USART_Cmd(USART1, ENABLE); //使能串口16 \8 M0 `1 x2 h USART_ClearFlag(USART1, USART_FLAG_TC); /*清除发送中断标志*/ USART_ClearFlag(USART1, USART_IT_IDLE); /*清除空闲中断标志*/6 h; W( G G$ T+ _% i% W7 ?$ t% a USART_ITConfig(USART1, USART_FLAG_TC, ENABLE); /*开启空闲中断*/ USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); /*开启空闲中断*/( P% @; O1 V, Y0 i; W9 N5 D USARTx_IT_Config(USART1_IRQn,0,0); USARTx_DMA_Config(DMA1_Channel4,(unsigned int)&USART1->DR,(unsigned int)USARTStr.SendBuff,DMA_DIR_PeripheralDST,0); USARTx_DMA_Config(DMA1_Channel5,(unsigned int)&USART1->DR,(unsigned int)USARTStr.ReadBuff,DMA_DIR_PeripheralSRC,USART_BUFSIZE); USART_DMACmd(USART1, USART_DMAReq_Tx|USART_DMAReq_Rx, ENABLE); /* 使能DMA串口发送和接受请求 */; \0 j. n) r% L# c- v" t$ \ DMA_Cmd(DMA1_Channel5,ENABLE); /*打开接收数据通道*/8 m% Z) [/ X' U" {0 j1 {' s) D UserMemset((unsigned char *)&USARTStr,0,sizeof(USARTStr)); /*USART2 config*/ USARTx_Config(USART2,115200);, z, F' `$ R/ z5 p* j2 u1 ` USART_Cmd(USART2, ENABLE); //使能串口1# f, Q L$ h# J2 g% b USART_ClearFlag(USART2, USART_FLAG_TC); /*清除发送中断标志*/ USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); /*开启空闲中断*/4 S5 @% O- b. B7 h, D( h7 U USARTx_IT_Config(USART2_IRQn,0,1);: r! u+ b/ O$ q7 I: M USARTx_DMA_Config(DMA1_Channel7,(unsigned int)&USART2->DR,(unsigned int)USART2Str.SendBuff,DMA_DIR_PeripheralDST,0); USARTx_DMA_Config(DMA1_Channel6,(unsigned int)&USART2->DR,(unsigned int)USART2Str.ReadBuff,DMA_DIR_PeripheralSRC,USART_BUFSIZE); USART_DMACmd(USART2, USART_DMAReq_Tx|USART_DMAReq_Rx, ENABLE); /* 使能DMA串口发送和接受请求 */ DMA_Cmd(DMA1_Channel6,ENABLE); /*打开接收数据通道*/. _3 m' k( s+ T6 V* r r! w( y- V0 ^ UserMemset((unsigned char *)&USART2Str,0,sizeof(USART2Str)); } /********************************************************************************% R$ ?( a4 N l0 f. O * 函 数 名: USART1SendData/ M0 f/ ?; {2 b) {. r9 ^. L * 功能描述: 串口1DMA发送数组% {% f0 m7 M2 P. A * 输入参数: buf 发送的数组0 W* r6 T- K2 V7 Y * len 数组长度) z5 x! g6 K) W1 b' l8 K * 输出参数: void * 注 释: 无 ********************************************************************************/+ w p, b" i4 L void USART1SendData(unsigned char *pData,unsigned short size)5 \# c$ `% |. n- C4 ?9 [6 [) L { UserCopy(USARTStr.SendBuff,pData,size);! Q; k+ z) Z, j S: U DMA_Cmd(DMA1_Channel4,DISABLE); DMA1_Channel4->CNDTR = size; DMA_Cmd(DMA1_Channel4,ENABLE); }% i# T( t" d/ z0 G" M /********************************************************************************- Z4 ]9 _2 e3 X' \ * 函 数 名: USART1_IRQHandler3 O: S( j$ J2 ]* k6 [; }9 o: s) y m * 功能描述: 串口接收中断 * 输入参数: void+ X- U% J( v5 Z0 w * 输出参数: void# }, R- Z& p# b2 Z, B* D; R * 注 释: 无 ********************************************************************************/1 u0 s$ L! }/ D4 B void USART1_IRQHandler(void)9 }$ ]8 K, _; m$ \0 ]" t/ H {; i" ]7 `* b7 G unsigned char temp; if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //空闲中断 {4 y' e' Z$ C5 v0 D! q7 F: U temp = USART1->SR; temp = USART1->DR;1 R1 T( F" E* G' _2 H temp = temp;! |& O }0 Z% p; R/ {5 X4 f USARTStr.Len = USART_BUFSIZE - DMA1_Channel5->CNDTR; USARTStr.Flag = 0x80; DMA_Cmd(DMA1_Channel5, DISABLE);& |7 h1 `! K& C* R9 l DMA1_Channel5->CNDTR=USART_BUFSIZE; DMA_Cmd(DMA1_Channel5, ENABLE); USART_ClearITPendingBit(USART1, USART_IT_IDLE); } if(USART_GetITStatus(USART1, USART_FLAG_TC) != RESET) //传输完成中断 {1 h2 z+ ^) D& [* k8 D/ S USARTStr.Flag = 0; UserMemset((unsigned char *)&USARTStr,0,USARTStr.Len); } } 下面是变量的声明2 V4 E d) ?; \5 d" c2 L# m 0 X& `' c5 T h5 l9 P6 d" p7 v #define USART_BUFSIZE 1024 /*最大接收串口数据的值*/ /****************************************************************************+ g) w( M/ `0 W4 Y0 | w' K+ G" N * Local Types ****************************************************************************/ & c- x* h5 Q8 d* Y- _# F typedef struct TagUSARTStruct{ /*声明结构体来接收串口的数据*/8 U3 @3 {% `% M) v# ^ unsigned short Len;; u* M& a7 _3 c; |5 z3 ]( m3 n& c unsigned char Flag; unsigned char SendBuff[USART_BUFSIZE]; /* 发送数据 */ unsigned char ReadBuff[USART_BUFSIZE]; /* 接收数据 */# q. U' b: x0 k }T_USARTStruct; : [- D% R D. n2 \% y) P% L0 A extern T_USARTStruct USARTStr; /*外部调用声明*/ extern T_USARTStruct USART2Str; 串口的gpio配置是好搞的我就补贴上代码了) S& W- V# |" W B/ D- Z8 r) e& @) ? 千万记住打开相关的时钟配置 . m7 z; J W1 n0 X+ [5 _+ v /* open DMA1 clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);7 C" C* o8 w' E 以上的配置代码是测试完全通过的,在DMA中所说的外设到内存其实是配置了串口的DR数据地址映射到全局变量中,所说的外设是STM32在M3内核上添加的功能,例如:串口,IIC,SPI,ADC,DAC等这些外设,配置DMA时候把这些地址给到DMA外设地址配置上去,DMA内存是把代码中的全局变量的地址。STM32DMA有三种模式:内存到内存和外设到内存、内存到外设。使用接收PC端或者其他设备发送过来的数据在配置DMA时候必须提前打开,否则接收不到数据。例如串口1接收数据在配置DMA1通道5时候,在配置时要事先使能打开。通道4是用于发送数据出去可以填写好发送内容再打开,填数据前必须先关闭通道,中断可以根据需求去配置,但是配置了中断记得及时的清除标志位。否则发生整个程序在不断的执行中断代码,主程序代码无法执行,包括DMA的中断配置可根据手册查询配置,同样配置了,也要及时的清除中断标志。使用C自带微型库会增加代码大小,使用不多其实建议自己写,下面贴出代码。 /******************************************************************************** * 函 数 名: UserCopy6 P. e' W W3 M7 l7 S * 功能描述: 拷贝数据; d. ^# `& T4 _ * 输入参数: pdata 拷贝到的数组. `7 R9 g7 M3 U7 A$ e& M$ Q * data 要拷贝的数组9 |+ W& k; c" i0 P * len 拷贝的长度 * 输出参数: void* x& b: p' O! W$ _# | * 注 释: 无# l6 C z( m, I/ D) c j ********************************************************************************/ void UserCopy(unsigned char *pdata,unsigned char *data,int len) {% z! k+ {" @6 L# ~ int i; for(i=0;i<len;i++) { pdata = data; }' X: p( v" a& M( S; i }/ \/ ~7 z: b* S; N2 I 4 l$ T( M, Y1 I6 n /******************************************************************************** * 函 数 名: UserMemset0 a& r7 O. M `2 r * 功能描述: 清除数据: y3 p& k% V- X7 P* Y- S! u * 输入参数: pdata 要清楚的数组 * t 填充的数据 * len 数组长度 * 输出参数: void * 注 释: 无 ********************************************************************************// v6 V8 g2 Q# N' ?, p void UserMemset(unsigned char *pdata,char t,int len)3 Z$ |* M% J0 V! q# m2 A; f: Q$ }4 b9 A" C {+ R8 Y8 d. e3 W X int i; for(i=0;i<len;i++), L: e3 k. [* g! J9 c0 U {3 e3 t% o0 w. ^" Q0 d9 A+ l pdata = t; }. m2 W3 w h2 e. i7 G& A& Y } /**************************************************************. v' V+ b; ^' T% ~ * 函 数 名:HexToAscii6 ]1 b0 a! e2 j- i * 功能描述:十六进制转字符串% v0 P0 G/ s; `' X- m$ S * 输入参数:pHex 十六进制7 H3 p$ `- G5 ~8 @$ O# e * pAscii 字符串* d7 r v+ u. t, W" R$ }" A * nLen 长度 * 输出参数: void7 f; c( J8 V$ T * 注 释: 无 ***************************************************************/2 {) S- F" q5 }" d void HexToAscii(unsigned char *pHex, unsigned char *pAscii, int nLen) { unsigned char Nibble[2]; u0 S5 o- j/ S9 P0 _- i unsigned int i,j; for (i = 0; i < nLen; i++) { Nibble[0] = (pHex & 0xF0) >> 4; Nibble[1] = pHex & 0x0F;2 \" c- K9 n* Q3 k; { for (j = 0; j < 2; j++) { if(Nibble[j] < 10). A3 }( H" f; l+ \1 y1 \ {8 g, C# m: u8 g* c Nibble[j] += 0x30; } else" s$ Z0 Y: e4 K1 m) y) W {7 T0 `6 v9 W, H G8 h if(Nibble[j] < 16) Nibble[j] = Nibble[j] - 10 + 'A';( d# f" o7 c7 a O# F } *pAscii++ = Nibble[j]; } }3 H, Z' `2 n7 \0 V: M2 G *pAscii++ = '\0'; }# P2 R% C0 q: z( h1 L 3 N6 E! q8 z( K6 a ( y, }6 D2 l p. i- n' }) o; | |
不客气