新手上路
- 积分
- 23
- 金钱
- 23
- 注册时间
- 2020-7-27
- 在线时间
- 4 小时
|
1金钱
我遇到了一个匪夷所思的问题,我开启了IDLE中断和DMA中断,其中IDLE中断是可以正常运行的,DMA中断却始终无法进入中断服务函数,哪怕在IDLE中断中用串口打印了出了dma相应的中断标志位是1,但仍然无法进入dma中断服务函数,不知道问题出在了哪里,跪求大佬指点!下面是程序..烦请各路高手过目...
----------------------------------------------------------------------------------------------------------------------------------------------------------
//dma.c配置函数,其中设置dma缓冲为5,循环模式,开启DMA1_IT_TC5中断,dma抢占优先级为1,高于usart的中断优先级
void DMA_Config(DMA_Channel_TypeDef* DMA_CHx, u32 dir, u32 cpar, u32 cmar, u16 cndtr) //形参是在特定应用中需要格外声明的状态,该函数的作用是配置官方库函数中的 DMA_InitType 结构体
{
//使能DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//记录传输数据量
CNDTR = cndtr;
//配置DMA中断
NVIC_InitStructure_DMA.NVIC_IRQChannel = DMA1_Channel5_IRQn; //开启DMA中断通道
NVIC_InitStructure_DMA.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级2,优先于串口中断
NVIC_InitStructure_DMA.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure_DMA.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure_DMA); //根据指定的参数初始化VIC寄存器
//去初始化DMA
DMA_DeInit(DMA_CHx);
//为 DMA_InitTpyeDef 结构体成员赋值
DMA_InitStruct. DMA_PeripheralBaseAddr = cpar;
DMA_InitStruct. DMA_MemoryBaseAddr = cmar;
DMA_InitStruct. DMA_BufferSize = cndtr;
DMA_InitStruct. DMA_Priority = DMA_Priority_Medium;
DMA_InitStruct. DMA_DIR = dir;
DMA_InitStruct. DMA_Mode = DMA_Mode_Circular; //循环模式
DMA_InitStruct. DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct. DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct. DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct. DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct. DMA_M2M = DMA_M2M_Disable;
//DMA中断标志位初始化
DMA_ClearITPendingBit(DMA1_IT_TC5);
//DMA1_CH5_TC中断使能
DMA_ITConfig(DMA_CHx,DMA1_IT_TC5, ENABLE); //开启DMA1_CH5_TC中断,DMA传输完成标志!
//DMA初始化
DMA_Init(DMA_CHx, &DMA_InitStruct);
//使能DMA
DMA_Cmd(DMA_CHx, ENABLE);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------
//dma开启函数,过程为关闭dma,重新赋值dma缓冲通道,开启dma
void DMA_EnableCmd(DMA_Channel_TypeDef* DMA_CHx)
{
//每次开启DMA之前必须先重装在CNDTR,开启CNDTR之前必须关闭DMA
DMA_Cmd(DMA_CHx, DISABLE);
//重装在CNDTR
DMA_SetCurrDataCounter(DMA_CHx, CNDTR);
//开启本次DMA传输
DMA_Cmd(DMA_CHx, ENABLE);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------
//DMA1_IT_TC5中断服务函数,功能是每次dma传输完成后,将MyFlag全局变量置1,但是这个中断服务函数始终进不去!!难受≧ ﹏ ≦
void DMA_EnableCmd(DMA_Channel_TypeDef* DMA_CHx)
{
//每次开启DMA之前必须先重装在CNDTR,开启CNDTR之前必须关闭DMA
DMA_Cmd(DMA_CHx, DISABLE);
//重装在CNDTR
DMA_SetCurrDataCounter(DMA_CHx, CNDTR);
//开启本次DMA传输
DMA_Cmd(DMA_CHx, ENABLE);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------
//usart.c配置函数,其中开启了usart1的dma功能
void uart_init(u32 bound){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
//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
//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;//串口波特率
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_IDLE,ENABLE); //开启串口空闲检测IDLE中断
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //开启串口DMA接收
USART_Cmd(USART1, ENABLE); //使能串口1
}
----------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------
//IDLE中断服务函数,先打印dma对应的中断标志位,再打印MyFlag标志,其中MyFlag是一个全局变量,初始化为0,在dma中断服务函数中置1,也就是说如果打印得到DMA1_IT_TC5是1的话,MyFlag打印也应该得到1才对!但是实际情况是DMA1_IT_TC5打印值为1时,MyFlag依然打印值是0,说明根本没进入dma中断服务函数,要哭了...
if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
{
DMA_FLAG = DMA_GetFlagStatus(DMA1_IT_TC5); //获取DMA1_IT_TC5中断标志位
printf("The DMA1_TC5 status is %d\r\n",DMA_FLAG); //打印DMA1_IT_TC5中断标志位
printf("The MyFlag is %d\r\n",MyFlag); //打印MyFlag全局变量
printf("The IDLE status was SET!\r\n");
IDLE_ClearBit = USART_ReceiveData(USART1); //清除IDLE标志位
if(USART_GetITStatus(USART1,USART_IT_IDLE) == RESET)
{
printf("The IDLE status is CLEAR!\r\n");
if(MyFlag == 0)
{
Cmd = ServoCmd(USART_RX_BUF);
printf("The current Cmd is %d\r\n",Cmd);
if(Cmd >= 20 && Cmd <= 90)
{
printf("占空比是%d%%\r\n",Cmd);
Duty_Count = Cmd * arr /100;
TIM_SetCompare1(TIM4,Duty_Count); //IDLE中断控制TIM4_CH1的CCR寄存器,用于修改占空比
}
else printf("非法指令!请重新输入:(输入范围:20至90)\r\n");
}
else
{
MyFlag = 0; //如果超载,重新刷新MyFlag,本次USART_RX_BUF中的数据无效,不做处理!
printf("数据超载!请重新输入o3o\r\n");
}
DMA_EnableCmd(DMA1_Channel5); //重置DMA,使之从BUF[0]开始记录数据
printf("接收缓冲器内的数据是 %s\r\n",USART_RX_BUF); //打印USART_RX_BUF的数据
memset(USART_RX_BUF,0,sizeof(USART_RX_BUF));
}
}
用串口打印结果如下:
输入“50\r\n”时,数据长度还没有达到dma缓冲长度,可以得到正确的结果:DMA1_IT_TC5 = 0,MyFlag = 0;
输入“123\r\n”时,数据长度达到了dma缓冲长度,dma完成一次传输,DMA1_IT_TC5 = 1,但是MyFlag依然是0,说明DMA1_IT_TC5中断服务函数没有运行!!

麻烦大佬们看看鄙人哪里出了纰漏,感激不尽!
|
|