微机原理之MSP432——基础知识(什锦)

1.位运算

符号 描述 运算规则
& 两个位都为1时,结果才为1
| 两个位都为0时,结果才为0
^ 异或 两个位相同为0,相异为1
~ 取反 0变1,1变0
<< 左移 各二进位全部左移若干位,高位丢弃,低位补0
>> 右移 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)

2.RS232、TTL关系

内容来源于https://zhuanlan.zhihu.com/p/25893717

RS232通常出现在传统的PC和服务器领域,TTL通常用于嵌入式设备。

TTL全名是晶体管-晶体管逻辑集成电路(Transistor-Transistor Logic),这种串行通信,对应的物理电平,始终是在0V和Vcc之间,其中常见的Vcc是5V或3.3V。TTL 高电平1是>=2.4V低电平0是<=0.5V(对于5V或3.3V电源电压),这里是正逻辑

RS232接口的电平范围是**-15V到+15V。 在 单片机范围内,RS232由于没有负电源,所以使用非常规的接口电平0-5V**.如果需要和PC连接,需要进行电平转换成-15+15V才能被PC识别,逻辑1的电平为-3~-15V,逻辑0的电平为+3~+15V,注意电平的定义反相了一次。

RS232和TTL的时序对比:

RS232和TTL之间的转换,不仅仅是简单的电平转换,还要考虑到其他一些因素,比如调节和矫正一些电平(提高或降低对应的电平),确保可能的有害的RS232电压不会破坏微控制器的串口针脚。这里有很成熟的方案,我们可以通过MAX3232之类的芯片,把TTL电平转为RS232电平,或者简单的在淘宝购买TTL转RS232电缆即可。

MAX3232一端与单片机的引脚相连,另一端与RS232的串口相连,完成了TTL电平到RS232电平的转换。其原理图如下:

3.进制转换

3.1基数对照表

3.2十进制转二进制

十进制转二进制的转换原理:除以2,反向取余数,直到商为0终止。

3.3十进制转十六进制

十进制转二进制的转换原理:除以16,反向取余数,直到商为0终止。

4.嵌入式C语言improve

4.1 如何进入死循环

1
2
3
while(1)
{
}

4.2 do while 和 while 有什么区别

简而言之 do while 就是先执行do里面的内容再来判断是否符合条件,而while是先判断条件再执行花括号里面的内容。下面的例子一目了然。

1
2
3
4
5
6
7
8
9
10
11
//while
#include <stdio.h>
int main() {
int i = 0;
while (i < 0)
{
i++;
printf("%d\n", i);
}
return 0;
}
1
输出结果:无输出
1
2
3
4
5
6
7
// do while
int i = 0;
do
{
i++;
printf("%d\n", i);
}while (i < 0);
1
输出结果:1

4.3 定义变量

用变量a定义

  1. 一个整数型
  2. 一个指向整型数的指针
  3. 一个有10个整型数的数组
  4. 一个有10个指针的数组,该指针指向一个整型数
1
2
3
4
5
6
7
8
// 1.一个整型数
int a;
// 2.一个指向整型数的指针
int *a;
// 3.一个有10个整型数的数组
int a[10];
// 4.一个有10个指针的数组,该指针指向一个整型数
int *a[10]

4.4 关键字static的作用是什么

static有三种不同的用法

1.修饰局部变量,2.修饰全局变量,3.修饰函数

1.当我们用static修饰局部变量,那么这个变量在函数调用完之后不会被释放

2.当我们用static修饰全局变量,我们知道全局变量在不同的源文件中是可以使用的,只不过需要先用extern外部声明一下。但是当我们用static修饰时那么被修饰的变量只能在当前.c文件中访问

3.当我们用static修饰函数,那么被修饰的函数只能在当前.c文件中中访问

4.5 关键字const的作用是什么

const修饰的东西无法修改。(常量)

const常量与#define有本质上的区别,#define本质上是文本替换

4.6 定义一个标准宏MIN,这个宏输入两个参数并返回较小的一个

上面我们说过,宏定义本质上是文本替换,那么我们只要把他替换成函数不就行了?

宏的替换规则:
1.在调用宏的时候,首先检查参数,看看是否包含任何由#define定义的符号,如果是,首先它们被替换。

2.替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。

3.最后再次对结果文件进行扫描,看着它是否包含任何由#define定义的符号,如果是,就重复上述处理。

1
#define MIN(A,B) ( (A)<=(B)?(A):(B) )

4.7 寄存器位操作,给一个int变量a,将a的bit3置为1或0,并保证其他位不变

先说思路,先用位操作将0x01左移3位并赋值给BIT3,然后我们紧抓其他位不变的条件

将a与BIT3做按位或操作即可将a的bit3置为1且其他位保持不变

将a与~BIT3做按位与操作即可将a的bit3置为0且其他位保持不变

1
2
3
4
5
6
7
8
9
10
#define BIT3  (0x1<<3)
static int a;
void set_bit3(void)
{
a|=BIT3;
}
void clear_bit3(void)
{
a &=~BIT3;
}

4.8 设置0x5a00的整型变量值为0xaa55

首先将0x5a00转换为地址复制给指针

然后对指针所对应的值进行修改

1
2
int *ptrTemp = (int *)0x5a00;
*ptrTemp = 0xaa55;

c

4.9 下面代码输出是什么

1
2
3
4
5
6
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b>6)?puts(">6"):puts("<6");
}

输出结果:>6

有符号数与无符号数进行运算时,有符号数先自动转换成无符号数。

1
2
3
4
5
6
#include <stdio.h>
int main()
{
int a = -20;
printf("%u", a);
}

输出结果:4294967276

4.10 评论下面代码

1
2
3
4
5
6
void test()
{
char string[10];
char *str = "0123456789";
strcpy(string,str);
}

这段代码会报错,因为string数组只能存放10个字节,而str有11个字节(字符串要加个\0)

4.11 评论下面代码

1
2
3
4
5
6
7
8
9
10
11
void GetMemory(char *p)
{
p = (char *)malloc(0x20);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str,"Hello World!");
printf(str);
}
  1. 调用GetMemory( str )后, str并未产生变化,依然是NULL.只是改变的str的一个拷贝的内存的变化

  2. strcpy( str, “hello world” );程序运行到这将产生错误。

4.12 评论下面中断回调函数

1
2
3
4
5
6
_interrupt double compute_area(double radius)
{
double area = PI * radius * radius;
printf("\nArea = %f", area);
return area;
}

中断最好不要有返回值,最好不要传入参数,最好不要用printf,要保证中断是短而有效率的

5.C语言基础

5.1 循环和分支

5.1.1 循环语句

  1. for循环

    1
    2
    3
    4
    5
    6
    7
    for(init; test; update)

    {

    body;

    }
  2. while循环

    1
    2
    3
    4
    5
    6
    7
    while(test)

    {

    body;

    }
  3. do while

    1
    2
    3
    4
    5
    6
    7
    do

    {

    body;

    }while(test)

循环辅助

break; //跳出循环

continue; //跳出本次循环

5.1.2 if语句

1
2
3
4
if(test)
{
body;
}
1
2
3
4
5
6
7
8
9
if(test)
{
body;
}

else
{
body;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(test)
{
body;
}

else if(test)
{
body;
}

else
{
body;
}

5.1.3 三元运算符

1
Exp1 ? Exp2 : Exp3;

5.1.4 switch语句

1
2
3
4
5
6
7
8
9
10
11
switch(exp)

{

case const1 : statements; break;

case const2 : statements; break;

default : statements; break;

}

注意:switch判断表达式必须是整数值,case标签必须是整数常量或常量表达式、字符,不能是变量

5.2 作用域与存储类

5.2.1 作用域

代码块作用域(局部变量)

代码块:包含在开始花括号和对应结束花括号之内的代码

作用域:从定义变量位置到该代码块的末尾

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main()
{
itemp++;
int itemp = 10; // 这个itemp变量的作用域是从这里开始到return0;也就是说前面的itemp++不会执行
itemp--;
return 0;
}

文件作用域(全局变量——多文件编程)

文件作用域:在所有函数之外定义的变量具有文件作用域

作用域:从定义变量位置到包含该定义文件的结尾处。在其他位置使用该变量应用extern来声明该变量

函数也是同理所以下面直接用函数的例子

1
2
3
4
5
6
7
8
9
10
// c源文件 func.c
int Max(int num1, int num2)
{
int max = num1;
if(max < num2)
{
max = num2;
}
return max;
}
1
2
3
4
5
// 头文件 head.h
#ifndef C_IMPROVE_HEAD_H
#define C_IMPROVE_HEAD_H
extern int Max(int num1, int num2);
#endif //C_IMPROVE_HEAD_H
1
2
3
4
5
6
7
8
#include <stdio.h>
#include "head.h"
int main() {
int num1 = 10;
int num2 = 20;
printf("%d",Max(num1, num2));
return 0;
}

5.2.2 存储时期

自动存储期 静态存储期
生成 程序执行到对象声明的时候创建出相应的对象 在程序执行开始执行的时候被创建出来
初始化 如果不显示地进行初始化,则该对象会被初始化为不确定的值 如果不显示地进行初始化,则该对象会被初始化为0
消失 执行到包含该声明的程序块的结尾时,该对象就会消失 在程序结束的时候消失

5.2.3 存储类

存储类 时期 作用域 链接 声明方式
自动 自动 代码块 代码块内
寄存器 自动 代码块 代码块内,使用关键字register
具有外部连接的静态 静态 文件 外部 所有函数之外
具有内部连接的静态 静态 文件 内部 所有函数之外,使用关键字static
空连接的静态 静态 代码块 代码块内,使用关键字static

5.3 内存与指针

5.3.1 指针

无论是什么类型的指针他所占的内存空间都是四个字节