1.字符串赋值,字符串在初始化后的赋值方式:用strcpy
2.scanf("%s",buff),空格、回车结束接收
3.数组arr[10]只在sizeof(arr)和取地址(&arr)时表示整个数组,其余均表示数组首元素地址
4.指向数组元素的指针可以与数组后面(越界)的指针比较,不可以与前面(越界)的指针比较
5.指针取地址是二级指针,如果void hanshu(char *p)
char *q;
hanshu(&q);
此时p是指向q的指针,即二级指针,改变p并不会对q的值有影响(形参)
6.const *和*const的区别:const *不能改变指针所指的目标数值,*const不能改变指针的值
7.微库使用:勾选target->Use microLib
8.USART清除总线空闲中断标志位的方法是操作数据寄存器,USART_ReceviceData()
9.重映射:一个外设可以有好几条通道,通过部分重映射、完全重映射可以更改,具体看stm32f103rc_datasheet.pdf
10.局部变量不能返回地址,当地址被释放后,无法通过地址找到值
11.ip地址,例:172.168.120:1/20,子网ID是172.168.112.0,子网掩码是:255.255.240.0,子网个数是16
12.时间函数:
time_t time(time_t *tloc) //获得时间
gmtime(time_t *clock) //获取国际时间
localtime(time_t *clock) //获取当地时间
asctime()//将国际时间转换成字符串时间
13.SPI的采样和输出:采样指的是读取信号,输出是指更改信号线
14.公网IP:在广域网上的IP,私网IP:在局域网上的IP
15.双目操作符&&和||的短路原则:&&从左到右遇到0后就不再往下运算,||遇到1后就不再往下运算
16.位段
struct A
{
int a : 2;
int b : 3;(位段)
}
17.bootloader和app,keil的设置,utilities->setting->erase sectors(擦除指定区域)
18.当bootloader和.s(app)都进行systeminit时钟初始化时,可以将.s中的IMPORT SystemInit;LDR R0, =SystemInit;BLX R0 ;三项用;屏蔽掉,减小代码大小
19.向量中断表偏移:向量中断表偏移值=程序烧录地址偏移值,在SystemInit函数中的SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET
20.U、L、F的作用:将常数强转,防止溢出C语言中在常数后面加U、L、F的功能(转)_guanjianhe的博客-CSDN博客_常量后面加u
U:unsigned
L:long / double
F:float
21.结构体对齐字节
#pragma pack(push) ---- 保存对齐状态
#pragma pack(pop) ---- 恢复push指令的对齐状态
#pragma pack(1) ---- 将对齐字节设置为1
#pragma pack() ---- 设置默认对齐字节
22.条件编译
#if
#elif
#elif
#else
#endif
23.F407主频时钟问题:F407时钟主频是168MHZ,默认是25MHZ的外部高速时钟,如果是8M的外部高速时钟,需在工程的system_stm32f4xx.c的第370行和外设usart.c的第327行及stm32f4xx.h的第144行改25为8
24.__asm__ (“nop”)是内嵌汇编做空指令延时用的,其中asm()的作用是指函数内部的参数翻译为汇编指令,其作用是在C语言环境下直接使用汇编指令执行。nop是一个空等待汇编指令,这个指令执行时,单片机是什么也不做,仅仅起一个时间延时作用,一个nop等于一个机器周期。volatile i = 5;while(i--);延时时间为:5*i+5个nop。asm(nop);具体延时_Mr_White01的博客-CSDN博客_asmnop延迟时间多少
25.静态链接和动态链接:静态链接是在形成可执行程序前(编译进去了),动态链接的进行则是程序执行时(形成库文件)
26.枚举内存:根据成员的范围来定,若成员从-1~128,则需要两个字节。若0~65536,需要4个字节。枚举的可以节省内存。
27.MDK的htm静态调用图文件中的Maximum Stack Usage = 32 bytes + Unknown(cycles,Untracable Function Pointers)中的32字节指的是静态调用函数(不包含递归、回调等函数)占用栈的最大空间,一般分配的栈需要大于这个值的1倍。
28.PSRAM内部和DRAM结构一样,但不需要手动刷新,比DRAM访问速度快,比SRAM容量大、价格便宜。
29.NOR FLASH和NAND FLASH:
异:NOR FLASH可以随机按字节读取数据,NAND FLASH需要按块进行读取
同:两者的擦除都是按块进行的,NOR FLASH的擦除和写入比NAND FLASH慢
30.__arttibute__((at()))的作用:绝对定位,https://www.cnblogs.com/xyelectric/p/9046048.html
31.keil5的内置宏定义__DATE__和__TIME__,可以将编译时间固化到FLASH中
keil5设置某文件总是编译:右键选择文件,选择options,勾选always Build
–DATE–------用于获取当前日期—格式— Jul 03 2020
–TIME–------ 用于获取当前时间—格式—15:52:54
30.低功耗模式下的独立看门狗处理方式:1.用RTC唤醒喂狗 2.手动复位后进入低功耗
31.备电域引脚:(LSE输入和TAMPER-RTC)
1.当单片机的备电域引脚作为GPIO使用时,速度必须限制在2MHZ以下,最大负载为30pF,绝对不能当做电流源(如驱动LED)
2.当备份域第一次上电时,这些引脚处于主功能状态,之后复位,这些引脚的状态由备份域寄存器控制。
32.变长数组int arr[n] //n变量只能在数组定义前起作用
1. 变长数组不能初始化
2.在定义数组时,变量的值必须确定且大于0
3.数组不能定义为全局的
33.SPI时钟下降沿进行采样,通信会更稳定,下降沿往往是稳定的,上升沿由于PCB或线路原因,可能出现抖动stm32 硬件SPI接收 数据的干扰、丢包的一些感想_spi有丢包机制-CSDN博客
34.FAT文件系统,挂载U盘后需延时一会,然后再执行文件IO。同时,若文件IO返回失败,有可能是需要延时一会,可能跟USB驱动有关系,也可能是全速设备读写太慢,需要等待。
35.DSP调试bootloader时的问题记录
a.DSP的bootloader拷贝至RAM运行的函数可能跟全局变量的地址重复
b.CCS不会检测RAM地址分配是否超过RAM大小
c.DSP栈顶指针设置,寄存器受保护,需加解除保护
EALLOW;
asm(" MOV SP,#0x400"); /* 设置栈顶指针 */
EDIS;
d.bootloader调用系统时钟初始化函数,函数中有用到系统延时函数F28x_usDelay,若未将延时函数拷贝至RAM,程序会跑飞,可替换成其它用循环延时
e.关于DSP的内部FLASH操作API,需要添加官方的API库
f.DSP使用看门狗进行软件复位,给WDCR.EDCHK写入非101立即复位
36.数据类型提升时,高位补充符号位,无符号类型无符号位,则补充0
37.__f32toui16r:C2000编译器数据类型转换,将folat32转成16位整型,四舍五入
38.stm32的CAN过滤器(28组):
在bxCAN中,每个过滤器组都存在这么两个寄存器CAN_FxR1和CAN_FxR2,这两个寄存器都是32位的,他的定义并不是固定的,针对不同的工作模式组合他的定义是不一样的,如列表模式-32位宽模式下,这两个寄存器的各位定义都是一样的,都用来存储某个具体的期望通过的CAN ID,这样就可以存入2个期望通过的CAN ID(标准CAN ID和扩展CAN ID均可);若在掩码模式-32位宽模式下时,则CAN_FxR1用做32位宽的验证码,而CAN_FxR2则用作32位宽的屏蔽码。在16位宽时,CAN_FxR1和CAN_FxR2都要各自拆分成两个16位宽的寄存器来使用,在列表模式-16位宽模式下,CAN_FxR1和CAN_FxR2定义一样,且各自拆成两个,则总共可以写入4个标准CAN ID,若在16位宽的掩码模式下,则可以当做2对验证码+屏蔽码组合来用,但它只能对标准CAN ID进行过滤。这个就是bxCAN过滤器的解决方案,它采用了这4种工作模式。
例子:验证码:0x100 掩码:0x100,则验证码的第9个bit有效,所以能获得0x..1xx的CANID
验证码:0x100 掩码:0x1F0,则验证码的第4-9个bit有效,所以能获得0x..10x的CANID
STM32 CAN 过滤器、滤波屏蔽器配置总结_can过滤器id和掩码设置成一样为什么不行-CSDN博客
39.结构体对齐:为了提高CPU寻找结构体成员的效率,采用空间换时间的策略,原则为:
对齐数:该结构体成员变量自身的大小与编译器默认的一个对齐数的较小值(gcc默认为8)
1.结构体成员首地址为其对齐数的整数倍,数组的对齐数为数组类型大小,嵌套的小结构体为其最大成员对齐数
2.整个结构体的大小为对齐数的整数倍,结构体嵌套结构体,小结构体的对齐数是自身的成员最大对齐数
40.数据类型的隐式转换:
1.整数提升:运算时(计算或比较)有符号的小于int提升为int,有符号的高位补符号位,无符号高位补0
2.算术转换:编译器首先会执行整数提升,如果数据类型不同,则会按int->unsigned int->long->unsigned long->long long->unsigned long long->float->double->long double此顺序将长度小的转换成大的,常见的算术转换不适用与赋值运算逻辑运算&&和||
41.指针运算,要对一个指针进行运算时,要注意指针类型,如果是想取该地址进行运算,则要先强转成U32类型,例:
u16 data[10];
&data+6 = data[6]; //指针运算
(u32)&data+6 = data[3]; //无符号类型运算
42.CPLD的引脚约束需要配置properties中的persist bit为0
43.浮点数清零不能使用内存清0,如memset()函数,需要一个一个赋值
44.DSP的中断优先级,在PIE中管理,分通道优先级和组优先级,组越低和通道越低则优先级越高,CPU是响应组的请求,然后再查找组中最高优先级的中断,如当PIEIFR2.3触发中断后,这时PIEIFR2.1和PIEIFR1.1中断标志也置位了,那CPU查找中断向量时会先响应2.1,执行完2.1后执行1.1,最后2.3。此外,DSP的中断默认是不嵌套的,如果要嵌套,要手动修改。
45.CCS添加IQmath库,需要在cmd文件分配数据地址,可参考例程
46.德维创取特定谐波,谐波变量名@电力组[N],谐波变量名即电力组的harmonics中的xx_hRMS,N为几次谐波,例:'I1_hRMS@负载'[0]即直流分量
47.CLA是按32位读取的,结构体中的成员变量都用32位才能正常访问成员变量,如果定义成16可能会按32位寻址,然后读出32位数据