1、当STM32的PA13/14/15引脚连接其他外设时,ST_link会出现internal grammar error 。
2、但有时未连接上述引脚也会出现此情况,可以通过保持reset按钮按下后不动,在stm32开发环境Keil中点击download按钮,随后松开reset。
3、在启动文件中有着stm32的分频设置,如果当前的外部晶振和内部设置的大小不匹配,则通讯时必然会出现乱码。
4、返回值函数和局部变量一起用的时候要仔细判断逻辑,避免出现多个返回值的情况,尽量使用static修饰的局部变量作为返回值
5、在程序上机之前,需要验证好他的逻辑是否正确,并在实验平台上实现期望动作之后,再上机验证。
6、与外部设备进行TTL通信时,需要共地。
7、定时器输入捕获多个通道的初始化函数,每个通道要单独初始化,不能TIM_Channel1|TIM_Channel2 这样
8、PID程序初次使用,出现了点问题,还没找到原因。猜测是因为显示函数在定时中断里面、或者占空比设置问题。
9、C++ & C short为一种数据类型,范围-32768~+32767。unsigned short i; i可以表示0~65535;signed(默认)short i; i可以表示-32768~+32767 ,两个字节即16位
10、不同的模块之间一定要共地。
11、OLED的显示函数尽量不要再中断中使用,会出现界面漂移的情况。
12、PID调节4路电机时,一定要将反馈环对应到正确的控制目标上,一旦错乱,PID调节过程中,将出现,一路越调越大,另一路越跳越小的情况,实际上是因为测速反馈接反了。
13、全局变量、静态全局变量、静态局部变量和局部变量的区别变量可以分为:全局变量、静态全局变量、静态局部变量和局部变量。 按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。
按作用域分,全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。
从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。
static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件
static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;
static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;
static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
全局变量和静态变量如果没有手工初始化,则由编译器初始化为0。局部变量的值不可知。
14、单片机跑飞的原因,中断处理没处理好,清的标志位可能不是本中断的标志。陷入中断中跳不出来。
15、程序运行的基本条件,初始化是前提、中断处理是关键。
16、硬件的热保护会关断电路。
17、PWM的使用,一个通道不行就换另一个通道试试。
18、const 在实际编程中用得并不多,const 是 constant 的缩写,意思是“恒定不变的”!它是定义只读变量的关键字,或者说 const 是定义常变量的关键字
19、stm32连接TTL转232转接头时 R接R 、T接T。
20、MQTT的发布任务不能放在中断中执行 会导致程序卡死
21、MQTT的两个发布任务需要间隔至少100ms。
22、有输出 有输入 需要分别初始化引脚
void FANS_RALAY_init(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12; //不同引脚功能 需要分别初始化
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //不同引脚功能 需要分别初始化
GPIO_Init(GPIOA, &GPIO_InitStructure);
//GPIO_SetBits(GPIOA, GPIO_Pin_11|GPIO_Pin_12);
}
23、电压是关键的一个参数,如果电压不对,用电设备很有可能工作不正常,尤其是射频设备在发射信号时,消耗功率加大,可能导致用电供给不足,设备重启
^= 异或
按位异或赋值 (^=)
示例:
i = 0x00;
i ^= 0x01;
第一次执行结果为 i = 1
第二次执行结果为 i = 0
以此类推
22、关于break、continue、return
23、& 叫取地址符
int a;
int *p;
p=&a;//此时p取得了a的地址。
24、*号在C语言中的作用
1.乘号
2.声明一个指针变量 例如
int *p;
3.间接访问符,取得指针所指向的内存的值;例如
printf("d%",*p);
25、malloc函数的使用 动态申请内存空间
#include
1.malloc()返回类型是void*类型——表示未确定类型的指针
在C和C++中,void*类型可以被强制转换成其他任意类型的指针
2.确定指针类型是为了告诉计算机该取多少连续的内存去读取一个数值。
26、- > 结构体指针运算符,用来访问结构体内部成员。
27、 PB3、4无法正常使用
//在系统复位的时候,PB3和PB4对应的功能默认为SYS_JTDO和SYS_NJTRST;
//要正常控制这两个引脚,就需要禁止掉这两个复用功能,在IO底层配置时,增加以下代码:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
//使能GPIOB时钟和复用功能(要先打开复用才能修改复用功能)
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
//要先开时钟,再重映射;这句表示关闭JTAG,使能SWD。
28、整型与整型的运算结果依然是整型,整型与浮点型的运行结果为浮点型。
29 、 在stm32端订阅的onenet话题 不会在产品中创建,需要借助调试助手订阅,才会创建,原因是MQTT的程序存在问题。
30、Flash 是电可擦除只读存储器的一种,其与EEPROM的区别在于,Flash擦除的区域以块为单位,EEProm是可以随机访问和修改任何一个字节
Flash用来做程序和一些掉电保护和不需修改的数据。
31、在C语言中
U表示该常数用无符号整型方式存储,相当于 unsigned int
L表示该常数用长整型方式存储,相当于 long
F表示该常数用浮点方式存储,相当于 float
17 typedef enum _gpio_pin_direction
18 {
19 kGPIO_DigitalInput = 0U, /* 输入 */
20 kGPIO_DigitalOutput = 1U, /* 输出 */
21 } gpio_pin_direction_t;
32、调试工具已经选择ST-link,但下载时报错,no jtag device found。修改Utilities中的调试工具为ST-Link。即可解决
33、电压要适配,工作电压范围很重要,使用电器时要注意。
1、RAM可以由CPU直接访问,而ROM不能
2、程序在运行时,所需的各种数据均需要从ROM读入进RAM后CPU才能执行程序
3、RAM区域分为5个区域,
1栈区(Stack):存储局部变量,栈区为栈,一种数据结构,具有先进后出的特点。
2堆区(Heap):程序员管理的区域,可以申请与释放内存,且申请到的实例均存储于此区域,使用完成后需要主动释放。
3全局区(Static):存储全局变量、静态变量,初始化的数据存于一片区域(.data),未初始化存于另一区域(.bss)。
4常量区:常量字符串等,const修饰的常量。
5代码区:程序运行时,会将代码指令复制到此区域。
且内存地址从高地址到低地址的顺序分配。栈区地址最高。
4、程序运行时,全局区、常量区、代码区均已固定,需要注意的是stack 和 heap的动态变化,保证能够访问到指定的区域,否则会出现程序崩溃的情况。
gcc test.c这样将编译出一个名为a.out的程序
gcc test.c -o test这样将编译出一个名为test的程序
-o参数用来指定生成程序的名字
我们一般用这个gcc text.c -o text命令。
text.c代表你的要操作的c语言文件,-o后面的代表你要给生成的exe的命名。
我们只需要知道这些。
//这个是可以进行转换和复原的,举例:
short x = -32752;//定义一个short
byte high = (byte) (0x00FF & (x>>8));//定义第一个byte
byte low = (byte) (0x00FF & x);//定义第二个byte
// 复原
short z = (short)(((high & 0x00FF) << 8) | (0x00FF & low));
#include
#include
int main(){
float angle;
unsigned char AngleH=0x86;
unsigned char AngleL=0xc7;
printf("input angleH = \n");
angle = (short)(((AngleH & 0x00FF) << 8) | (0x00FF & AngleL))/100.0;
printf("angle: %.3f",angle);
getchar();getchar();
return 0;
}
发现问题,
由于Python不是强类型的语言,对于数据的值的大小没有严格的限制,所以可以直接通过做减法来获得正确的负数值。如果是其他的强类型语言,就需要按照负数补码原理来获取到高位符号位值后再取反处理,获得正确的负数值。
def unpackage(data):
'''Python解包方法'''
'''由于Python不是强类型的语言,对于数据的值的大小没有严格的限制,所以可以直接通过做减法来获得正确的负数值。
如果是其他的强类型语言,就需要按照负数补码原理来获取到高位符号位值后再取反处理,获得正确的负数值。'''
list_2 = []
for i in range(len(data)):
data[i] = round(data[i], 2) # 用于规范数据位数,均限制在小数点后两位
data100 = int(data[i] * 100)
high_byte = ((data100 >> 8) & 0x00FF)
low_byte = (0x00FF & data100)
temp = (high_byte & 0x00FF) << 8 | (0x00FF & low_byte)
if temp > 32767:
temp = -(65536 - temp) / 100.0
else:
temp = temp / 100.0
list_2.append(temp)