OpenEdv-开源电子网

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

串口数据读取问题

[复制链接]

14

主题

55

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2016-12-3
在线时间
21 小时
发表于 2016-12-24 13:46:20 | 显示全部楼层 |阅读模式
10金钱
我用串口3来读取传感器数据,然后用串口1输出数据至电脑查看数据。
QQ截图20161224133741.png
程序如下:[mw_shl_code=c,true]void USART3_IRQHandler(void)
{
        u8 Rec[9];
        u8 i;
        u8 temp,con,par;

        if(USART_GetITStatus(USART3,USART_IT_RXNE))
        {
                USART_ClearITPendingBit(USART3, USART_IT_RXNE);

                for(i=0;i<9;i++)
                {
                        Rec=USART_ReceiveData(USART3);
                       
                       
                }
                if(i>8) i=0;
                USART_SendData(USART1,Rec[0]);
                //if(i==0)
                //{
                //        temp=~(Rec[1]+Rec[2]+Rec[3]+Rec[4]+Rec[5]+Rec[6]+Rec[7])+1;
                //        if(temp==Rec[8])
                //        {
                //        par=(Rec[3]*100+Rec[4])*5;//颗粒数
                //        con=(int)((Rec[3]*100+Rec[4])*1.014705);//浓度
                        //printf("颗粒数: %d  浓度: %d \n",par,con);
                                //printf("颗粒数%o\n",Rec[3]);
                        //USART_SendData(USART1,par);
                        //}
                //        printf("颗粒数: %d  浓度: %d \n",par,con);
                //}
        }
         
}[/mw_shl_code]

我只发送了Rec[0]的数据至串口。请问为什么串口显示的是FF 18 00 0B 02 00 01 00 DA 这样的全部数据呢?我应该怎样将它分开?

最佳答案

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

写代码首先自己心里得有思路,不要期望自己还没弄明白流程的情况下,就把程序调出来。 是这样的,串口接收寄存器,每次只能接收一个字节,而且有“时效性”,就是在下一个字节数据到来之前可以保持,供程序去读取,然后下一个字节到来会被重新刷掉,所以每一个字节数据到来后,应该第一时间先把它缓存起来,常用做法是开辟一定大小的数组(根据实际需求)。 串口接收有一般有两种情况,对方发送频率较快(一般 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

44

主题

225

帖子

0

精华

高级会员

Rank: 4

积分
660
金钱
660
注册时间
2013-11-22
在线时间
131 小时
发表于 2016-12-24 13:46:21 | 显示全部楼层
oywjex 发表于 2016-12-24 14:24
顶一下,让大神看到一下呢被困在这里了

写代码首先自己心里得有思路,不要期望自己还没弄明白流程的情况下,就把程序调出来。

       是这样的,串口接收寄存器,每次只能接收一个字节,而且有“时效性”,就是在下一个字节数据到来之前可以保持,供程序去读取,然后下一个字节到来会被重新刷掉,所以每一个字节数据到来后,应该第一时间先把它缓存起来,常用做法是开辟一定大小的数组(根据实际需求)。
       串口接收有一般有两种情况,对方发送频率较快(一般大于10HZ)或者发送频率较慢(一般小于10HZ),不过不是严格区分的,要根据实际项目需求是否允许丢包,就比如对方发100个包,你只要收到10个包就可以了,那么这种情况就属于局部采样;如果对方发送100个包,需要你绝对收到100个包,那么就是严格的全采样,这个频率如果快的话一般MCU可能办不到,这就需要专门的硬件去实时接收解析数据包,比如使用FPGA,嗯,扯远了。。
      你现在的情况可以直接在中断里面使用一个状态机,用来接收一个完整的包,接受完,校验通过后,触发响应的动作即可。
回复

使用道具 举报

14

主题

55

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2016-12-3
在线时间
21 小时
 楼主| 发表于 2016-12-24 13:50:07 | 显示全部楼层
求大神们解答一下这个问题么。。
回复

使用道具 举报

14

主题

55

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2016-12-3
在线时间
21 小时
 楼主| 发表于 2016-12-24 14:24:14 | 显示全部楼层
顶一下,让大神看到一下呢被困在这里了
回复

使用道具 举报

14

主题

55

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2016-12-3
在线时间
21 小时
 楼主| 发表于 2016-12-24 14:57:19 | 显示全部楼层
zhp 发表于 2016-12-24 14:48
写代码首先自己心里得有思路,不要期望自己还没弄明白流程的情况下,就把程序调出来。

       是这样 ...

您好,谢谢您,我有点没明白。我本意是每个Rec[]里面装如表通讯命令表中的一个位,每次recive就赋值给一个Rec[],但是实际情况是一次RECIVE赋值给Rec[]就是给了全部值了,没有办法分开。这是为什么呢
回复

使用道具 举报

44

主题

225

帖子

0

精华

高级会员

Rank: 4

积分
660
金钱
660
注册时间
2013-11-22
在线时间
131 小时
发表于 2016-12-24 15:38:48 | 显示全部楼层
oywjex 发表于 2016-12-24 14:57
您好,谢谢您,我有点没明白。我本意是每个Rec[]里面装如表通讯命令表中的一个位,每次recive就赋值给一 ...

你每次进来就把那个数据存了9次,肯定一样的
回复

使用道具 举报

44

主题

225

帖子

0

精华

高级会员

Rank: 4

积分
660
金钱
660
注册时间
2013-11-22
在线时间
131 小时
发表于 2016-12-24 15:44:51 | 显示全部楼层
oywjex 发表于 2016-12-24 14:57
您好,谢谢您,我有点没明白。我本意是每个Rec[]里面装如表通讯命令表中的一个位,每次recive就赋值给一 ...

USART3_IRQHandler 这个中断函数每进来一次,只接收一个字节,要多次进来,才能接收整个数据帧,那么问题来了,我怎么去区分它当前进来的数据,该存储在Rec数组的那个位置呢?用状态机!!! 用一个全局变量表示每次接收的状态,每接收一个字节,就先判断上次接收的状态,并跟你的数据帧结构的特点比对,一致则开始存储,然后解析!
回复

使用道具 举报

23

主题

323

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1010
金钱
1010
注册时间
2016-11-8
在线时间
233 小时
发表于 2016-12-24 15:55:11 | 显示全部楼层
学习学习
亦余心之所善,
虽九死其犹未悔。
回复

使用道具 举报

14

主题

55

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2016-12-3
在线时间
21 小时
 楼主| 发表于 2016-12-24 16:46:31 来自手机 | 显示全部楼层
zhp 发表于 2016-12-24 15:44
USART3_IRQHandler 这个中断函数每进来一次,只接收一个字节,要多次进来,才能接收整个数据帧,那么问题 ...

噢,我明白了,谢谢! 我还有个问题想请教您一下,就是既然每次中断只接收一个字节,那为什么它可以把9个字节的数据全部存入我的Rec[1] 里面并且输出出来呢?我的Rec 也定义的为一个字节呀。
回复

使用道具 举报

44

主题

225

帖子

0

精华

高级会员

Rank: 4

积分
660
金钱
660
注册时间
2013-11-22
在线时间
131 小时
发表于 2016-12-24 18:10:03 | 显示全部楼层
本帖最后由 zhp 于 2016-12-24 18:34 编辑
oywjex 发表于 2016-12-24 16:46
噢,我明白了,谢谢! 我还有个问题想请教您一下,就是既然每次中断只接收一个字节,那为什么它可以把9个 ...

你应该要存储成图一这样:
111.png

而不是图二这样
222.png


把 你的 Rec[9] 定义成全局变量

我直接给你把代码写出来吧。。。


[mw_shl_code=c,true]typedef enum{
   URSTATE_NULL= 0,
   URSTATE_START,
   URSTATE_DATA,
}e_uart_recv_state;


e_uart_recv_state  rstate = URSTATE_NULL;      //串口接收状态初始化  
u8 Rec[9];
void USART3_IRQHandler(void)
{
   
    u8 i;
    u8 Res;  //存储每次接收的数据
    u8 rcvlen;   //存储接收的数据长度
    u8 temp,con,par;

    if(USART_GetITStatus(USART3,USART_IT_RXNE))
    {
        USART_ClearITPendingBit(USART3, USART_IT_RXNE);
        Res = USART_ReceiveData(USART3);

switch(rstate)
        {
            case  URSTATE_NULL:
            {
                if(Res == 0xFF)
                {
                    rcvlen = 0;
                    rstate = URSTATE_START;
                    Rec[rcvlen++] = Res;
                }
                break;
            }

            case  URSTATE_START:
            {
                if(Res == 0x18)
                {
                    rstate = URSTATE_DATA;
                    Rec[rcvlen++] = Res;
                }
                else if(Res == 0xFF)
                {
                    rcvlen =0;
                    rstate = URSTATE_START;
                    Rec[rcvlen++] = Res;                    
                }
                else
                {
                    rstate = URSTATE_NULL;
                }
                break;
            }

            case  URSTATE_DATA:
            {
                if(rcvlen<=7)
                {
                    Rec[rcvlen++] = Res;
                }
                else
                {
                    Rec[8] = Res;
                    if(Rec[8] == CRCchecsum())   //check ok
                    {
                        for(i=0; i<8; i++)
                        {
                            USART_ReceiveData(USART1, Rec);
                        }
                    }
                    rstate = URSTATE_NULL;
                }
                break;
            }

            default:
            {
                break;
            }            
        }
}[/mw_shl_code]
至于  CRCchecsum() 这个函数你要自己根据需求写



回复

使用道具 举报

14

主题

55

帖子

0

精华

新手入门

积分
3
金钱
3
注册时间
2016-12-3
在线时间
21 小时
 楼主| 发表于 2016-12-24 20:48:42 | 显示全部楼层
zhp 发表于 2016-12-24 18:10
你应该要存储成图一这样:

谢谢您!真的特别详细,理解到了。只是还有个这个之外的问题,就是您讲的我把每一个字节赋给了每一个数组。但是例如您画的第一个字节0XFF给了Rec[0] 第二字节0X18又给了Rec[0],那为什么没有将最开始的0xFF覆盖呢,最后输出Rec[0]是完整的 8个字节的数据呢?
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-5-26 11:30

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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