中级会员
 
- 积分
- 452
- 金钱
- 452
- 注册时间
- 2014-8-11
- 在线时间
- 87 小时
|
200金钱
帖子地址:http://www.openedv.com/posts/list/22466.htm
帖子题目:求助,串口DMA接收只能进一次中断,再收到一个字节就收不到了,万分苦恼中!
问题核心:开启接收DMA后,第一次中断正常进入中断服务程序,但是之后,无论如何初始化DMA接收的寄存器设置(即使设置为与初始化相同的代码),也无法再进入中断,而且观察DMA1_Channel5->CNDTR的值,发现再收到一个字符就停止了。
该贴的测试内容我在早期进行过,但当时比较顺利就飘过了。。。
我的测试贴(库函数版F103)地址:http://www.openedv.com/thread-64008-1-1.html
如今我在我之前的测试帖的内容下加了sd卡存储和gprs等功能,之前测试是没有问题的,后来我把波特率改为115200
就出现了和源求助帖一样的现象,在第一次传输完成中断顺利,中断处理完成后跟踪发现只传输了一个字符就不再传
输了。接着我把测试帖源程序中的波特率由9600改为115200发现传输没有问题,但在现在加额外功能的程序上却出现
了问题,我把这些功能都注释掉只留下DMA传输还是如此,核心代码如下
串口1的设置
[mw_shl_code=c,true]void uart_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
USART_DeInit(USART1); //复位串口1
//USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART1_RX PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
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(USART1, &USART_InitStructure); //初始化串口
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
//USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
USART_Cmd(USART1, ENABLE); //使能串口
}[/mw_shl_code]
DMA设置
[mw_shl_code=c,true]//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_CHx MA通道CHx
//cpar:外设地址
//cmar:存储器地址
//cndtr:数据传输量
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //打开DMA时钟线
/////////////////////////////////串口接收数据DMA的配置//////////////////////////////////////
USART_DMACmd(USART1,USART_DMAReq_Rx,DISABLE);
DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从内存读取发送到外设
DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小
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; //工作在正常缓存模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//工作在循环模式下
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //DMA通道 x拥有中优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA_CHx, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
DMA_ClearFlag(DMA1_FLAG_TC5); //清除DMA接收完成标志
DMA_ClearFlag(DMA1_FLAG_TE5); //清除DMA接收错误标志DMA1_FLAG_TE5
DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);//DMA5传输完成中断
DMA_ITConfig(DMA1_Channel5, DMA_IT_TE, ENABLE);//DMA5传输错误中断DMA_IT_TE
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);//使能USART1的接收DMA请求
Free_Buf_No=BUF_NO2; //因为 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART1_DMA_Buf1;
Buf_Ok=0; //此时没有数据准备完成 当然FALSE
COM_DMA_NVIC_Config();
//DMA_Cmd(DMA1_Channel5, ENABLE); //正式允许DMA
MYDMA_Enable(DMA1_Channel5);
}[/mw_shl_code]
传输完成中断
[mw_shl_code=c,true]void DMA1_Channel5_IRQHandler(void)
{
OSIntEnter();
if(DMA_GetITStatus(DMA1_IT_TC5)) //通道5传输完成中断TC 还有传输 过半中断HT 错误中断TE 全局中断GL
{
MYDMA_Disable(DMA1_Channel5);
DMA_ClearITPendingBit(DMA1_IT_GL5); //清除全部中断标志
DMA_InitStructure.DMA_BufferSize = (u16)500;
//转换可操作BUF
if(Free_Buf_No==BUF_NO1)
{
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART1_DMA_Buf1;
FIFO_WRITE_BUF(RX_BUF_FIFO,USART1_DMA_Buf2,USART1_RX_BUF2_SIZE);
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
Free_Buf_No=BUF_NO2;
LED0=!LED0;
}
else
{
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART1_DMA_Buf2;
FIFO_WRITE_BUF(RX_BUF_FIFO,USART1_DMA_Buf1,USART1_RX_BUF1_SIZE);
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
Free_Buf_No=BUF_NO1;
LED1=!LED1;
}
Buf_Ok=1; //有准备好的数据了
MYDMA_Enable(DMA1_Channel5);
}
if(DMA_GetITStatus(DMA1_IT_TE5))
{
DMA_ClearITPendingBit(DMA1_IT_GL5); //清除全部中断标志
BEEP=1;
MYDMA_Enable(DMA1_Channel5);
}
OSIntExit();
}[/mw_shl_code]
完整源代码下载调试请附件下载

|
|