OpenEdv-开源电子网

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

请大家看看,为什么串口中断只能收到第一个字节?

[复制链接]

1

主题

8

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-1-13
在线时间
4 小时
发表于 2016-1-13 17:33:59 | 显示全部楼层 |阅读模式
1金钱
串口只能接收第一个字节,求教!


void USART1_IRQHandler(void)                    //串口1中断服务程序
{
    u8 Res;
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是checksum[0] checksum[1]结尾)
    {
        USART_ClearFlag(USART1,USART_FLAG_RXNE);  //清除中断标志     
        Res =USART_ReceiveData(USART1);//(USART1->DR);    //读取接收到的数据

        if((USART_RX_STA&0x8000)==0)//接收未完成
        {
            if(USART_RX_STA&0x4000)//接收到了checksum[1]
            {
                if(Res != USART_RX_BUF[USART_REC_LEN-1])USART_RX_STA=0;//接收错误,重新开始
                else USART_RX_STA|=0x8000;    //接收完成
            }
            else //还没收到chucksum[1]
            {     
                if(Res == USART_RX_BUF[USART_REC_LEN-2])USART_RX_STA|=0x4000;
                else
                {
                    USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
                    USART_RX_STA++;         
                     
                    if (USART_RX_STA >=2)
                    {
                        USART_RX_BUF[USART_REC_LEN-2] += Res;
                        USART_RX_BUF[USART_REC_LEN-1] += USART_RX_BUF[USART_REC_LEN-2];
                    }
                     
                    if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收      
                }         
            }
        }

最佳答案

查看完整内容[请看2#楼]

我建议哦,你在串口中断里面什么都先不做,就是单纯的接收一个字节发送会给电脑,看看对不对; 对了之后再调试你的协议,这是最好的办法,不用纠结是哪里的问题了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2016-1-13 17:34:00 | 显示全部楼层
我建议哦,你在串口中断里面什么都先不做,就是单纯的接收一个字节发送会给电脑,看看对不对;
对了之后再调试你的协议,这是最好的办法,不用纠结是哪里的问题了
回复

使用道具 举报

354

主题

1475

帖子

12

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
8096
金钱
8096
注册时间
2015-10-15
在线时间
2919 小时
发表于 2016-1-13 21:23:25 | 显示全部楼层
这个你debug调试一下很容易知道的。。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-1-13
在线时间
4 小时
 楼主| 发表于 2016-1-14 09:02:04 | 显示全部楼层
openedvadmin 发表于 2016-1-13 21:23
这个你debug调试一下很容易知道的。。。。。

debug进去,每次只收一个字节
回复

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2016-1-14 09:25:52 | 显示全部楼层
你先把那个中断里面的函数化简之后再试试看,到底是串口还是其他的问题
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-1-13
在线时间
4 小时
 楼主| 发表于 2016-1-14 09:44:46 | 显示全部楼层
1201yuge 发表于 2016-1-14 09:25
你先把那个中断里面的函数化简之后再试试看,到底是串口还是其他的问题

while(1)
        {
                if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断
                {
                        USART_ClearFlag(USART1,USART_FLAG_RXNE);  //清除中断标志       
                        Res =USART_ReceiveData(USART1);//(USART1->DR);        //读取接收到的数据

                        if ((Res == 0xB5) && (USART_RX_STA == 0))
                        {
                                USART_RX_BUF[USART_RX_STA] = Res;
                                USART_RX_STA++;
                        }
                        else if ((Res == 0x62) && (USART_RX_STA == 1))
                        {
                                USART_RX_BUF[USART_RX_STA] = Res;
                                USART_RX_STA++;
                        }
                        else
                        {
                                if ((USART_RX_STA >= 2) && (USART_RX_STA < 36))
                                {
                                        USART_RX_BUF[USART_RX_STA] = Res;
                                        USART_RX_STA++;                       
                                }
                                else
                                {
                                        USART_RX_STA=0;       
                                }
                        }
                }
        }


我这么写就可以接收到36个字节,但是用了while(1),跳不出中断了
回复

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2016-1-14 10:15:00 | 显示全部楼层
你的那个清中断的函数是不是有点问题?接收中断可以不清,你把那个屏蔽掉试试看
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-1-13
在线时间
4 小时
 楼主| 发表于 2016-1-14 10:18:04 | 显示全部楼层
1201yuge 发表于 2016-1-14 10:15
你的那个清中断的函数是不是有点问题?接收中断可以不清,你把那个屏蔽掉试试看

效果一样,停在中断里出不来
回复

使用道具 举报

20

主题

468

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1684
金钱
1684
注册时间
2014-2-25
在线时间
230 小时
发表于 2016-1-14 10:22:24 | 显示全部楼层
你仿真看看是什么中断标志位没有被清掉;还有你打开了串口的什么中断
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-1-13
在线时间
4 小时
 楼主| 发表于 2016-1-14 10:34:56 | 显示全部楼层
1201yuge 发表于 2016-1-14 10:22
你仿真看看是什么中断标志位没有被清掉;还有你打开了串口的什么中断

原因我明白,就是while(1),始终处在循环里,所以跳不出来.但是删了以后,就只能接收一个字节.
回复

使用道具 举报

19

主题

702

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3339
金钱
3339
注册时间
2013-7-30
在线时间
708 小时
发表于 2016-1-14 10:45:42 | 显示全部楼层
楼主的程序逻辑很乱
思想很重要,无论做人还是编程!
我的技术公众号【微联智控工作室】
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-1-13
在线时间
4 小时
 楼主| 发表于 2016-1-14 10:55:02 | 显示全部楼层
本帖最后由 shmm91 于 2016-1-14 11:03 编辑
小温 发表于 2016-1-14 10:45
楼主的程序逻辑很乱

谢谢提醒,您帮我看一下程序,我简化了一下,一次接收36个字节,第一个是0xB5.
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
        {
                USART_ClearFlag(USART1,USART_FLAG_RXNE);   //清除中断标志        
                Res =USART_ReceiveData(USART1);            //读取接收到的数据
               
                USART_RX_BUF[USART_RX_STA] = Res;         
                USART_RX_STA++;
               
                if ((USART_RX_BUF[0] == 0xB5) && (USART_RX_STA > 35))   // 第一个字节是0xB5,总共36个字节
                {
                        USART_RX_STA = 0;
                }
               
        }
回复

使用道具 举报

19

主题

702

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3339
金钱
3339
注册时间
2013-7-30
在线时间
708 小时
发表于 2016-1-14 11:07:57 | 显示全部楼层
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)     //接收非空中断标志置位
        {
                USART_ClearFlag(USART1,USART_FLAG_RXNE);   //清除中断标志        
                Res =USART_ReceiveData(USART1);            //读取接收到的数据
               
                USART_RX_BUF[USART_RX_STA] = Res;        //假如USART_RX_STA初值为0,则从 USART_RX_BUF[0] 开始保存接收到的数据
                USART_RX_STA++;     // USART_RX_STA 加1
               
                if ((USART_RX_BUF[0] = 0xB5) && (USART_RX_STA > 35))   // 第一个字节是0xB5,而且USART_RX_STA 超过35的时候
                {
                        USART_RX_STA = 0;    //把USART_RX_STA 清零
                }
               
        }


问:你在哪里设置接收完成标志位?
问:接收完成的条件是什么?
原子的代码是以 回车 换行 符来判断接收完成的
还可以用超时的方式来判断接收完成
思想很重要,无论做人还是编程!
我的技术公众号【微联智控工作室】
回复

使用道具 举报

1

主题

8

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2016-1-13
在线时间
4 小时
 楼主| 发表于 2016-1-14 11:24:59 | 显示全部楼层
小温 发表于 2016-1-14 11:07
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)     //接收非空中断标志置位
        {
        ...

明白原子哥的结束标志,每次发送的数据为36字节,而且开始为0xB5,所以满足这两个条件就结束
回复

使用道具 举报

6

主题

115

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1027
金钱
1027
注册时间
2015-6-1
在线时间
126 小时
发表于 2016-1-14 13:31:54 | 显示全部楼层
首先,对串口数据寄存器进行一次读操作就可以自动消除中断标志,没必要再加一条。其次,这样写就是要求发送的第一个数据必须是0xB5,然后接收36个字节作为一次接收数据完成,这样写没问题。但是,你在中断里就清零了,那么在程序外部怎么对数据进行读取,直接清零就无法处理这次接收到的数据了。一般的做法都不会在中断里清零的,而是写一个接收完成标志。可以参考原子的做法,将最高位置1。
建议改成这样:if ((USART_RX_BUF[0] = 0xB5) && (USART_RX_STA > 35))   // 第一个字节是0xB5,而且USART_RX_STA 超过35的时候
                {
                        USART_RX_STA |= 0x8000;    //接收完成标志。
                }

然后再程序外部判断if(USART_RX_STA&0x8000),对这次数据处理完后再将指针清零。USART_RX_STA=0;
回复

使用道具 举报

50

主题

193

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2016-4-11
在线时间
141 小时
发表于 2016-12-23 10:54:18 | 显示全部楼层
小温 发表于 2016-1-14 11:07
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)     //接收非空中断标志置位
        {
        ...

您好,我按您这个程序试了下,为什么我每次进入中断还是只能接收一个字节
我现在想学习下,如何在一次接收多个字节,
谢谢
回复

使用道具 举报

50

主题

193

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2016-4-11
在线时间
141 小时
发表于 2016-12-23 10:55:16 | 显示全部楼层
小温 发表于 2016-1-14 11:07
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)     //接收非空中断标志置位
        {
        ...

我是用串口调试助手直接发送123456,每次都只能接收12就跳出中断了。
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

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

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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