OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 12100|回复: 7

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

[复制链接]

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2014-1-19
在线时间
6 小时
发表于 2016-10-23 11:05:22 | 显示全部楼层 |阅读模式
10金钱
各位大神,最近做项目遇到一问题,如下:功能要求:串口要接收大量数据,用于绘图;使用串口屏绘图,每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,正常。求救!!!!


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-10-24 23:06:53 | 显示全部楼层
你的串口又要发送,又要接收?
回复

使用道具 举报

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2014-1-19
在线时间
6 小时
 楼主| 发表于 2016-10-26 03:58:06 来自手机 | 显示全部楼层
本帖最后由 doleph 于 2016-10-28 16:41 编辑

使用串口5发数据的,因为在主函数的while循环中要进行键盘检测,有较长延时,不能完成实时绘图工作,所以只能用定时器。把定时器间隔改成100ms就没问题了,但不能满足要求。
回复

使用道具 举报

2

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2016-6-25
在线时间
13 小时
发表于 2016-12-6 12:15:29 | 显示全部楼层
正点原子 发表于 2016-10-24 23:06
你的串口又要发送,又要接收?

原子哥,我的是,就是串口发送与接收都有,请问如何解决像楼主这样的问题呢?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2016-12-8 22:07:31 | 显示全部楼层
拽拽君 发表于 2016-12-6 12:15
原子哥,我的是,就是串口发送与接收都有,请问如何解决像楼主这样的问题呢?

1,尽量提高串口波特率。
2,尽量使用DMA接收。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2015-4-12
在线时间
3 小时
发表于 2017-1-13 21:15:30 | 显示全部楼层
我用的是串口接传感器模块,只有接接收到命令,才会返回数据,采用定时器TIM3每隔500ms发一次命令,在主程序的while(1)中发送命令是正确的,但进入不了串口2的接收中断程序,请教应该如何处理
回复

使用道具 举报

1

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2016-3-9
在线时间
7 小时
发表于 2017-4-26 13:42:52 | 显示全部楼层
楼主 问题解决了吗 我也遇到这个问题,我用定时器产生一个4us的延时 串口用来收发数据,但是两个程序不能同时运行,我先是定时器初始化然后串口初始化,两个必须隐掉一个程序才能往下走,不知道是哪里的原因
回复

使用道具 举报

36

主题

195

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
313
金钱
313
注册时间
2014-10-27
在线时间
34 小时
发表于 2017-5-17 15:46:47 | 显示全部楼层
jingsiniao 发表于 2017-1-13 21:15
我用的是串口接传感器模块,只有接接收到命令,才会返回数据,采用定时器TIM3每隔500ms发一次命令,在主程 ...

你好,我最近也遇到类似问题,串口同时发送和接收,接收采用的中断,发现发送的时候会导致接收无法进入中断,但是程序没死,还在跑?可以一起交流下吗。我qq:527050828
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-8-21 04:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表