1、程序的样式与结构
C语言与C++和python等语言不同,他是一门面向过程的编程语言,所以其的应用大多是用在单片机及嵌入式的驱动方向,同时由于其入门相对简单,所以其基本上是大多数人入门程序设计时第一门接触到的语言,对于入门来说,在课堂上老师基本上不会讲解一项工程设计时,对于程序的样式和结构的要求,这就导致了很多学生只求把老师要求的任务完成就万事大吉了,对于程序样式和程序结构都没有太过注意,我本科在电子设计实验室学习的时候,周围有很多同学都是这样的态度,对项目指标的要求只求达到即可,但是对于整个程序的调用胡乱无章,最后工程完成,同项目组的同学对程序进行查看时,往往一头乱麻不知道从何看起,自己过一段时间后需要对原来项目进行调用修改时,也是一头雾水,这个在实际工作中是不可取的,第一这样会导致效率低下,第二,在后期对程序进行维护的时候往往很容易出现意想不到的BUG。
下面介绍一个好的项目程序应该如何布局和搭建。
首先,对于没有调用RTOS的一个项目,程序的结构要清晰,一般main.c文件应该为工程文件的顶层头文件,其他的.c类文件应该为对应功能的完成文件,其中.c类文件的.h 类文件应该为该类文件的API接口,然后通过include.h文件来进行调用设置,最后被main.c文件进行调用。但是,当工程特别巨大时,还是建议另外在建立一个schedule.c文件将初始化的调用和中断处理等作为函数在这里进行分级后再在main.c里面进行调用,这样工程结构就会特别清晰了,对于后期的修改和维护也会方便的多。
下面以我最近在看的GIT上的文件为例:
1 // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <unistd.h> 18 #include <string.h> 19 #include "freertos/FreeRTOS.h" 20 #include "freertos/task.h" 21 #include "nvs.h" 22 #include "nvs_flash.h" 23 #include "esp_system.h" 24 #include "esp_log.h" 25 26 #include "bt.h" 27 #include "bt_app_core.h" 28 #include "bt_app_av.h" 29 #include "esp_bt_main.h" 30 #include "esp_bt_device.h" 31 #include "esp_gap_bt_api.h" 32 #include "esp_a2dp_api.h" 33 #include "esp_avrc_api.h" 34 35 /* event for handler "bt_av_hdl_stack_up */ 36 enum { 37 BT_APP_EVT_STACK_UP = 0, 38 }; 39 40 /* handler for bluetooth stack enabled events */ 41 static void bt_av_hdl_stack_evt(uint16_t event, void *p_param); 42 43 44 void app_main() 45 { 46 /* Initialize NVS — it is used to store PHY calibration data */ 47 esp_err_t ret = nvs_flash_init(); 48 if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { 49 ESP_ERROR_CHECK(nvs_flash_erase()); 50 ret = nvs_flash_init(); 51 } 52 ESP_ERROR_CHECK( ret ); 53 54 55 esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); 56 if (esp_bt_controller_init(&bt_cfg) != ESP_OK) { 57 ESP_LOGE(BT_AV_TAG, "%s initialize controller failed\n", __func__); 58 return; 59 } 60 61 if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) { 62 ESP_LOGE(BT_AV_TAG, "%s enable controller failed\n", __func__); 63 return; 64 } 65 66 if (esp_bluedroid_init() != ESP_OK) { 67 ESP_LOGE(BT_AV_TAG, "%s initialize bluedroid failed\n", __func__); 68 return; 69 } 70 71 if (esp_bluedroid_enable() != ESP_OK) { 72 ESP_LOGE(BT_AV_TAG, "%s enable bluedroid failed\n", __func__); 73 return; 74 } 75 76 /* create application task */ 77 bt_app_task_start_up(); 78 79 /* Bluetooth device name, connection mode and profile set up */ 80 bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); 81 } 82 83 84 static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) 85 { 86 ESP_LOGD(BT_AV_TAG, "%s evt %d", __func__, event); 87 switch (event) { 88 case BT_APP_EVT_STACK_UP: { 89 /* set up device name */ 90 char *dev_name = "ESP_SPEAKER"; 91 esp_bt_dev_set_device_name(dev_name); 92 93 /* initialize A2DP sink */ 94 esp_a2d_register_callback(&bt_app_a2d_cb); 95 esp_a2d_register_data_callback(bt_app_a2d_data_cb); 96 esp_a2d_sink_init(); 97 98 /* initialize AVRCP controller */ 99 esp_avrc_ct_init(); 100 esp_avrc_ct_register_callback(bt_app_rc_ct_cb); 101 102 /* set discoverable and connectable mode, wait to be connected */ 103 esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); 104 break; 105 } 106 default: 107 ESP_LOGE(BT_AV_TAG, "%s unhandled evt %d", __func__, event); 108 break; 109 } 110 }
这里文件按的内容并不是最重要的,贴出这篇文档是为了由此学习一份好的程序的大致样式,从这篇文章可以可看出文件基本的书写样式如下:
/************************************************************************* * 版权所有 (C)2013,公司(或个人)名称。 * 公司网站或个人联系方式 * 文件名称: * 内容摘要: * 其他说明: * 作者: * 完成日期: * * 修改记录1: * 修改日期: * 版本号: * 修改人: * 修改内容: * * * **************************************************************************/ #include 'XXX.h' //自写的.h文件最好加备注 #ifdef _XXX_H //防止头文件被重复引用 #define _XXXX_H #endif /************************************************************************* 变量及相关宏定义 **************************************************************************/ /************************************************************************* 相关结构体定义 **************************************************************************/ /************************************************************************* 源程序中出现的函数声明 **************************************************************************/ /*************毫无疑问,上面声明部分的变量结构体和函数等最好进行相关注释**********/ //相关main函数实现功能说明 void main(void) { //main函数内除了函数的调用尽量少的涉及无关操作,这样可以保持程序的整洁性,并保持系统逻辑性 }
这里,可以看到对程序进行了严格的排版操作,这样,对于程序的阅读和修改都提供了良好的代码环境,这个部分从小的项目开始训练是最好的,开始可能感觉不到什么用处,但是当做到大型项目的时候,可以明显感觉到这种做法为程序编程提供了很大的便利。

浙公网安备 33010602011771号