朋友您好!Nikolay再次与您在一起,在上一篇文章“
DevBoy-我如何创建开源设备项目并在Kickstarter上启动项目 ”中,重点更多地放在外观和硬件上,今天我们将讨论如何在“
内部 ”完成并分析软件部分。

谁在乎-我要猫。
如前所述,该项目基于ARM Cortex-M4内核上意法半导体的
STM32F415RG微控制器。 有多种不同的IDE用于为这些微控制器开发微控制器,但是,对于一个开源项目,您至少需要一个免费的IDE,最好是开源的。 此外,
STM32CubeMX仍必须支持IDE。 在我开始从事这个项目时,只有一个IDE可以满足所有这些要求
-STM32的System Workbench 。
目前,有Atollic TrueStudio,在意法半导体购买它们后免费提供。
下一个使用的程序是
STM32CubeMX 。 该程序是用于使用图形界面配置微控制器外围设备的实用程序。

结果是包含硬件抽象层(HAL)的代码。 许多程序员并不真正喜欢这种“
创造 ”,它并非没有错误,但是,它极大地简化了开发并提高了意法半导体不同微控制器之间程序的可移植性。
另外,在配置过程中,您可以指定使用某些第三
方开源软件,例如
FreeRTOS ,
FatFS和其他一些开源软件。
我们已经完成了所用软件的描述,现在让我们继续进行最有趣的部分
-DevCore 。 该名称来自“
核心开发 ”,让我们按顺序进行。
首先,它是
C ++ RTOS包装器 (
在这种情况下为FreeRTOS )。 需要Vrapper的原因有两个:
- 创建一个对象然后调用互斥锁要好得多,例如,以()为例,比创建一个句柄,调用create函数,然后将此句柄传递给所有互斥锁函数要好得多
- 如果有必要替换RTOS,则只需替换包装器就足够了,并且不是从代码中对RTOS函数的所有调用
谁在乎,把包装器代码带到这里,谁在乎-
我们看一下GitHub ,然后继续。
下一部分是
应用程序框架 。 这是所有任务的基类。 由于这些只是两个相对较小的文件,因此完整列出它们是有意义的:
继承的类可以覆盖4个虚函数:
- Setup()是开始任务之前调用的函数。 在执行主循环之前,可以确保所有任务的所有这些功能的代码完成。
- Loop() -主任务周期,任务本身在其中组织所需的内容。 不能与以下两个功能一起使用。
- TimerExpired() -以给定间隔定期调用的函数。 例如,方便实现轮询传感器。
- ProcessMessage() -处理来自其他任务的消息的功能。
前两个函数为任务实现“
Arduino风格 ”。
接下来的两个实现了“
事件 ”系统,简化了任务之间的交互。 通过这种方法,任务以函数的形式实现了外部接口,该函数通过内部邮箱将发送数据发送到任务。 通过这种方法,使用该界面的用户无需担心在什么上下文中执行动作。 没错,这仅适用于二传手或团队。 对于吸气剂,最好使用互斥锁和数据复制以防止长时间捕获互斥锁。
在我开发医疗设备软件时发现了这种方法。 微控制器只有一个
看门狗,如果有很多任务,则需要全部跟踪。 为此,有一个单独的任务服务看门狗,并从TimerExpired()函数发送的其他任务中接收消息。 如果在任务* n的计时期内没有消息,则任务死了,我们
熄灭灯并采取措施关闭所有影响患者的腺体。
所有任务都是单例,您不能直接创建它们,但是可以获取任务的链接。 为此,每个任务都实现静态的
GetInstance()方法:
还包括
音频输出 ,
输入模块和
屏幕维护的任务。声音输出的任务非常简单-它接收频率和持续时间的数组,并简单地定期更改计时器设置以生成特定频率的矩形脉冲。
维修
水模块的任务也很简单。 在有趣的点中,将自动检测模块:首先,使用ADC测量电压,如果电压在电源电压的25%到75%的范围内,则插入模拟操纵杆,否则插入按钮或编码器。 如果不是操纵杆,请检查I / O模块的第四行:如果处于高电平,则为按钮(将
所有按钮上拉至电源,并且在按下按钮时将其关闭在地面上 );如果该
按钮较低,则为编码器(将一个
小按钮“拉起”)接地并在按下时关闭电源 )。
屏幕维护任务是最有趣的任务。首先,屏幕为320x240x16bit,因此帧缓冲区需要153600字节。这不只是很多,而且是巨大的-在此微控制器中只有192k的RAM,而在微控制器中根本没有合适的大小可能会更容易。怎么样答案很简单:将屏幕分成几部分!但是您可以用不同的方式画些东西。。。我为这项任务申请的解决方案就像所有巧妙的方法一样。它在两个屏幕行上都有一个缓冲区。我们绘制所有应在一行中的内容,然后通过DMA模式下的SPI将其发送到屏幕,此时我们可以准备另一行。任务如何知道行中应该包含什么以及如何绘制?但是她不知道!但是她有一系列知道如何绘画的对象。每个此类对象均从VisObject类继承。每行的屏幕维护任务都会遍历对象列表,并调用DrawInBufW()函数,并向其传递指向缓冲区的指针,点数,要绘制的线和起始位置(直到使用了使用屏幕控制器模式更新“窗口”的想法)。实际上,每个对象都在已绘制的其他对象之上绘制自身,并且只需将它们放置在列表中的所需位置即可轻松按所需顺序排列对象。另外,这种方法使集成活动对象的处理变得容易-在从触摸屏控制器接收坐标之后,屏幕维护任务可以从头开始遍历工作表,以搜索落入按压坐标的活动对象。如果找到这样的对象,则为此对象调用虚拟函数Action()。, (
, , ), (
).
DevCore UI(
), I2C, I2C BME280 EEPROM 24256, — .
GitHub :
https://github.com/nickshl/devboyPS , Epic Fail'. , - "
“,从一个可能从有关Habré的文章中了解了这个项目的人那里得到的180美元(谢谢您,Andrey!),其余的则来自我的同事从一个相邻的立方体中得到的。不收钱不是问题。问题是对该项目缺乏兴趣...