尝试描述程序设计的一般思路
概述
写代码之前,特别是开发新模块,先考虑后期维护问题。
下面以LED控制,记录开发的过程,准备工具:
XMind 脑图
Snipaste 截图/贴图
有道词典
NotepadNext
Word
打开 XMind
打开脑图软件,进行设计:
列出LED的基本需求,准备抽象这个模型。
LED模型抽象
了解整体情况后,它大致需要这些东西,初步建构成这个样:
数据结构设计
需要满足:
单个LED的控制
多个LED的管理
LED的控制时基
打开有道,随时翻译。打开Snipaste,截图贴在屏幕上,边看边写代码。
LED控制的结构体:
typedef struct
{
uint8_t status; /* LED的状态 */
void (*ctr_cbk)(uint8_t); /* LED亮灭控制 */
void (*toggle_cbk)(void); /* LED翻转 */
}ry_led_t;
LED控制块,管理所有注册的LED:
typedef struct
{
uint32_t tick; /* LED的时基 */
ry_led_t list[RY_LED_SN_MAX]; /* LED列表 */
}ry_led_obj_t;
用户的LED,用于注册LED:
typedef enum
{
LED_WHITE,
RY_LED_SN_MAX,
}E_user_led_sn_t;
其它一些参数:
/* LED的闪烁周期 */
/* LED的状态 */
typedef enum
{
RY_LED_OFF,
RY_LED_ON,
RY_LED_SLOW_FLICKER,
RY_LED_NORMAL_FLICKER,
RY_LED_FAST_FLICKER,
}E_led_status_t;
LED创建函数
创建之前,LED驱动先定义了一个‘__ledObj’控制块:
static ry_led_obj_t __ledObj = {.tick = 0};
/* 创建一个LED,并设置其默认状态 */
void ry_led_create(E_user_led_sn_t led, E_led_status_t s,
void (*ctr_cbk)(uint8_t), void (*toggle_cbk)(void))
{
if(led >= RY_LED_SN_MAX)
return;
__ledObj.list[led].status = s;
__ledObj.list[led].ctr_cbk = ctr_cbk;
__ledObj.list[led].toggle_cbk = toggle_cbk;
}
LED扫描控制
基本逻辑设计,扫描 + 状态机:
/* LED扫描,定时调用该函数实现LED控制 */
void ry_led_scan(void)
{
E_user_led_sn_t sn;
__ledObj.tick++;
for(sn = 0; sn < RY_LED_SN_MAX; sn++)
{
__led_ctr(sn);
}
}
static void __led_ctr(E_user_led_sn_t led)
{
switch(__ledObj.list[led].status)
{
case RY_LED_ON :
__ledObj.list[led].ctr_cbk(1);
break;
case RY_LED_SLOW_FLICKER :
if(__ledObj.tick % LED_SLOW_FLICKER_CYCLE == 0)
__ledObj.list[led].toggle_cbk();
break;
case RY_LED_NORMAL_FLICKER :
if(__ledObj.tick % LED_NORMAL_FLICKER_CYCLE == 0)
__ledObj.list[led].toggle_cbk();
break;
case RY_LED_FAST_FLICKER :
if(__ledObj.tick % LED_FAST_FLICKER_CYCLE == 0)
__ledObj.list[led].toggle_cbk();
break;
default :
__ledObj.list[led].ctr_cbk(0);
break;
}
}
LED状态配置函数
状态配置,供外部更改LED状态:
void ry_led_status_cfg(E_user_led_sn_t led, E_led_status_t s)
{
if(led >= RY_LED_SN_MAX)
return;
__ledObj.list[led].status = s;
}
总的结构
至此,总的结构就出来了:
其它工作
文档编写
代码测试
程序维护升级
-END-