7 i$ {* |0 y. E+ V5 `3 L8 m# B$ Y 直接上代码 /******************************************************************************** * 函 数 名: USART_Config()4 V& Z- S* V0 u1 {- y * 功能描述: 配置USART的GPIO口6 y( b& y4 r. Q/ A * 输入参数: bau 串口波特率4 x" r- T5 T( |" ]* S * 输出参数: void * 注 释: 配置USART串口参数 ********************************************************************************/! f1 N( N0 \8 }$ p2 k void USARTx_Config(USART_TypeDef* USARTx,unsigned int bar) { USART_InitTypeDef USART_InitStructure;' b* q7 y/ u: ?9 g" d- k //USART1 初始化设置 USART_InitStructure.USART_BaudRate = bar; //波特率设置0 F* v) ^7 Y3 s! i) d! V: D USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位7 t6 u# ^" o ]6 X1 A USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位: \! z7 `" l( t8 K2 r4 G/ { USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式" Y9 Z5 u7 e- b) i USART_Init(USARTx, &USART_InitStructure); //初始化串口1) M/ y# z7 c, o }/ o- ^; Z0 D; J' s5 w- i9 @ t /********************************************************************************8 K: Y% }* l# h * 函 数 名: USARTx_IT_Config() * 功能描述: 配置USART的GPIO口 * 输入参数: irq 中断通道号6 }/ y- [' g) u% u * Pre 抢占优先级. G4 Q6 X9 Z- W% n, Z a9 Y9 ? * Sub 子优先级! A+ B# J) R0 w! l5 }# M& | * 输出参数: void * 注 释: 配置串口中断& z4 G$ x" |. p- V ********************************************************************************/ void USARTx_IT_Config(unsigned char irq,unsigned char Pre,unsigned char Sub) { NVIC_InitTypeDef NVIC_InitStructure;9 y; [' x) k9 O: W9 C //Usart1 NVIC 配置9 ?5 h) o- Y! h, |8 U$ ^* w" n6 V NVIC_InitStructure.NVIC_IRQChannel = irq; //串口1中断通道- ^" z g& [2 O6 T; p2 p# ^ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=Pre;//抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority =Sub; //子优先级' I# H% L9 e* n- P4 A5 d NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、 & N S+ y. X0 k6 E. G! a% P; I }7 d* M; S) ^, V5 I# e7 Y; | /******************************************************************************** * 函 数 名: USARTx_DMA_Config() * 功能描述: 配置USART的DMA通道% J7 ^! T$ J- a/ S, D* j* Y9 G * 输入参数: DMAy_Channelx 通道号 * paddr 外设地址 (串口的DR地址,详情配置见Init代码)2 q. w3 x$ I' a+ X+ W h * Maddr 存储器地址- r& ~9 c7 K* z * dir 模式 DMA_DIR_PeripheralDST(存储器到外设) DMA_DIR_PeripheralSRC(外设到存储器) * size 传输数据量- W( r; j4 ~3 i8 K * 输出参数: void( I" K% T a) z# S0 v9 t! j- E/ _ * 注 释: 配置串口中断5 L; i% ~: {% s/ r ********************************************************************************/ 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;5 m F2 ~. O0 Y& s! z H DMA_DeInit(DMAy_Channelx); /* 配置 DMA 发送通道*/2 a; X! W5 Y0 |% `2 m# | DMA_InitStructure.DMA_PeripheralBaseAddr = paddr; //DMA外设地址 DMA_InitStructure.DMA_MemoryBaseAddr = Maddr; //DMA 存储器地址! m; [ u2 u7 c L. s- s; J DMA_InitStructure.DMA_DIR = dir; //存储器到外设模式) A: g& h2 ^+ m' B DMA_InitStructure.DMA_BufferSize = size; //数据传输量 . i- ^: d9 R( {7 x4 [: ~ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式/ w& [9 q3 z1 O9 p DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度:8位2 N( j& w. ^$ p' A1 I6 j% i( j DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //使用普通模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //中等优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输' t% \$ r" L% t DMA_Init(DMAy_Channelx, &DMA_InitStructure); //初始化DMA } /********************************************************************************1 V$ k/ ]# ^, G% `! Y. @6 q * 函 数 名: USART_Init() * 功能描述: 配置USART * 输入参数: void * 输出参数: void: t+ F# b# a, d% i6 q * 注 释: 配置USART串口参数) Y, @ Z* f4 a h; b i4 i ********************************************************************************/, x: b: n4 n! V) p$ @ void USARTx_Init(void)% K, W5 H1 P; Q& ]8 H z { /*USART1 config*/ USARTx_Config(USART1,115200);1 W9 ?- ?0 E: _& x/ T/ Z USART_Cmd(USART1, ENABLE); //使能串口1 USART_ClearFlag(USART1, USART_FLAG_TC); /*清除发送中断标志*// r& b; a4 s- {' t USART_ClearFlag(USART1, USART_IT_IDLE); /*清除空闲中断标志*/ USART_ITConfig(USART1, USART_FLAG_TC, ENABLE); /*开启空闲中断*/ USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); /*开启空闲中断*/ 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);; }7 u" O8 Q( u USART_DMACmd(USART1, USART_DMAReq_Tx|USART_DMAReq_Rx, ENABLE); /* 使能DMA串口发送和接受请求 */, Q; x! N3 }8 p; R. e7 d DMA_Cmd(DMA1_Channel5,ENABLE); /*打开接收数据通道*/: c" C A% K- W UserMemset((unsigned char *)&USARTStr,0,sizeof(USARTStr)); u1 O6 H$ D/ |1 k+ Z' i( S /*USART2 config*/$ U3 O! o! Y/ t; F( V USARTx_Config(USART2,115200);- a* r- h! g! t- w: e: B3 S+ N0 c USART_Cmd(USART2, ENABLE); //使能串口1 USART_ClearFlag(USART2, USART_FLAG_TC); /*清除发送中断标志*/ USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); /*开启空闲中断*/ USARTx_IT_Config(USART2_IRQn,0,1); 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); /*打开接收数据通道*/7 J0 p" F7 ?# S1 [8 F* } UserMemset((unsigned char *)&USART2Str,0,sizeof(USART2Str)); }; c4 \, L6 K J6 U( w/ r+ X- b /********************************************************************************$ G" Y5 X# r. E% K3 u3 X * 函 数 名: USART1SendData * 功能描述: 串口1DMA发送数组, [6 }' ?) c/ u" ? * 输入参数: buf 发送的数组 * len 数组长度% b* n& r% B0 n6 k# V * 输出参数: void. j" `$ @& J, w& U. M * 注 释: 无 ********************************************************************************/, V r, m% L' `) C# j( ~ void USART1SendData(unsigned char *pData,unsigned short size) { UserCopy(USARTStr.SendBuff,pData,size);. U- ~6 T- X6 ]. V1 d1 M( Q DMA_Cmd(DMA1_Channel4,DISABLE); DMA1_Channel4->CNDTR = size; DMA_Cmd(DMA1_Channel4,ENABLE);1 J* m' m# J0 X' a* b3 X% N1 D* F }0 Y! g: r* t; N# u+ c9 ] /******************************************************************************** * 函 数 名: USART1_IRQHandler * 功能描述: 串口接收中断& ?& Y; z2 d, J9 X& q * 输入参数: void0 f! J- _+ m0 a* G * 输出参数: void. @8 O; i4 f$ ` * 注 释: 无 ********************************************************************************/ void USART1_IRQHandler(void) {8 b7 ~5 _: a. _( J% s% k0 \1 n$ o unsigned char temp;: A$ h* I0 P3 o# z if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //空闲中断- a' I6 S' x0 j4 M {. T" U4 {: a2 i) y- U temp = USART1->SR; temp = USART1->DR; temp = temp;% H t' z# U* v+ U% n8 p# G USARTStr.Len = USART_BUFSIZE - DMA1_Channel5->CNDTR; USARTStr.Flag = 0x80;5 c( C% a6 c: R; ~5 Z% m DMA_Cmd(DMA1_Channel5, DISABLE);) F$ \7 g9 d- X, F. o, z, R DMA1_Channel5->CNDTR=USART_BUFSIZE; z& p# T6 Z( K& L/ b# E DMA_Cmd(DMA1_Channel5, ENABLE); USART_ClearITPendingBit(USART1, USART_IT_IDLE); } if(USART_GetITStatus(USART1, USART_FLAG_TC) != RESET) //传输完成中断 { USARTStr.Flag = 0; UserMemset((unsigned char *)&USARTStr,0,USARTStr.Len);! u% H) r: ^' o }9 X3 ~! _2 L9 I$ z- H: d } u" s: r* w3 ^+ h 下面是变量的声明 1 y j+ Z# o, C1 y$ F2 @ #define USART_BUFSIZE 1024 /*最大接收串口数据的值*/ # K i& Q# r" E. {( d2 z, e2 c /**************************************************************************** * Local Types. n) x* g% e3 J5 S. ]- P ****************************************************************************/: f, G1 K' W# U; X; }8 Y8 U6 t0 l " `9 d3 \ g: G- [* E- T typedef struct TagUSARTStruct{ /*声明结构体来接收串口的数据*/ unsigned short Len; unsigned char Flag; unsigned char SendBuff[USART_BUFSIZE]; /* 发送数据 */ unsigned char ReadBuff[USART_BUFSIZE]; /* 接收数据 */ ! c! H* O3 M) R5 Z! K7 b( u8 ? }T_USARTStruct; 5 ?, C+ g( D0 V extern T_USARTStruct USARTStr; /*外部调用声明*/ extern T_USARTStruct USART2Str; E5 {& [: @7 \6 K9 v # d( q, y9 G' L5 V/ J9 X% _ 串口的gpio配置是好搞的我就补贴上代码了 千万记住打开相关的时钟配置 /* open DMA1 clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); 以上的配置代码是测试完全通过的,在DMA中所说的外设到内存其实是配置了串口的DR数据地址映射到全局变量中,所说的外设是STM32在M3内核上添加的功能,例如:串口,IIC,SPI,ADC,DAC等这些外设,配置DMA时候把这些地址给到DMA外设地址配置上去,DMA内存是把代码中的全局变量的地址。STM32DMA有三种模式:内存到内存和外设到内存、内存到外设。使用接收PC端或者其他设备发送过来的数据在配置DMA时候必须提前打开,否则接收不到数据。例如串口1接收数据在配置DMA1通道5时候,在配置时要事先使能打开。通道4是用于发送数据出去可以填写好发送内容再打开,填数据前必须先关闭通道,中断可以根据需求去配置,但是配置了中断记得及时的清除标志位。否则发生整个程序在不断的执行中断代码,主程序代码无法执行,包括DMA的中断配置可根据手册查询配置,同样配置了,也要及时的清除中断标志。使用C自带微型库会增加代码大小,使用不多其实建议自己写,下面贴出代码。 d+ ~1 ]1 V# r* a$ U5 [3 p8 [ . `0 ?. J" r) l /******************************************************************************** * 函 数 名: UserCopy& P7 B0 Z* i% z# I * 功能描述: 拷贝数据 * 输入参数: pdata 拷贝到的数组 * data 要拷贝的数组; F% u/ Q& b3 b) Y, i * len 拷贝的长度" @, r5 F, @5 j) ?+ Z * 输出参数: void% }) U; Y# f* e. v* W * 注 释: 无9 J4 S! k6 l+ A v3 O/ B# L ********************************************************************************/. M; W0 [" s! d V7 H! u void UserCopy(unsigned char *pdata,unsigned char *data,int len)4 C; W, ?6 ^! M { int i; for(i=0;i<len;i++)" n+ r' C! Y# f1 C: n6 ` { pdata = data;- g) q$ }# Y* S% m3 N } }1 F' s, C8 E- d /********************************************************************************: @0 T5 w- L9 X2 l+ j8 [ * 函 数 名: UserMemset * 功能描述: 清除数据 * 输入参数: pdata 要清楚的数组. C6 t) Y2 Q: ^( e; s x * t 填充的数据+ ^% N+ g, K7 Z * len 数组长度+ ]7 Z! J2 J( Y. U9 ~* O * 输出参数: void7 j; c& X$ W5 ]3 H2 m * 注 释: 无 ********************************************************************************/1 ]) D" f! Q7 M void UserMemset(unsigned char *pdata,char t,int len) { int i;& G# N+ g) v z- L for(i=0;i<len;i++) {: p/ [1 d' H; Z: @ pdata = t; }1 |4 H& o! K6 J* n+ U }5 I3 W: q: r6 Y+ J8 g9 W /**************************************************************& B5 w) B" H$ m1 o3 B. D: }! o * 函 数 名:HexToAscii * 功能描述:十六进制转字符串 * 输入参数:pHex 十六进制 * pAscii 字符串( Z5 @# Q3 @* T# {" W) I/ Z/ } * nLen 长度 * 输出参数: void; n! g) c; a+ t& l& r * 注 释: 无 ***************************************************************/* P+ v5 k7 O: v* C+ s$ Q6 F2 h void HexToAscii(unsigned char *pHex, unsigned char *pAscii, int nLen)1 R& r. ^9 `6 j8 G4 e# U {. H3 P5 w' y" z/ ]6 I unsigned char Nibble[2]; unsigned int i,j;* h# ]9 N4 p; b' Q8 Z) b' g5 g; N for (i = 0; i < nLen; i++)0 D8 ]* T2 @ U7 F, r: M {* a# F& Z8 Q8 X$ Q$ A o Nibble[0] = (pHex & 0xF0) >> 4;, a7 [' f- A+ j0 d/ x1 t' P Nibble[1] = pHex & 0x0F; for (j = 0; j < 2; j++) {" ? \6 `( v$ p9 z+ q4 n if(Nibble[j] < 10)5 F9 w6 x3 [- o* Y$ W { Nibble[j] += 0x30;3 N* g% `' p8 b } else2 P& ~8 c/ O- }* q' \ { if(Nibble[j] < 16) Nibble[j] = Nibble[j] - 10 + 'A'; } *pAscii++ = Nibble[j];' s( D' x9 C. c! w1 X }* t* n- x4 {9 w# n# B) j7 n6 s; s } *pAscii++ = '\0'; } ! \4 z; }% Q" H) q% B* I: | ! ?9 q; T; d' ?' g( j6 v4 z9 S. h 5 `4 T* g8 L8 L3 C0 X, @& ~ |
不客气