软件设计——随手笔记

  • 头文件包含其它头文件尽量少
  • include头文件会导致文件体积增大吗?不会。最后生成的可执行文件.hex里面只有函数定义、全局变量、以及一些字符串常量等。这些才会占据.hex文件的空间。c文件里定义变量和函数,h文件里声明变量(有的用extern声明对应c文件的变量成外部变量)和函数
  • 软件中标志位变量,计数变量什么时候复位非常重要,要么是置位后马上复位,要么在其它地方复位,计数变量一般是计满值触发执行后马上复位
  • 全局变量的共用时间点非常关键,不要这边在改变,那边却要使用改变前的值,这样程序就会出现奇怪值
  • 软件中同样需要设置测试点
  • 软件看门狗必须加上
  • 端口的输入输出模式很重要,模式不对,就达不到效果,比如逻辑电平输出就不能设置推挽输出,而是准双向
  • 用串口调试助手时,把杀毒软件退出,否则影响串口稳定
  • 主函数中必须有while(1)循环,否则程序会不断复位
  • 程序的头文件必须对应所用的芯片型号,否则会出现奇怪的问题
  • 软件设置中内存模式DATA和XDATA是有差别的
  • 看门狗喂狗是在主循环里喂,不要在中断里或多处喂狗
  • 函数应该是一个入口,一个出口
  • 一个系统程序执行逻辑时,某一个设置应该是在某一种运行模式的条件下生效的,所以系统需要分割成不同运行模式
  • 程序里多写一些测试打印函数,把想知道的作为打印的数据,单片机寄存器的值可以作为判断条件进行打印,把看不到的值显示出来,比如串口不响应,可以把串口接收的原始数据打印出来,把寄存器的值打印出来,看有没有丢包或错位,串口数据帧接收一定要先判断帧头正确了再继续计数接收,不能来数据就计数接收,容易出现错位问题当软件无法找到奇怪问题的原因时,转去检查电信号是否正常
  • 用条件编译来打开或关闭log打印的语句,也可以关闭或打开某个功能模块
  • 当启用新的功能模块时,进入低功耗模式前记得关闭对应的模块,避免出现莫名其妙静态电流就变大了
  • 串口助手选的是无校验,程序里把发送的字节数据赋给ACC,再把ACC赋给SBUF,结果串口收到的数据没错,发出来的一直不对,原来ACC寄存器是用于校验的,如果无校验,就直接把数据给SBUF就行
  • 芯片的寄存器总数取决于存放寄存器地址的位宽度(地址线条数),比如位宽度是4,那么就有16个寄存器地址,地址是该寄存器在内存中唯一位置标识,地址好比房间号,寄存器好比房间,寄存器的值就是房间里的物品,寄存器类型又分多种,各有用途
  • 芯片数据手册中参数的典型值表示默认值,也是寄存器的默认值
  • 各种变量初始化:整型和浮点型初始化为0,字符初始化为’\0’,字符串初始化为" ",可以使用memset函数(按照字节进行填充),指针初始化为NULL,但如果没有重新给指针分配内存,就会出现难以预料的错误,所以可以用malloc等函数给指针分配内存,用完指针后释放它,并将指针置为NULL,否则为编程野指针,结构体初始化可以用memset
  • 真正的模块化,并不是文本意义上的,而是逻辑意义上的。一个模块应该像一个电路芯片,它有定义良好的输入和输出。它的名字叫做“函数”。每一个函数都有明确的输入(参数)和输出(返回值),同一个文件里可以包含多个函数,所以你其实根本不需要把代码分开在多个文件或者目录里面,同样可以完成代码的模块化。
  • 避免写太长的函数。如果发现函数太大了,就应该把它拆分成几个更小的。通常我写的函数长度都不超过40行。
  • 制造小的工具函数。每个函数只做一件简单的事情。函数既共享一些代码,又是独立函数。
  • 避免使用全局变量和类成员来传递信息,尽量使用局部变量和参数。
  • 帮助大大减少写代码注释的方法:
    使用有意义的函数和变量名字。
    局部变量应该尽量接近使用它的地方。
    局部变量名字应该简短。
    不要重用局部变量。
    把复杂的逻辑提取出去,做成“帮助函数”。
    把复杂的表达式提取出去,做成中间变量。
    在合理的地方换行。
  • 避免使用自增减表达式(i++,++i,i–,–i)。
  • 永远不要省略花括号。合理使用括号,不要盲目依赖操作符优先级。
  • 避免使用continue和break。循环语句(for,while)里面出现return是没问题的
  • 写代码有一条重要的原则:如果有更加直接,更加清晰的写法,就选择它,即使它看起来更长,更笨,也一样选择它。
  • 代码里面很少出现只有一个分支的if语句。我写出的if语句,大部分都有两个分支,每个if语句都有两个分支的理由是:如果if的条件成立,你做某件事情;但是如果if的条件不成立,你应该知道要做什么另外的事情。不管你的if有没有else,你终究是逃不掉,必须得思考这个问题的。
  • 代码可靠的一种通用思想:穷举所有的情况,不漏掉任何一个。尽量不要产生null指针。尽量不要用null来初始化变量,函数尽量不要返回null。
  • 防止过度工程的原则如下:
    先把眼前的问题解决掉,解决好,再考虑将来的扩展问题。先写出可用的代码,反复推敲,再考虑是否需要重用的问题。先写出可用,简单,明显没有bug的代码,再考虑测试的问题
  • Dev C++开发软件可以运行C语言基础编程,查看内存情况
  • 对于软件功能模块化设计,可以使用条件编译对代码块进行选择性编译,比如
    #define configUSE_COMM 1
    #if (configUSE_COMM == 1)
    代码块1
    #else
    代码块2
    #endif
    当这个宏定义为0时,就不执行代码块1了,很方便
  • 开发环境只是一种工具,做同一件事可以用多种不同的工具来完成它,就看这工具能不能做到而已
  • 赋值时一定确保左右两边的数据类型一致,否则会出错或运行奇怪
  • 不同的编译器理解为对编码翻译结果(机器码)不同,比如同一个代码文件,编译器A可以正确翻译,编译器B却无法翻译一些代码,编译器可以比喻成不同国家的人,对同一段文章的不同理解。不同编译器要求编码的语法是有所差异的,所以更换编译器后,编码格式或语法就要做相应的修改
  • 用gpio模拟串口收发通讯:串口协议中高电平表示空闲,拉低后表示通信开始。波特率9600,是1s内传送9600个bit,一个bit所需要的时间为 1000000us / 9600 = 104.166 us,也就是104us。发送数据采用while结合delay的阻塞式,比较占用cpu,不能做其他任务,采用定时器定时104us发送更高效,接收数据必须采用定时器中断,中断时间为52us,在接收到下降沿中断来临的时候,开启定时器中断
  • 结构体中的冒号表示位域,就是把一个字节的八个位分成不同区域,存储不需占用一个字节的信息,冒号右边是区域的位数,位域跟结构体成员使用方法一样
  • 单片机定时器定时计算方法:
    对12MHz晶振 1个机器周期 1us 12/fosc = 1us
    方式1 16位定时器最大时间间隔 = 2^16 = 65.536ms
    方式2 8位定时器最大时间间隔 = 2^8 = 0.256ms =256 us
    定时5ms,计算计时器初值 M = 2^K-XFosc/12 12MHz
    方式0: K=13,X=5ms,Fosc=12MHz 则 M = 2^13 - 5
    10(-3)*12*106/12= 3192 = 0x0C78
    THx = 0CH,TLx = 78H
  • 单片机C语言unsigned char code table[],
    code的作用是告诉单片机,我定义的数据要放在ROM(程序存储区)里面,写入后就不能再更改
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值