背景说明
以前写以前写串口接收是:
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
微信看了一篇文章,我这种方法比较低能了,别人用的串口空闲中断,数据接收完毕以后,空闲,随即触发DMA来搬运数据到内存
这一部分我已经试验成功了。
现在我想实现DMA数据搬运完成以后触发DMA的中断,但是搞了一上午没找到问题,求助。
- void uart_init(u32 bound)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- //1时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);
-
- //2GPIO USART1_TX GPIOA.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);//初始化GPIOA.9
-
- //USART1_RX GPIOA.10初始化
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
- GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
- //3中断 NVIC 配置
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
- NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
- //4配置 USART设置
- USART_InitStructure.USART_BaudRate = bound;//串口波特率
- 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); //初始化串口1
- // USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
- // USART_Cmd(USART1, ENABLE); //使能串口1
- USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
- USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
- USART_Cmd(USART1,ENABLE);
- DMA_init();
- }
复制代码
- void DMA_init(void)
- {
- DMA_InitTypeDef DMA_Initstructure;
- NVIC_InitTypeDef NVIC_Initstructure;
-
- /*开启DMA时钟*/
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
- DMA_DeInit(DMA1_Channel5); ///////
- /* Enable the DMA1 Interrupt */
- NVIC_Initstructure.NVIC_IRQChannel = DMA1_Channel5_IRQn; //通道设置为串口1中断
- NVIC_Initstructure.NVIC_IRQChannelSubPriority = 2; //中断响应优先级0
- NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority=3;
- NVIC_Initstructure.NVIC_IRQChannelCmd = ENABLE; //打开中断
- NVIC_Init(&NVIC_Initstructure);
-
-
- /*DMA配置*/
- DMA_Initstructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);;
- DMA_Initstructure.DMA_MemoryBaseAddr = (u32)receive_data;
- DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC;
- DMA_Initstructure.DMA_BufferSize = 128;
- 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_High;
- DMA_Initstructure.DMA_M2M = DMA_M2M_Disable;
- DMA_Init(DMA1_Channel5,&DMA_Initstructure);
- DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
- DMA_Cmd(DMA1_Channel5,ENABLE);
- }
复制代码 结果就是void USART1_IRQHandler(void)正常 可以进来
{
// unsigned char num=0;
// if(USART_GetITStatus(USART1,USART_IT_IDLE) == SET)
// {
// num = USART1->SR;
// num = USART1->DR; //清USART_IT_IDLE标志
// DMA_Cmd(DMA1_Channel5,DISABLE); //关闭DMA
// num = 128 - DMA_GetCurrDataCounter(DMA1_Channel5); //得到真正接收数据个数
// receive_data[num] = '\0';
// DMA1_Channel5->CNDTR=128; //重新设置接收数据个数 DMA_Cmd(DMA1_Channel5,ENABLE); //开启DMA
// // receive_flag = 1; //接收数据标志位置1
// DMA_Cmd(DMA1_Channel5,ENABLE); //开启DMA
// printf("%s ",receive_data );
// }
}
void DMAChannel5_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC5) != RESET)
{
TestLive();
DMA_ClearITPendingBit(DMA1_IT_TC5);
}
//进不来
}
说明:我百度找了找别人的问题,一种是中断函数名字的问题,我这里不存在这个问题,如图
|
串口助手循环不停的发送
现在注意到一个现象 中断在CNDRT为0是可以进去的
所以我的配置是有问题的 发个几十次 DMA表示完成了
代码问题大了 我DMA设置的是128个bit 串口过来数据其实是不定长的而我在128的时候才表示传输完成,。。。是不是无法这样写了。。
参考:http://blog.csdn.net/u010001130/article/details/77816020 所以void DMAChannel5_IRQHandler(void)这个函数一般没啥用?
4. DMA接收数据初始化
在串口使用DMA接收时,由于不知道数据传输的长度,故不能使能DMA接收中断。
评分
查看全部评分
嗯 我的思路好像有问题 串口空闲中断+DMA可以的 不能再加DMA中断 你的这个评论 我又迷糊了:空闲中断是怎么发生的?我上午以为是PC上位机 发送结束不在发送 那么串口空闲产生的中断 随后触发DMA去搬 你的说法是DMA搬运完数据 串口产生空闲中断
是的 是搬完了 再进空闲中断的
void USART1_IRQHandler(void)
{
unsigned char num=0;
memset(receive_data,0,128);..此后看到清空了
当波特率确定后,一个字节的接收时间就已经确定了(假设当前波特率下一字节的发送时间为1ms),假设串口一直在接收数据,突然有1ms空闲下来,没有数据可接收了,这时CPU就可以提出串口空闲中断了;原理就是这样。DMA是自动搬运工,当有匹配数据时,它自然会去搬。
评分
查看全部评分