请教定时器中断与串口中断优先级配置问题

2019-08-18 21:27发布

各位大神,最近做项目遇到一问题,如下:功能要求:串口要接收大量数据,用于绘图;使用串口屏绘图,每5ms刷新一次。

实现过程:使用TIM3,每5ms取一次数据,并发送一次绘图命令,优先级设置为抢占3,组内2;使能串口1接收中断(或DMA空闲中断),把数据放置在某缓冲区,优先级设置为最高(抢占0,组内0);中断优先级分组为2。
故障表现:定时器绘图正常,但串口接收大量数据丢失,把TIM3关掉,或者TIM3中断时间改成100ms,串口就能正常工作。貌似定时器优先级比串口优先级高,非常奇怪。
部分代码如下:
void USART1_Init(uint32_t baud)
{
    USART_InitTypeDef USART1_InitStruct;
          GPIO_InitTypeDef GPIO_InitStruct;
          NVIC_InitTypeDef NVIC_InitStruct;
       
          //enable clock
          RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);   
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
          
          //reset usart1
          USART_DeInit(USART1);
       
          //init GPIO
          //PA9 TX
          GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
    //PA10 RX
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
          GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
          GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
          GPIO_Init(GPIOA,&GPIO_InitStruct);
       
    //Init usart
          USART1_InitStruct.USART_BaudRate=baud;
          USART1_InitStruct.USART_WordLength=USART_WordLength_8b;
          USART1_InitStruct.USART_StopBits=USART_StopBits_1;
          USART1_InitStruct.USART_Parity=USART_Parity_No;
          USART1_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
          USART1_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
          USART_Init(USART1,&USART1_InitStruct);
          //init NVIC
                NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
                NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
                NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
                NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
                NVIC_Init(&NVIC_InitStruct);
    //enable rx interrupt
          USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
                //enable usart1
          USART_Cmd(USART1,ENABLE);
               
}




void SendChar1(char ch)
{
          USART_SendData(USART1,ch);
          while(!USART_GetFlagStatus(USART1,USART_FLAG_TC));
          USART_ClearFlag(USART1,USART_FLAG_TC);
}


void SendStr1(char *str)
{
          while(*str)
                {
                          SendChar(*str);
                          str++;
                }
}


void USART1_IRQHandler(void)
{
          if(USART1->CR1 & RXNEIE)
                {
                          
                          //receive first byte
                          *(usart1->buff+0)=USART1->DR;
                          SendChar1(*(usart1->buff+0));//直接转发
                          USART_ClearFlag(USART1,USART_IT_RXNE);

          }


//定时器代码
void TIM3_Init(u16 arr,u16 psc)
{
          NVIC_InitTypeDef NVIC_InitStruct;
          TIM_TimeBaseInitTypeDef TIM_InitStruct;
       
          RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
       
          TIM_InitStruct.TIM_Period=arr;
          TIM_InitStruct.TIM_Prescaler=psc;
          TIM_InitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
          TIM_InitStruct.TIM_CounterMode=TIM_CounterMode_Up;
          TIM_TimeBaseInit(TIM3,&TIM_InitStruct);
          TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
       
          NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0x03;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority=0x02;
    NVIC_Init(&NVIC_InitStruct);               
                  
                TIM_Cmd(TIM3,ENABLE);
}

void TIM3_IRQHandler(void)
{
          if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
                {
         TEST_LED_ON();

                                    if(rt->Data_Length>0&&rt->ECG_Started==TRUE)
                                 {
                                          
                                                                 //set end point position
                                                               
                                                                 rt->EndPoint.x = ECG_START_DRAWING_POS_X + 1 + (u16)(ECG_SCALE_X*rt->time_Counter);                                              
                                                                 rt->EndPoint.y = ECG_DRAWING_BASELINE_Y +0x80- rt->pData[rt->Data_Index];
                                                         
                                                                 if(rt->EndPoint.x > ECG_END_DRAWING_POS_X)
                                                                 {
                                                                                 rt->EndPoint.x=ECG_START_DRAWING_POS_X;
                                                                                 rt->time_Counter=0;
                                                                                 rt->StartPoint.x=ECG_START_DRAWING_POS_X;
                                                                                 rt->StartPoint.y=rt->EndPoint.y;
                                                                 }       
                                                                 
                                                                 if(rt->StartPoint.x<455)
                                                                 {
                                                                         //draw line
                                                                         DrawLine(&rt->StartPoint,&rt->EndPoint);
                                                                 }
                                                                 rt->StartPoint.x=rt->EndPoint.x;
                                                                 rt->StartPoint.y=rt->EndPoint.y;
                                                                 
                                                                 rt->time_Counter=(rt->time_Counter+1)%459;
                                                                 //change ECG_Data index
                                                                 rt->Data_Index=(rt->Data_Index+1)%rt->Data_Length;
                           }
                           TEST_LED_OFF();
                 }
                 TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}


初始化部分:

USART1_Init(9600);
TIM3_Init(49,7199);//5ms
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

用示波器看TIM3中断,脉宽5ms,正常。求救!!!!


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
正点原子
1楼-- · 2019-08-19 01:40
 精彩回答 2  元偷偷看……
doleph
2楼-- · 2019-08-19 01:56
本帖最后由 doleph 于 2016-10-28 16:41 编辑

使用串口5发数据的,因为在主函数的while循环中要进行键盘检测,有较长延时,不能完成实时绘图工作,所以只能用定时器。把定时器间隔改成100ms就没问题了,但不能满足要求。
拽拽君
3楼-- · 2019-08-19 07:01
正点原子 发表于 2016-10-24 23:06
你的串口又要发送,又要接收?

原子哥,我的是,就是串口发送与接收都有,请问如何解决像楼主这样的问题呢?
正点原子
4楼-- · 2019-08-19 11:38
拽拽君 发表于 2016-12-6 12:15
原子哥,我的是,就是串口发送与接收都有,请问如何解决像楼主这样的问题呢?

1,尽量提高串口波特率。
2,尽量使用DMA接收。
jingsiniao
5楼-- · 2019-08-19 14:46
我用的是串口接传感器模块,只有接接收到命令,才会返回数据,采用定时器TIM3每隔500ms发一次命令,在主程序的while(1)中发送命令是正确的,但进入不了串口2的接收中断程序,请教应该如何处理
婵宝1016
6楼-- · 2019-08-19 20:15
 精彩回答 2  元偷偷看……

一周热门 更多>