初级会员

- 积分
- 94
- 金钱
- 94
- 注册时间
- 2018-2-27
- 在线时间
- 32 小时
|
5金钱
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_dma.h"
#include "misc.h"
#include <stdlib.h>
#include <stdio.h>
#include "string.h"
#define DMA_Rec_Len 200
u8 DMA_Rece_Buf[DMA_Rec_Len];
u16 Usart1_Rec_Cnt=0;
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
_sys_exit(int x)
{
x = x;
}
//ÖØ¶¨òåfputcoˉêy
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);
USART1->DR = (u8) ch;
return ch;
}
#endif
void RCC_Config()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE) ;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
}
void GPIO_Config()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
void USART1_Config()
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
USART_Cmd(USART1, ENABLE);
}
void NVIC_Config()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void DMA_Config()
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DMA_Rece_Buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = DMA_Rec_Len;
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;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel5, ENABLE);
}
void MYDMA_Enable(DMA_Channel_TypeDef* DMA_CHx)
{
DMA_Cmd(DMA_CHx, DISABLE );
DMA_SetCurrDataCounter(DMA_CHx,DMA_Rec_Len);
DMA_Cmd(DMA_CHx, ENABLE);
}
void Usart1_Send(u8 *buf,u8 len)
{
u8 t;
for(t=0;t<len;t++)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1,buf[t]);
}
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
void USART1_IRQHandler(void)
{
int i;
u16 x;
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
{
USART_ReceiveData(USART1);
Usart1_Rec_Cnt = DMA_Rec_Len-DMA_GetCurrDataCounter(DMA1_Channel5);
Usart1_Send(DMA_Rece_Buf,Usart1_Rec_Cnt);
USART_ClearITPendingBit(USART1, USART_IT_IDLE);
MYDMA_Enable(DMA1_Channel5);
}
}
int main(void)
{
int i;
for( i=10000000;i>0;i--)
;
RCC_Config();
GPIO_Config();
USART1_Config() ;
NVIC_Config();
DMA_Config();
while(1)
{
USART1_IRQHandler() ;
for( i=1000000;i>0;i--)
;
}
}
这个程序是学习原子哥的程序编写的,在stm32f103已经调试成功,程序功能是从电脑的串口调试助手上发送一个不定长数据到单片上,然后单片机再将该数据返回发送给电脑。运行结果如下图
,
问题:我查看了很多利用IDLE串口空闲中断和DMA来发送和接收数据时,都写了“当单片机接收不定长数据时,DMA默默的将串口上的数据转移到缓冲区”,我想知道的是:
1、当多个字节发送给USART1时,USART1_DR只能接收1个字节,DMA依靠什么来判断要转移这个字节,毕竟我只打开了IDLE中断并没有打开RNXE和TC中断
2、请问一下,该程序运行时数据的转移过程及各个中断的变化情况
|
最佳答案
查看完整内容[请看2#楼]
没有看你写的大段东西
按照我自己用的DMA空闲中断接收和DMA发送给你大概解释一下
初始状态空闲中断不会触发,当你收到数据 比如0x01,0x02,0x0d,0x0a这一帧数据,按一定波特率发过来,当你收到0x01的时候空闲中断也不会触发,直到你收到0x0a的时候,空闲中断触发,这个时候DMA已经把串口上收到的4个字节搬到你的数据缓冲区了,你只需要在空闲中断触发当中把DMA重新设置好接收长度和目标地址,并置位一个标志告诉你的主程序有一帧数据已经 ...
|