gokit3 STM32源码分析 四部曲:
1)重点分析:程序的架构
https://mp.weixin.qq.com/s/aCWrcKGuR5LANIzdUnhCvQ
2)重点分析:串口接收数据机制
https://mp.weixin.qq.com/s/p9PKgwrTB9Gw4ksgkBy6AQ
3)重点分析:机智云协议结构体的定义
https://mp.weixin.qq.com/s/sK-kGEi1TbY_yhtOUt0MnQ
4)重点分析:机智云的按键处理机制
https://mp.weixin.qq.com/s/BkasPKHYk0zl8ZeIhYwhSQ
从收到机智云的第一批试用板子到现在也挺久了,一直没时间和大家分享,今天抽空写下我的感受,机智云gokit3.X是2016年6月25日发布的新产品,模型与Gokit2基本相同,采用底板+功能板+模组的方式,保留arduino接口,可扩展性不错,具备以下功能:
-
独创的双排模组接口,兼容MCU和SoC两种连接方式。
-
1路USB转TTL调试串口。可用于SoC方式开发的日志输出。
-
兼容Arduino接口。
-
GoKit经典传感器组合,温湿度、红外感应、双向电机、RGB灯。
-
3个key。
-
增加2路MIC,1路Speaker。
-
丰富的扩展接口,如OLED等。
有3种配置:
GoKit3(V) - 语音模组版 (GoKit3功能板+底板+宇音天下模组)
GoKit3(S) - SoC版(乐鑫模组(GoKit3转接板)+底板+GoKit3功能板)
GoKit3(H) - 高性能模组版
![](https://i-blog.csdnimg.cn/blog_migrate/f6fbb442d04b4beff00613a664eaea90.jpeg)
我拿到的是带宇音天下模组Lark7618的语音识别版本,机智云还送了esp8266的模块,赞一个!试用了下效果还不错,一些基本的开源项目论坛已经很多了,我就不多说了,我着重分享下STM32端整个程序的流程,机智云传输这么稳定得益于它整个框架的完整性,包括协议的制定以及解码部分的机制,是一个比较好的框架,下面重点分析:
![](http://club.gizwits.com/data/attachment/forum/201807/11/180400b5cqdqqw8ycy85i5.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180407ki7jfggssn7fn0sd.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180414lq4gncei7nugzurp.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180419t212vf22v9j2vix2.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180425zuuuvjh6vo11lb1u.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180546lho6569oyylw2hwx.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180433merldff3zy7hhcul.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180439myr1qnd15yql888d.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180607r0qahq46g60tj40h.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180607fwqufxw09kxkvj3q.jpg.thumb.jpg)
昨天分享了整个程序的架构,今天重点分析一下串口接收数据这块的机制
数据通讯采用的串口2,引脚为GPIO2和GPIO3,在gizwitsInit()中进行初始化
![](http://club.gizwits.com/data/attachment/forum/201807/11/180816cd2ujjhju227ejdj.jpg.thumb.jpg)
我们进去看看
![](http://club.gizwits.com/data/attachment/forum/201807/11/180822ehgp5t7tngttptgn.jpg.thumb.jpg)
上图主要初始化了一些硬件接口,并开启中断,这也是我们一般的写法,再往下看,看到一个pRb的结构体,这是个什么呢,我们追踪下,下面是pRb的定义
![](http://club.gizwits.com/data/attachment/forum/201807/11/180827ccozwmz8re80e80n.jpg.thumb.jpg)
我们先来解释下环形缓冲区的原理:
环形缓冲区通常有一个读指针和一个写指针。读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓冲区。通过移动读指针和写指针就可以实现缓冲区的数据读取和写入。在通常情况下,环形缓冲区的读用户仅仅会影响读指针,而写用户仅仅会影响写指针。
这里的rbCapacity代表缓冲区的容量,head指向了读区域,tail指向了写区域,rbBuff指向缓冲区的入口地址,示意图入下
![](http://club.gizwits.com/data/attachment/forum/201807/11/180832bud3r7yo8e7e3oii.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/180839ssd3b5fmb7gscfnb.jpg.thumb.jpg)
rbCreate(),顾名思义,此函数的作用用于创建缓冲区,将缓冲区的head/Tail都指向缓冲区的首地址,那么rbCapacity和rbBuff在哪里赋值的呢?我们返回去看gizwitsInit();
![](http://club.gizwits.com/data/attachment/forum/201807/11/180846efq4c5d531fx8gd2.jpg.thumb.jpg)
看到这里我们就明白了,继续往下看
这个函数为删除缓冲区函数,将结构体里面的数据全部清零
![](http://club.gizwits.com/data/attachment/forum/201807/11/180858lx4e4yce33xzy3e8.jpg.thumb.jpg)
这个函数为获取缓冲区的总容量,很好理解
![](http://club.gizwits.com/data/attachment/forum/201807/11/180903zshpphoggpk6sk6s.jpg.thumb.jpg)
接下来这个函数为缓冲区有多少数据可以读,有三种情况:
![](http://club.gizwits.com/data/attachment/forum/201807/11/181050kuvz7776uv7qz7r8.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/181055n7kj9b4b1w7v11ff.jpg.thumb.jpg)
接下来的函数为可写区域大小,直接用总容量rb_capacity(rb)减去可读区域大小就好了。
![](http://club.gizwits.com/data/attachment/forum/201807/11/181101d6djf6j5t2fcs7y7.jpg.thumb.jpg)
然后是读数据函数,从Head处开始读,读取count个数据,放到data地址开始的数据区域,如下图所示,也是分为三种情况
![](http://club.gizwits.com/data/attachment/forum/201807/11/181106k386j6sx6b2ibnkh.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/181112zl9cfoll633ndfnk.jpg.thumb.jpg)
3、Head>Tail,且count中的数据大于从Head到缓冲区尾部的个数,即大于下图中的看灰色,这种情况我们就先把Head到缓冲区尾部的数据复制到data处,再把绿色区域的复制过去,这里绿色部分并不会超过Tail,写操作中做了限制。
![](http://club.gizwits.com/data/attachment/forum/201807/11/181118oowwzzvkcvpl47ry.jpg.thumb.jpg)
最后是写数据函数,把从data指向的地址,写到Tail指向的地址,写count个数据,返回成功写入的个数,在这里判断了要写入的数据大小要小于可写区域大小,防止数据覆盖,如下图所示,也是分为三种情况
![](http://club.gizwits.com/data/attachment/forum/201807/11/181123kjngn5magjla56pz.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/181128iimdzli7upwismyd.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/181132twc485inw4whi989.jpg.thumb.jpg)
![](http://club.gizwits.com/data/attachment/forum/201807/11/181138hwl6q06uozqv02h5.jpg.thumb.jpg)
那么明白了串口环形buff的机制,数据是从哪里进入的呢,我们找到串口中断的入口,
![](http://club.gizwits.com/data/attachment/forum/201807/11/181144kdlqi88icivkzx4l.jpg.thumb.jpg)
可以看到中断程序非常简单,中断之后直接往缓冲区丢一个数据就行了,采用这种数据结构,大大提高了程序的稳定性,同时操作起数据来也很方便,需要的时候直接去读缓冲区数据就好了。今天就先分享这么多,下期分享机智云的协议与结构体的定义,谢谢大家!
![](http://club.gizwits.com/data/attachment/forum/201807/11/181149ml6hy9gngmtyr7a8.jpg.thumb.jpg)