跳转至

模块化代码简介 - 实例

Hi, 今天主要分享的是一个写代码的模块化设计,主要以一个例子进行探讨分析。

想要写的好自己的代码,就需要多学习一些思想,当你拿到一个项目时候,不是嘎嘎一段就开始造,而是在你写代码之前需要考虑整个代码框架的设计,模块化设计,让代码显得更加优雅。俗称高内聚,低耦合!

1. 案例介绍

本案例以MCU STM32 作为主控,蜂窝模块作为无线通信模块,采用串口通信。

目标:实现访问HTTP 网络功能;

硬件链接图如下:

image-20240904102014840

从硬件图来说非常简单,Cellular 模块与MCU 通过常用的串口连接,通过AT指令进行交互获取数据;

在没有使用过蜂窝模块的朋友,这里先简单介绍下,蜂窝模块就是常用语上网模块,在嵌入式设备中长如图这样:

image-20240904102437881image-20240904102800280

常用通信接口:

UART, SPI , 或者其他

通信协议:

大多数都采用AT

2. 系统代码设计

从功能和后期维护来看,考虑到有蜂窝模块硬件通信部分(UART,SPI或者其他),蜂窝控制部分,蜂窝模块的AT命令部分,提供上层网络应用使用部分;

image-20240904114315924

引入中间层接口,统一不同模块的接入,更换其他蜂窝模块非常方便,上层代码结构也不会有很大变化。通过module 底层收发可以设定通信的接口方式,而不绑定到具体接口。

通信部分:

对于蜂窝模块考虑作为一个设备创建,对其通信部分赋予读写接口层,控制赋予相应接口,创建多个指针函数:

typedef struct {
    void (*modem_power_up_ptr)(); 
    void (*modem_reset_ptr)(); 
    void (*modem_power_off_ptr)(); 
    uint32_t (*modem_read_ptr)(int32_t fd, uint8_t *buffer, uint32_t length, uint32_t timeout); 
    uint32_t (*modem_write_ptr)(int32_t fd, const uint8_t *data, uint32_t length); 
    void (*modem_dtr_ptr)(bool state); 
    bool (*modem_ri_read)(); 
    void (*modem_wake_up_psm)(); 
} HalModemOps;

AT部分:

AT指令部分设计到业务,比如联网,设置制式,发送TCP/UDP,接收TCP/UDP 等等具体接口。但这里需要注意不同的厂家的模块可能存在点点差异,虽然大多都是一样,但总有一些差距。

AT 业务放到中间层上,采用include 到具体模块解决,这样可以灵活切换到其他蜂窝模块。

总结

主要对例子进行一个简单分析,主要对于这些业务和底层进行分层,物理模块进行虚拟化,创建中间层进行隔离,采用函数指针,回调方式,对代码的耦合性大大减小。虽然说这样带来工作量会多一些,但是对于维护应该非常方便。