嵌入式开发笔记随记

1、CAN 485相关理解

3、snprintf(写到哪里,写多少个,"格式化字符",变量) snprintf(buf,sizeof(temp),"%s",version);strncat(连接到哪里,连接谁,从哪里开始连接) strncat(buf,temp.sizeof(buf)-strlen(buf)-1);

4、结构体数组的使用和初始化Device_ST *dev_st = &devicezj_id-23;

5、与或非,异或,同或解决不了的变量取值问题,使用遍历移位 与操作 再取反

6、对于一个结构体,实例化是一个二维数组,比如DevInfo_md md_dev3MAX_DEV;

假设 MAX_DEV = 10,那么 md_dev3MAX_DEV 就是一个包含 3 行,每行 10 个 DevInfo_md 元素的数组。你可以通过 md_devi 访问某一行,也可以通过 md_devij 访问某一行的具体元素。

md_devi 是类型 DevInfo_mdMAX_DEV 的一维数组;

md_devij 是 DevInfo_md 类型的单个元素

md_devi访问的是这一行,一个类型,二维数组访问的是具体的某个元素

7、函数指针结构体的用法

​

8、开发商,物业,楼栋楼层 结构体指针的应用

如果是全局的结构体,创建很多的数组,会占用大量的全局空间内存,总10KB左右 数据量小,均匀连续

如果是局部结构体,占用栈区空间消耗,总40KB左右,但是访问比较快,不用考虑内存泄漏问题,性能好,代码简单

如果使用结构体指针创建,需要动态开辟内存空间, 总120KB左右,需要手动释放,开发复杂,但是节省内存空间,不会导致溢出 数据量大,不均匀

对于启动文件的堆栈空间,线程创建消耗栈区内存,虽然可能创建的线程很多,超过了栈区的总大小,但是实际使用并没有超过当前线程分配的栈空间大小

还有一些情况内存空间是动态调整的,但是最好还是遵循内存布局,使用指针不需要的时候释放空间,需要再用

另外访问的时候遍历也能少一些

9、冒泡,快速,插入,反转,斐波那契,质数

10、中断和事件,外部中断

11.在多个实时变化的数据中取出最大值

12.并发线程,多个时间线程同时异步执行,多个中继器同时执行不同的喷洒逻辑

状态机,消息队列,定时器

13.精通UART,SPI,IIC,USB,CAN 485常见的协议移植和驱动开发,并且示波器调信号,

14.编码器控制PWM,ADC传感器读取,

15.IAP升级,bootloader开发移植

16.rt_thread操作系统 OTA升级功能

17.rt_thread_mdelay打印部分,哪个线程在占用 线程耗时比较短的线程打印

18.对于数字类需要加U尾缀 然后移位操作 如果超过32位 1需要改成 (UINT64_C(1)) 所有的数字都要

19.事件集的处理

20.实时打印当前运行的线程名称

cpp 复制代码
在void rt_schedule(void)中最后增加
#if DEBUG_TIME
    static struct rt_thread *last=NULL;

    if(last!=rt_current_thread)
    {
        last=rt_current_thread;

        rt_kprintf("RUN:%s\r\n",
                   rt_current_thread->name);
    }
    #endif
    /* enable interrupt */
    rt_hw_interrupt_enable(level);

__exit:
    return;

21.实时打印线程名称和delay时间

cpp 复制代码
rt_err_t rt_thread_mdelay(rt_int32_t ms)
{
    #if DEBUG_TIME
    rt_thread_t thread;

    thread = rt_thread_self();

    if(ms > 0 && ms < 1000)
    {
        rt_kprintf("[DIRECT_MDELAY] th=%s ms=%d tick=%u\r\n",
                   thread != RT_NULL
                       ? thread->name
                       : "null",
                   ms,
                   (unsigned int)rt_tick_get());
    }
    #endif
    rt_tick_t tick;

    tick = rt_tick_from_millisecond(ms);

    return rt_thread_sleep(tick);
}

22.低功耗模式下让JLINKE一直保持连接

cpp 复制代码
DBG_ConfigPeriph(DBG_SLEEP |
                     DBG_STOP |
                     DBG_IWDG_STOP |
                     DBG_WWDG_STOP,
                     ENABLE);

23.线程最好要统一处理,尽量减少线程的使用,增加局部函数体的调用,局部变量一定要初始化

24.当使用rt_thread_mdelay进行时间片切换的时候,其他外部触发需要准确下一步跳转到xx线程运行的处理,参考安定宝代码gpio点灯部分

随机bug原因:

1.边界问题 临界区

2.共享内存

3.全局变量多出修改

4.上行输入诊断

5.饱和,限幅值

6.溢出 泄露

7.锁范围释放

8中断嵌套优先级配置错误

9野指针、空指针访问

10未初始化局部变量

11看门狗使用不当

12Flash/EEPROM 擦写超时、写冲突

13内存对齐问题

软件设计规则:

□ 01. 我处理的是"当前状态",还是其实应该处理"状态变化"?

□ 02. 如果只允许触发一次,我有没有保存 last / handled?

□ 03. 多个 bool 能不能用 bitmask 表达得更清楚?

□ 04. if/else 是否已经多到应该改成状态机?

□ 05. 有没有为了等时间而阻塞本可继续运行的任务?

□ 06. 超时判断是否使用了统一的 tick/时间单位?

□ 07. 输入会不会抖?是否需要连续 N 次确认或迟滞?

□ 08. 中断里是否做了 printf、解析、循环、阻塞等重工作?

□ 09. 生产数据和消费数据速度不同,是否需要队列/环形缓冲区?

□ 10. 共享变量是否存在多个写者?能否明确唯一 owner?

□ 11. 多字段读取是否可能出现"一半新、一半旧"?

□ 12. 数组下标、长度、地址、枚举是否做了范围检查?

□ 13. "0 / -1 / 0xFF"到底是正常值还是故障值?有效性是否应独立?

□ 14. 故障应该自动恢复,还是必须人工 reset?

□ 15. 数值计算、计数器、乘法有没有溢出风险?

□ 16. 通信失败后是有限重试,还是无脑高频重发?

需求一实现一风险点一查手册一做实验一总结一个模型。

相关推荐
懿路向前1 小时前
【唤醒实战笔记】2026-09-29 | 智能体提示词迭代史(v1 → v8)
linux·笔记·算法
2601_957883842 小时前
2026年9月:雷神专业维修服务保障
笔记
71-32 小时前
MySQL密码重置
数据库·笔记·学习·mysql
咖啡忍者3 小时前
【SAP BASIS】Section 13: Managing Transport Request
笔记
bllovepigpig4 小时前
操作系统个人学习笔记(四):K8s基础
笔记·学习·kubernetes
有范先生4 小时前
懒人代餐即食米饭:常温全能型,让一顿热饭不受厨房和冰箱限制
笔记
高山有多高4 小时前
【Linux笔记】Linux基本指令
linux·运维·笔记
司南-70494 小时前
AI infra 学习笔记(三):预处理·第一步——QKV 投影到底算了多少
人工智能·笔记·学习
sevenez5 小时前
AiMaMi 介绍及与 CC Switch 对比
笔记