硬件区别
http://www.stmcu.org/module/forum/thread-582410-1-1.html
软件区别
http://forum.eepw.com.cn/thread/230356/1/
开发模型
抽象化
如果拿来一个开发板学习,目前一般采用标准库方式来入门。那么我们在用标准库来学习时到底在学什么?本质上我们是在学驱动开发。
一般我们在学习某个外设的时候会建立这样的文件,bsp_xxx.h和bsp_xxx.c,xxx指某个外设,然后在main文件里调用上述头文件,main函数里写些测试代码。这里bsp_xxx基于库开发的针对特定板载硬件的驱动程序,而main函数里面才是最终我们要做的应用开发。
由于mcu的功能众多,不可能为每个功能单独拉出管脚,对于实现一个功能,比如led,你用哪个gpio都可以,如果需要用UART,i2c等,因为存在多个这样的外设,你用哪个都可以,这就不开避免的产生硬件结构的差异化,进而带来驱动的一致问题。一般采取的方式是,在头文件里定义和具体管脚、接口相关的宏,在c文件里尽量避免带来和硬件相关的移植问题。这样,针对某个特定mcu开发的驱动就可以很容易的移植到另一个板子。
还有一种外设相关的驱动,比如用i2c,这种外设是通用外设,你是用它来操作EEPROM还是控制传感器、传输数据都可以,但具体到驱动细节就需要根据操作的对象分别来实现。这时候,我们尽量把通用外设的操作和具体外设的操作区分开来,比如i2c共有的代码单独放到一个文件,针对eeprom的操作单独放在一个文件去引用i2c的代码,其它外设如传感器控制采用类型方式。
另一个问题,就是多个同类外设,比如UART,会有UART1,UART2……等多个UART,如果我们在定义宏、函数名的适合,不加区分,如UART_xxx(),那当我们同时使用UART1和UART2时这时就有命名冲突。因为UART1和UART2对应的管脚不一样,甚至有的同类外设时钟等也不一样,这时候我们最好进一步对管脚进行抽象,如定义UART1相关的宏或管脚结构体,尽量做到面向对象编程中的类和对象模型,方便同类芯片不同板子的移植工作。
标准化
虽然stm32外设众多,管脚复用繁杂,但是不同外设的使用方式上仍然有很多功能的地方,如需要先定义GPIO初始化结构体,外设初始化结构体,开启对应的GPIO和具体外设时钟,配置GPIO输入输出模式结构体,配置外设结构体,配置或使能GPIO复用功能等,这些操作对于不同外设都有类似的模式。另外,不同的板子的驱动,如果对方抽象的比较好,比如把移植相关的代码都定义在了头文件,那我们也是可以直接拿来简单修改即可以使用。尤其是官方的参考实例,一些简单的协议我们可以自己理解后自己编写,对于复杂的通信协议,比如USB等,如果没有移植问题,肯定要参考已有的示例。
命名上,建议和驱动相关的文件以bsp_xxx方式命名,这些代码如果用于移植到某个rtos,都是可以直接使用的。
代码架构
对于库开发方式,如果是学习,则每个外设功能一个项目目录便于理解。
如果是产品开发,则为一个项目目录,方便各模块调用。
来源:oschina
链接:https://my.oschina.net/u/114411/blog/691211