OpenEdv-开源电子网

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

正点原子MiniFly V1.2学习笔记二

[复制链接]

10

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
215
金钱
215
注册时间
2018-5-25
在线时间
34 小时
发表于 2019-6-28 16:34:22 | 显示全部楼层 |阅读模式
本帖最后由 Dluffy 于 2019-6-28 16:33 编辑

      第1个任务radiolinkTask 处理串口接收到的数据包,把命令提取出来。
一、数据包格式
       一条指令,包含 功能ID 和数据。功能ID–就是接收方用来区别需要做什么事,数据 --指令中需要的数据。另外,为了区别指令的开始位置,要在开始加上 帧头,为了保证接收正确,还要在最后加上一个校验,如果接收方发现校验错了,就把该指令丢弃。
      在atkp.h中:
1、宏定义,定义帧头,功能ID 等
2、结构体 数据定义
3、atkp.c中的函数声名,方便其它模块通过包含atkp.h头文件,就可以调用atkp.c中的函数

指令格式: 帧头(AA+AF)+功能ID+数据长度+数据+校验

      

二、任务void radiolinkTask(void *param)
     xTaskCreate(radiolinkTask, "RADIOLINK", 150, NULL, 5, NULL);
任务优先级被定义为 5



    //radiolink接收ATKPPacket任务
    void radiolinkTask(void *param)
    {
            rxState = waitForStartByte1;
        
        u8 c;
        u8 dataIndex = 0;
        u8 cksum = 0;


        while(1)
        {
                if (uartslkGetDataWithTimout(&c))
                {
                        switch(rxState)
                        {
                                case waitForStartByte1:  #帧头第1字节AA
                                        rxState = (c == DOWN_BYTE1) ? waitForStartByte2 : waitForStartByte1;
                                        cksum = c;
                                        break;
                                case waitForStartByte2:  #帧头第2字节AF
                                        rxState = (c == DOWN_BYTE2) ? waitForMsgID : waitForStartByte1;
                                        cksum += c;
                                        break;
                                case waitForMsgID:
                                        rxPacket.msgID = c;
                                        rxState = waitForDataLength;
                                        cksum += c;
                                        break;
                                case waitForDataLength:
                                        if (c <= ATKP_MAX_DATA_SIZE)
                                        {
                                                rxPacket.dataLen = c;
                                                dataIndex = 0;
                                                rxState = (c > 0) ? waitForData : waitForChksum1;        /*c=0,数据长度为0,校验1*/
                                                cksum += c;
                                        } else
                                        {
                                                rxState = waitForStartByte1;
                                        }
                                        break;
                                case waitForData:
                                        rxPacket.data[dataIndex] = c;
                                        dataIndex++;
                                        cksum += c;
                                        if (dataIndex == rxPacket.dataLen)
                                        {
                                                rxState = waitForChksum1;
                                        }
                                        break;
                                case waitForChksum1:
                                        if (cksum == c)        /*所有校验正确*/
                                        {
                                                atkpPacketDispatch(&rxPacket);
                                        }
                                        else        /*校验错误*/
                                        {
                                                rxState = waitForStartByte1;        
                                                IF_DEBUG_ASSERT(1);
                                        }
                                        rxState = waitForStartByte1;
                                        break;
                                default:
                                        ASSERT(0);
                                        break;
                        }
                }
                else        /*超时处理*/
                {
                        rxState = waitForStartByte1;
                }
        }
}

      任务的流程如下:
1、调用uartslkGetDataWithTimout(&c)获取1个字节
2、识别出帧头AA+AF
3、把功能ID,数据长度+数据 存到变量rxPacket中
4、这里采用的校验码是把前面所有的数据相加,只取1个字节。如果校验码正确,把接收到的存在rxPacket中的指令通过函数atkpPacketDispatch(&rxPacket);发送出去,然后回到开头等待帧头AA+AF
5、如果检验错误,也重新等待帧头AA+AF
6、如果1超时都没有获得1个字节,继续等待帧头AA+AF


       整个过程的逻辑还是比较简单,这就是系统的好处


三、函数uartslkGetDataWithTimout(&c)
上面的任务中,需要获取1个字节,这不是直接从串口获取,而是从队列uartslkDataDelivery获得。



四、函数atkpPacketDispatch(atkp_t *rxPacket)
解析出来的指令,调用atkpPacketDispatch(&rxPacket)把它发送到队列rxQueue中,发送的是指令的指针。然后看一下txQueue队列,有没有数据要回复给发送方,如果有,则取一条数据回复过去。


五、整个任务的框架

六、队列的定义
1、uartslkDataDelivery队列


2、rxQueue队列


3、txQueue队列


七、串口是怎么把一个字节接收到队列uartslkDataDelivery的
1、串口2初始化


2、串口2中断接收数据 到队列中

八、从txQueue取指令发送到串口



九、队列在什么地方定义
      从上面分析我们看到,串口中断接收到的数据放进队列uartslkDataDelivery中,在任务中,再从该队列读取数据。那么队列就相当于全局变量了,它需要定义在什么地方呢?
      1、uartslkDataDelivery队列----定义在uart_syslink.c开头----使用到该队列的函数:初始化函数,串口中断函数,从队列读数据函数,都定义在这个.c文件里---------任务函数通过包含#include "radiolink.h"头文件来调用这个.c文件的函数
  
   




      2、同理,rxQueue队列的,定义,初始化,向队列发送消息,从队列获取消息的函数,都定义在atkp.c文件里

      3、txQueue队列好像有点特殊,它在两个地方定义了usblink.c 和radiolink.c,这两个c文件里的队列只是同名而已,其实它是两个不同的队列,因为在定义的时候加了static 只限本文件使用,所以txQueue相当于每个文件的局部变量。



十、疑问
      这里有一个疑问,把接收到的指令解包到变量rxPacket中,然后把变量rxPacket的指针发送到队列rxQueue中,如果指令没有处理,接收第二指令的时候不是会把第一个指令覆盖了?因为都是接收到同一个变量里的啊。


      原来,FreeRTOS的队列是值传递,发送函数的第二个参数就是指向 待发数据 的指针,在发送函数里会从该指令复制N个字节到队列里,N就是在队列初始化中定义的项目大小






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

使用道具 举报

4

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
173
金钱
173
注册时间
2019-4-23
在线时间
24 小时
发表于 2019-6-28 18:19:35 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2019-8-20
在线时间
3 小时
发表于 2019-8-25 16:07:00 | 显示全部楼层
你好,在stabilizer.c中的setpoint变量是怎么赋值的?尤其是在commander.c中void commanderGetSetpoint(setpoint_t *setpoint, state_t *state)中的setpoint变量赋值理不清逻辑?能否讲解一下?
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 16:11

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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