OpenEdv-开源电子网

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

原子哥串口中断发多个数据,只进入了一次中断

[复制链接]

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
发表于 2023-9-11 16:22:46 | 显示全部楼层 |阅读模式
void USART1_IRQHandler(void)                        //串口1中断服务程序
        {
        u8 Res;
        u8 CNT1=0;
#if SYSTEM_SUPPORT_OS                 //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
        OSIntEnter();   
#endif
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
                {
//                USART_ClearITPendingBit(USART1,USART_IT_RXNE);        
                Res =USART_ReceiveData(USART1);        //读取接收到的数据
               
                if((USART_RX_STA&0x8000)==0)//接收未完成
                        {
                        if(USART_RX_STA&0x4000)//接收到了0x0d
                                {
                                if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
                                else
                                        {
                                                USART_RX_STA|=0x8000;        //接收完成了
                                        }
                                }
                        else //还没收到0X0D
                                {        
                                if(Res==0x0d)USART_RX_STA|=0x4000;
                                else
                                        {
                                        USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
                                        USART_RX_STA++;
                                        CNT1++;
                                        if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收         
                                        }                 
                                }
                        }
     }
//   else if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
//                 {
//                         USART1->SR;//先读SR
//                         USART1->DR;//再读DR
//           }               
                len1=CNT1;
                 state++;
//                 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
//                 USART_ClearFlag(USART1,USART_FLAG_RXNE);
#if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
        OSIntExit();                                                                                          
#endif
}

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

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-11 16:24:46 | 显示全部楼层
我发送010203,三个数据,但是用JLINK调试只进入了一次中断,接收到了01,其余的没有接收到,这是啥原因阿
回复 支持 反对

使用道具 举报

54

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1040
金钱
1040
注册时间
2022-4-20
在线时间
373 小时
发表于 2023-9-11 17:45:16 | 显示全部楼层
Vircyom 发表于 2023-9-11 16:24
我发送010203,三个数据,但是用JLINK调试只进入了一次中断,接收到了01,其余的没有接收到,这是啥原因阿

我猜测是因为你打的断点导致的,当第一个01来的时候触发中断,然后程序被你的断点拦截,后续数据即使来了,也不会被收到,建议直接整一个全局变量,在中断里自加,发送一次数据之后,去主程序里面打个断点,再看这个全局变量是多少,就知道进了几次中断
又菜又爱指点
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-11 19:22:22 | 显示全部楼层
驭剑的秘密 发表于 2023-9-11 17:45
我猜测是因为你打的断点导致的,当第一个01来的时候触发中断,然后程序被你的断点拦截,后续数据即使来了 ...

不是的,我在板子里就是这个情况,然后才用JLINK调试的
回复 支持 反对

使用道具 举报

11

主题

2130

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4724
金钱
4724
注册时间
2015-1-10
在线时间
590 小时
发表于 2023-9-12 10:16:02 | 显示全部楼层
你为什么要看进几次中断?你看看接收缓存里面有几个数不就行了
回复 支持 反对

使用道具 举报

54

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1040
金钱
1040
注册时间
2022-4-20
在线时间
373 小时
发表于 2023-9-12 11:56:09 | 显示全部楼层
Vircyom 发表于 2023-9-11 19:22
不是的,我在板子里就是这个情况,然后才用JLINK调试的

那就是你代码里没有清标志位
又菜又爱指点
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-12 12:27:26 | 显示全部楼层
阿侑kevin 发表于 2023-9-12 10:16
你为什么要看进几次中断?你看看接收缓存里面有几个数不就行了

是一样的,接收缓存只有ABC中的A,所以我才说只进入了一次中断
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-12 12:28:12 | 显示全部楼层
驭剑的秘密 发表于 2023-9-12 11:56
那就是你代码里没有清标志位

我看了中文参考手册,他说读取DR的时候就会自动清,我这里用receivedata读取了,应该是清零了的
回复 支持 反对

使用道具 举报

54

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1040
金钱
1040
注册时间
2022-4-20
在线时间
373 小时
发表于 2023-9-12 13:32:14 | 显示全部楼层
发你的uart_init看看
又菜又爱指点
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-12 14:54:45 | 显示全部楼层
  1. GPIO_InitTypeDef GPIO_InitStructure;
  2.         USART_InitTypeDef USART_InitStructure;
  3.         NVIC_InitTypeDef NVIC_InitStructure;
  4.          
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟
  6.   
  7.         //USART1_TX   GPIOA.9
  8.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  9.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  11.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
  12.    
  13.   //USART1_RX          GPIOA.10初始化
  14.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  15.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  16.   GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  17.   //Usart1 NVIC 配置
  18.   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  19.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
  20.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;                //子优先级3
  21.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
  22.         NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
  23.   
  24.    //USART 初始化设置

  25.         USART_InitStructure.USART_BaudRate = bound;//串口波特率
  26.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
  27.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  28.         USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
  29.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  30.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式

  31.   USART_Init(USART1, &USART_InitStructure); //初始化串口1
  32.   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  33.   USART_Cmd(USART1, ENABLE);                    //使能串口1
  34. //        USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
复制代码


回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-12 14:55:23 | 显示全部楼层
  1. GPIO_InitTypeDef GPIO_InitStructure;
  2.   USART_InitTypeDef USART_InitStructure;
  3.         NVIC_InitTypeDef NVIC_InitStructure;

  4.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);//使能GPIOA,D时钟
  5.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟
  6.        
  7.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;                                 //PD7端口配置
  8.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
  9.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.         GPIO_Init(GPIOD, &GPIO_InitStructure);

  11.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;        //PA2
  12.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽
  13.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  14.    
  15.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
  16.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
  17.   GPIO_Init(GPIOA, &GPIO_InitStructure);  

  18.         RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//复位串口2
  19.         RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位

  20.        
  21. #ifdef EN_USART2_RX                          //如果使能了接收
  22.         USART_InitStructure.USART_BaudRate = bound;//波特率设置
  23.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据长度
  24.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
  25.         USART_InitStructure.USART_Parity = USART_Parity_No;///奇偶校验位
  26.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
  27.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式

  28.   USART_Init(USART2, &USART_InitStructure); ; //初始化串口
  29.   
  30.         NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //使能串口2中断
  31.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级2级
  32.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级2级
  33.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
  34.         NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

  35.   USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断
  36.    
  37.   USART_Cmd(USART2, ENABLE);                    //使能串口

  38. #endif

  39.   RS485_TX_EN=0;                        //默认为接收模式
复制代码


回复 支持 反对

使用道具 举报

54

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1040
金钱
1040
注册时间
2022-4-20
在线时间
373 小时
发表于 2023-9-12 15:59:29 | 显示全部楼层

看了,也复制你的代码试了,我这边一切正常。

想复刻你的现象,目前能想到的就是USART_REC_LEN

微信截图_20230912155610.png

除此之外应该就是硬件导致的了

又菜又爱指点
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-12 16:02:12 | 显示全部楼层
驭剑的秘密 发表于 2023-9-12 15:59
看了,也复制你的代码试了,我这边一切正常。

想复刻你的现象,目前能想到的就是USART_REC_LEN

朋友,这个和我的是一个现象阿,你发的123123,但是你看你的发送数据只有1
回复 支持 反对

使用道具 举报

54

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1040
金钱
1040
注册时间
2022-4-20
在线时间
373 小时
发表于 2023-9-12 16:21:15 | 显示全部楼层
Vircyom 发表于 2023-9-12 16:02
朋友,这个和我的是一个现象阿,你发的123123,但是你看你的发送数据只有1

这是我把USART_REC_LEN改成3来复刻你的现象的,上一条回复里面有说明
又菜又爱指点
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-12 16:26:47 | 显示全部楼层
驭剑的秘密 发表于 2023-9-12 16:21
这是我把USART_REC_LEN改成3来复刻你的现象的,上一条回复里面有说明

这里数组长度改成3的话,发送123123的话也应该是能储存123阿,不会出现只发送1的情况
回复 支持 反对

使用道具 举报

54

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1040
金钱
1040
注册时间
2022-4-20
在线时间
373 小时
发表于 2023-9-12 16:40:29 | 显示全部楼层
Vircyom 发表于 2023-9-12 16:26
这里数组长度改成3的话,发送123123的话也应该是能储存123阿,不会出现只发送1的情况

又看了一下,是有点巧合在里面的
由于打印的代码是这样的
  1. len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
  2.             printf("\r\n您发送的消息为:\r\n\r\n");
  3.             for(t=0;t<len;t++)
  4.             {
  5.                 USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据
  6.                 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
  7.             }
复制代码
打印的长度受到len控制,len受USART_RX_STA控制,USART_RX_STA的长度代码是这样的
  1.                     USART_RX_STA++;
  2.                     if(USART_RX_STA > (USART_REC_LEN-1)) USART_RX_STA = 0;
复制代码

所以当串口软件发送的长度与USART_REC_LEN的值取余的区间在(0,USART_REC_LEN)的时候才会有消息打印,刚刚只是我发送数据的长度恰巧余1,才显示的1(随手一按的数据),我以为是复刻了现象,结果是巧合

又菜又爱指点
回复 支持 反对

使用道具 举报

54

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1040
金钱
1040
注册时间
2022-4-20
在线时间
373 小时
发表于 2023-9-12 16:47:57 | 显示全部楼层
驭剑的秘密 发表于 2023-9-12 16:40
又看了一下,是有点巧合在里面的
由于打印的代码是这样的
打印的长度受到len控制,len受USART_RX_STA控 ...

补一下图,确实是巧合,没有复刻

微信截图_20230912164607.png
微信截图_20230912164524.png

又菜又爱指点
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-12 17:09:32 | 显示全部楼层
本帖最后由 Vircyom 于 2023-9-12 17:11 编辑
驭剑的秘密 发表于 2023-9-12 16:47
补一下图,确实是巧合,没有复刻

对阿,但我这个中断函数是以原子哥的代码改的,我这里给一下我的中断处理函数和主函数吧。

串口1中断处理函数
  1. void USART1_IRQHandler(void)                        //串口1中断服务程序
  2.         {
  3.         u8 Res;
  4.         u8 CNT1=0;
  5. #if SYSTEM_SUPPORT_OS                 //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
  6.         OSIntEnter();   
  7. #endif
  8.                
  9.         //9.12        
  10. //                if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)== SET)//程序中断过多,主机的发送速度又快,很容易会造成溢出错误
  11. //                {
  12. //                        USART_ClearFlag(USART1, USART_FLAG_ORE); //清除溢出中断
  13. //                }
  14.                
  15.         if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
  16.                 {        
  17.                 Res =USART_ReceiveData(USART1);        //读取接收到的数据
  18.                         
  19.                 if((USART_RX_STA&0x8000)==0)//接收未完成
  20.                         {
  21.                         if(USART_RX_STA&0x4000)//接收到了0x0d
  22.                                 {
  23.                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
  24.                                 else USART_RX_STA|=0x8000;        //接收完成了
  25. //                                        {
  26. //                                                USART_RX_STA|=0x8000;        //接收完成了
  27. //                                        }
  28.                                 }
  29.                         else //还没收到0X0D
  30.                                 {        
  31.                                 if(Res==0x0d)USART_RX_STA|=0x4000;
  32.                                 else
  33.                                         {
  34.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
  35.                                         USART_RX_STA++;
  36.                                         CNT1++;
  37.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收         
  38.                                         }                 
  39.                                 }
  40.                         }
  41.      }
  42.                 USART_ClearITPendingBit(USART1,USART_IT_RXNE);
  43.                 len1=CNT1;
  44.                  state++;
  45. #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
  46.         OSIntExit();                                                                                          
  47. #endif
  48. }
复制代码

回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-12 17:12:14 | 显示全部楼层
驭剑的秘密 发表于 2023-9-12 16:47
补一下图,确实是巧合,没有复刻

主函数

  1. if(state&0XFFFF)//
  2.                 {
  3.                         RS485_Send_Data(USART_RX_BUF,len1);//发送串口1->串口2
  4.       len1=0;                       
  5.       state=0;
  6.       USART_RX_STA=0;                       
  7.                 }
复制代码
回复 支持 反对

使用道具 举报

0

主题

15

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
382
金钱
382
注册时间
2020-9-24
在线时间
61 小时
发表于 2023-9-12 17:50:37 | 显示全部楼层

主函数里的state与中断里的state是一个东西吗
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-12 18:16:50 | 显示全部楼层
笑而有语 发表于 2023-9-12 17:50
主函数里的state与中断里的state是一个东西吗

是一个变量
回复 支持 反对

使用道具 举报

54

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1040
金钱
1040
注册时间
2022-4-20
在线时间
373 小时
发表于 2023-9-13 09:27:24 | 显示全部楼层

你是怎么看缓冲数组的,进调试看的USART_RX_BUF数组吗?还是看的RS485_Send_Data发送的数据?如果没进调试看的话肯定没对,因为你这个len1最大值只有1
又菜又爱指点
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2023-7-26
在线时间
20 小时
 楼主| 发表于 2023-9-18 09:11:26 | 显示全部楼层
驭剑的秘密 发表于 2023-9-13 09:27
你是怎么看缓冲数组的,进调试看的USART_RX_BUF数组吗?还是看的RS485_Send_Data发送的数据?如果没进调试 ...

进了调试的,这个已经解决了,是因为在中断的if里面加了一段变量赋值的语句导致中断只进入了一次,但是有个点想不明白,如果进入调试来看中断的话,一步一步调试下来,中断应该早就完了吧,所以造成只有一次的假象?
回复 支持 反对

使用道具 举报

54

主题

349

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1040
金钱
1040
注册时间
2022-4-20
在线时间
373 小时
发表于 2023-9-18 11:28:32 | 显示全部楼层
Vircyom 发表于 2023-9-18 09:11
进了调试的,这个已经解决了,是因为在中断的if里面加了一段变量赋值的语句导致中断只进入了一次,但是有 ...

RXNE是这样的,收到的每个字节都会有一个中断,要是一步一步调,发送端也得同步调,不然发送端全速运行,数据早就跑完了
又菜又爱指点
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-24 15:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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