打印
[STM32F7]

串口中断问题求教?

[复制链接]
2337|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
最近公司一个项目,使用的核心板是正点原子的F767,自己设计了外部电路,现在在串口通讯是有点问题无法解决。
其中用到几个串口,和定时器,其中串口1是和上位机通讯,串口1的优先级最高,抢占优先级是1,其他串口和定时器都是2和3,串口1需要将ADC采集的数据每100ms一次上传给上位机;同时接收上位机的控制指令。串口1我只打开了接收中断,在接受中断中的唯一操作是将接收到的字节存入到我事先准备好的缓存数组中。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)      
{
if(huart->Instance==USART1)
{
   UART1_RX_BUF[++UART1_ReceiveBuf_Count] = aRxBuffer_UART1[0];   //将接收到的字节存入自己定义的接收缓存数组中
  if(UART1_ReceiveBuf_Count%50==0) LED1_Toggle;
}
每次ADC采集完成(100ms),将采集的值存入到我自己定义的发送缓存数组中,串口1的发送是循环发送,主循环中每次最多发送一个字节,主循环很快。
  if(ADC_Sampling_Enable==0)   //1组采样完成
  {
    Vin1=2.5*ADS1251_Read_middle(ADC_Sample)/0x7fffff;
    ADC_Sampling_Enable=1;    //开启下一组采样
   UART1_DisposalTemp[0]='?';    //头
   UART1_DisposalTemp[1]='1';    //表示主板的信息
   UART1_DisposalTemp[2]='1';    //表示测量的电压
   UART1_DisposalTemp[3]='1';    //对应的档位
      ADC_float_to_ascll(Vin1,UART1_DisposalTemp) ;
     UART1_DisposalTemp[11]='#';
     //printf(urt_disposaltemp);
    for(i=0;i<12;i++)
    {
     UART1_TX_BUF[++UART1_SendBuf_Count]=UART1_DisposalTemp[i];   //ADC采样值存入到自己定义的发送缓存数组中,等待发送
   }
   }


   if(UART1_SendBuf_Count!=UART1_SendBuf_Current)  //main循环中发送串口数据,此处每次最多发一个字节
  {
     HAL_UART_Transmit(&UART1_Handler,(uint8_t*)(&UART1_TX_BUF[++UART1_SendBuf_Current]),1,1000); //发送接收到的数据
   while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET);  //等待发送结束
  }

问题如下:
串口1发送没问题,但是接收一段时间后会出现无法接收的现象,程序没有卡死,因为串口还在定时发送,但是就是无法进入串口接收中断。当我串口不发送时(把这句注释掉://UART1_TX_BUF[++UART1_SendBuf_Count]=UART1_DisposalTemp[i]; ),则串口接收就没问题。一开始以为接收中断是不是打开,调试时确认没打开(TXEIE和TCIE都是0);请教,这个可能是什么原因?
沙发
hudi008| | 2017-5-17 23:02 | 只看该作者
先试试复位之后会不会出现这个现象

使用特权

评论回复
板凳
hudi008| | 2017-5-17 23:05 | 只看该作者
以前遇到过串口开始不能接收,复位之后可以接收这个现象。

使用特权

评论回复
地板
qq12344321|  楼主 | 2017-5-18 10:18 | 只看该作者
hudi008 发表于 2017-5-17 23:05
以前遇到过串口开始不能接收,复位之后可以接收这个现象。

如果串口是在不停发送,复位后串口能收到几条,但是过会就不能进入串口接收中断了,程序没死,发送还是正常。不太清楚为什么会进不了中断,我在线调试,发现寄存器值也没变化。

使用特权

评论回复
5
qq12344321|  楼主 | 2017-5-18 22:23 | 只看该作者
我用正点原子的开发板也试了一下(F767),我根据我的意思把你们提供的串口通信例程修改了下(F767),串口1接收中断中只负责接收,而主循环中则是串口循环发送,每个循环最多发送一个字节。发现如果主循环中不发送,则串口接收正常,接收速度很快。但是当我主循环里循环发送时,串口接收中断运行一段时间后就无法进入中断,但是程序没死,照样在发送。能麻烦帮看下吗,按理说串口中断也没关,其他中断也没打开。
下面是主循环程序:
int main(void)
{
    u8 len,i;       
          u32 times=0;
    Cache_Enable();                 //打开L1-Cache
    HAL_Init();                                        //初始化HAL库
    Stm32_Clock_Init(432,25,2,9);   //设置时钟,216Mhz
    delay_init(216);                //延时初始化
          uart_init(115200);                        //串口初始化
    LED_Init();                     //初始化LED
    while(1)
    {
                        times++;
                        if(times>0x2fffff)
                        {
                                times=0;
                                for(i=0;i<12;i++)
                                {
                                        /***************加上这一句,串口接收就有问题*****************/
                                        UART1_TX_BUF[++UART1_SendBuf_Count]='0'+i;    //如果有发送的时候会导致运行无法进入串口接收中断?????
                                  /***************加上这一句,串口接收就有问题*****************/
                                }
                                LED0_Toggle;
                        }               
                        if(UART1_SendBuf_Count!=UART1_SendBuf_Current)  //main循环中发送串口数据,此处每次最多发一个字节
                        {
                                HAL_UART_Transmit(&UART1_Handler,(uint8_t*)(&UART1_TX_BUF[++UART1_SendBuf_Current]),1,1000);        //发送接收到的数据
                                while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET);                //等待发送结束
                        }                         
          }
}
下面是串口中断的操作:

u8 UART1_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
u8 UART1_TX_BUF[USART_SEND_LEN];     //发送缓冲,最大USART_REC_LEN个字节.
u8 UART1_ReceiveBuf_Current=0;   //接收缓存当前处理的字节位置
u8 UART1_ReceiveBuf_Count=0;     //接收缓存中存储字节量
u8 UART1_SendBuf_Current=0;      //发送缓存当前处理的字节位置
u8 UART1_SendBuf_Count=0;        //发送缓存中存储字节量
u8 aRxBuffer_UART1[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
        if(huart->Instance==USART1)//如果是串口1
        {
                UART1_RX_BUF[++UART1_ReceiveBuf_Count] = aRxBuffer_UART1[0]; //串口接收中断中只负责接收
                if(UART1_ReceiveBuf_Count%50==0) LED1_Toggle;
        }
}
工程文件压缩了也有好几M,传不上来,哪位亲能帮我看看,告知可能是什么原因,多谢。

使用特权

评论回复
6
zyj9490| | 2017-5-18 22:30 | 只看该作者
肯定是发生错误中断了,或者其他串口中断,断点串口的回调函数就知道了。

使用特权

评论回复
7
qq12344321|  楼主 | 2017-5-18 22:44 | 只看该作者
zyj9490 发表于 2017-5-18 22:30
肯定是发生错误中断了,或者其他串口中断,断点串口的回调函数就知道了。 ...

谢谢您的解答,这个程序中只开了一个中断,运行一段时间后就无法进入串口接收中断,打断点无法进入,但是主程序还是在正常运行。

使用特权

评论回复
8
zyj9490| | 2017-5-18 23:06 | 只看该作者
qq12344321 发表于 2017-5-18 22:44
谢谢您的解答,这个程序中只开了一个中断,运行一段时间后就无法进入串口接收中断,打断点无法进入,但是 ...

有问题时,接收中断标志有没有上位,查看有没有其他中断产生,还有你调用的ST的库,它有一个串口的状态机,有没有破坏了,如有,强制复位到初始状态。你要细看发送与接收中断回调函数,及发送函数调用时的变量初始化。发送没有中断,你是用轮询方法吧?是用延时查询,还是主函数查询。

使用特权

评论回复
9
zyj9490| | 2017-5-18 23:08 | 只看该作者
qq12344321 发表于 2017-5-18 22:44
谢谢您的解答,这个程序中只开了一个中断,运行一段时间后就无法进入串口接收中断,打断点无法进入,但是 ...

连串口中断都进不去吗?也就是没有产生串口中断,(不是指接收中断)、

使用特权

评论回复
10
zyj9490| | 2017-5-18 23:23 | 只看该作者
还有一种情况,串口外设工作不正常,需重启。关闭再开启。再就要查原因。标志位要看下。ST的中断库是没有问题的。

使用特权

评论回复
11
qq12344321|  楼主 | 2017-5-18 23:37 | 只看该作者
zyj9490 发表于 2017-5-18 22:30
肯定是发生错误中断了,或者其他串口中断,断点串口的回调函数就知道了。 ...

我监视了串口寄存器中接收中断使能位,CR1的bit5------RXNEIE;
if((USART1->CR1&0x20)==0)   LED0_Toggle;
发现接收一段时间后RXNEIE自动清0了,好奇怪,但是手册上说该位只能被软件修改。

RXNEIE.png (21.78 KB )

RXNEIE.png

使用特权

评论回复
12
zyj9490| | 2017-5-18 23:44 | 只看该作者
qq12344321 发表于 2017-5-18 23:37
我监视了串口寄存器中接收中断使能位,CR1的bit5------RXNEIE;
if((USART1->CR1&0x20)==0)   LED0_Toggl ...

断点打在串口中断HANDLER开始的地方,单步调试能否进入接收回调函数里?

使用特权

评论回复
13
zyj9490| | 2017-5-18 23:47 | 只看该作者
qq12344321 发表于 2017-5-18 23:37
我监视了串口寄存器中接收中断使能位,CR1的bit5------RXNEIE;
if((USART1->CR1&0x20)==0)   LED0_Toggl ...

查看自已的代码是否有清零的地方,还有错误发生时,外设是否有重启的代码?如OV,总线出错的。

使用特权

评论回复
14
chenci2013| | 2017-5-19 00:13 | 只看该作者
你是数据发送速度是多快?

使用特权

评论回复
15
chenci2013| | 2017-5-19 00:14 | 只看该作者
一般数据发送速度快了芯片不能做出相应,可能有问题。

使用特权

评论回复
16
usysm| | 2017-5-19 08:44 | 只看该作者
硬件电路有没有问题,共地了吗

使用特权

评论回复
17
usysm| | 2017-5-19 08:46 | 只看该作者
也有可能是信号干扰造成的。

使用特权

评论回复
18
qq12344321|  楼主 | 2017-5-19 15:14 | 只看该作者
zyj9490 发表于 2017-5-18 23:44
断点打在串口中断HANDLER开始的地方,单步调试能否进入接收回调函数里?

谢谢你的解答,是串口接收中断标志位被清零了,但是我还没找到在那被清零了,现在只能在主循环里不停的检测标志位是不是清零,如果清零就再启动中断,但是感觉这个办法太被动了。主要还是要找出中断使能标志位清零的原因。

使用特权

评论回复
19
qq12344321|  楼主 | 2017-5-19 15:15 | 只看该作者
chenci2013 发表于 2017-5-19 00:14
一般数据发送速度快了芯片不能做出相应,可能有问题。

速度我试过慢的,一秒钟二十几个字节,但是也会中断标志也会自动清零,还没找到原因。

使用特权

评论回复
20
qq12344321|  楼主 | 2017-5-19 15:16 | 只看该作者
usysm 发表于 2017-5-19 08:46
也有可能是信号干扰造成的。

硬件问题应该不会,因为单片机没有死机或重启之类。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

20

帖子

1

粉丝