1.五大区
2.数据类型
一维数组:int arr[i],int *p = arr; 则 arr[i] = p[i] = *(arr + i) = *(p +i)
二维数组:int arr[i][j] = int (*p)[j];则 arr[i][j] = p[i][j] = *(*(p+i)+j) = *(p[i]+j)
指针使用前必须有一个指向。32位:4字节 64位:8字节
指针作用:
指针可以用来传参(提高效率),返回值,指向结构体,数组。
使用字符串指针可以节约内存(只开辟一次)char *p;
使用指针数组存放可以存放多个地址(数组、变量、字符串) char *p[10];
使用函数指针可以指向一个函数 void (*p)(形参) = function1; //形参个数类型与指向的函数形参个数类型保持一致
使用函数指针数组可以存放多个函数地址 void (*p[10])(形参) = {function1,function2.......};
使用数组指针保存多个一维数组地址(连续的) char (*p)[10];
指针函数:函数返回值必须是局部静态变量,全局变量,动态开辟地址,指针地z址 。不能返回局部变量和指针指向局部变量的地址
5.结构体
常量指针:int const *p 指针内容不变,指向可变 int const *p == const int *p
单片机复位后,从0x08000004取出复位中断向量的地址,跳转到复位中断服务程序执行。执行完毕后运行main(while(1)),在执行main过程中收到中断请求,
STM32强制将PC指针指向中断向量表处,根据中断源执行执行相应的中断服务函数,执行完毕后返回main继续执行程序。
串行通信和并行通信
并行通信:多根线同时发送接受数据,通信速度快、距离短,成本高
串行通信:只用1-2根线,通信速度慢、距离段,成本低
同步串行:首同一时钟源控制,发送前约束同步字符
异步串行:不受同一时钟源控制。起始位+数据位+奇偶校验+停止位 先发低位
单工:只能单向传输
半双工:同一时刻只能收发
全双工:同一时刻可收可发
波特率:1s传输字符个数
串口主要用来调试和接收发送数据
串口接收发送数据:
1.空闲中断+接收中断
2.定时器中断+接收中断
3.dma搬运
IIC是飞利浦公司研发两线制串行同步半双工通信总线,通信速度(100k,400k,3.4M)
起始信号:SCL在高电平期间,SDA出现一个由高到低的跳变(SDA,SCL有最小保持时间 )
停止信号:SCL在高电平期间,SDA出现由低变高的跳变(SDA,SCL有最小保持时间 )
应答信号:SCL在高电平期间SDA始终处于低电平
非应答信号:SCL在高电平期间SDA始终处于高电平
应答/非应答产生于每个字节传输完毕后的下一个脉冲
读取数据:SCL拉高读取数据(模式切换)一位一位的加。
SCL在低电平的时候允许数据改变,高电平读数据
SDA线为高电平的时候可以被占用,SDA为低电平的时候表示总线被其他主设备占用。
开漏输出:防止多路、实现线与
IIC通信器件地址:4+3+1 0读1写 部分支持10位寻址
AT24C04:4Kbit,512字节,32页,一页16字节。写周期5ms,等待5ms后读取数据。跨页写要手动增,其余自增。
SHT20:SHT20 的分辨率可以通过输入命令进行改变,传感器可以检测到电池低电量状态,并且输出校验和,有助于提高通信的可靠性。有主机模式(SCL有传感器进行控制)和非主机模式(可以处理其他I2c任务)
总结:对于存储设备,一般是读写操作。注意数据覆盖、清除以及写周期等
对于测量设备,一般要编写软件复位、通电状态、器件参数设置、读写函数(时间问题)。
F10x系列有3个12位ADC模块。有18个通道,支持16个外部信号和2个内部信号(温度传感器,VREFINT--32内部参考电压) 。
最多支持16个规则通道和4个注入通道。同一时刻只能有一个通道工作。触发注入模式下,注入通道打断规则通道。自动注入模式下, 在转换完规则通道后自动转换注入通道。
外部触发模式:定时器触发、外部中断触发、软件触发(用户编写,会使得通道开始工作)----------上升沿启动转换
ADC工作频率由ADC分频器提供,最大不超过14MHZ.
ADC所有通道支持单次、连续(单次循环)、扫描(一个周期内转换多个通道)、间断模式(只转换第一个)。
ADC开关控制:断电模式或低功耗模式下,ADC使能称为ADC唤醒(需要延时tSTAB = 1us),再一次使能ADC则进入工作模式。清除ADC使能,ADC进入低功耗
ADC转换原理:ADC转换后的结果就是份数(模拟电压 / (参考电压/精度))
配置过程:选择通道对应引脚--模拟输入--配置四种工作模式--触发条件--数据存储方式--通道个数、顺序、采样周期--唤醒ADC--复位并校准,等待校准完成--触发模式(等待置1)--读DR寄存器。
SPI三线或者四线制,串行同步全双工
SPI通信速度最大是18MHZ。NSS为片选引脚:主模式当做GPIO口,只有当从器件才会使用。四种工作模式,有时钟极性和时钟相位决定
SPI是一个数据交换协议,发送一个数据必然收到一个数据。主机上升沿给数据,下降沿采样。上升沿采样,下降沿给数据。
SPI软件模拟和硬件驱动区别:
软件模拟:存数数据需要时间,速度较慢
硬件驱动:相同时种下,速度快软件模拟32倍,只需要等待标志位置变化就可以把1字节数据拿出来。
SPI | IIC | |
速度(MAX) | 18MHZ | 3.4MHZ |
与器件通信 | 拉低片选 | 地址通信 |
通信方式 | 串行同步全双工 | 串行同步半双工 |
CRC校验 | 硬件CRC | 无 |
传输数据大小 | 8或者16 | 8 |
传输顺序 | 高位或者低位在前 | 高位在前 |
连接器件 | 不使用菊花链模式下,每个器件需要额外引脚 | 挂载到1条总线 |
驱动方式 | 软件模拟、硬件驱动 | 软件模拟、硬件驱动 |
.
驱动器件:
查看器件支持哪种工作方式(时钟极性与时钟相位)
考虑通信速度是否兼容
传输位数与高位低位在前
操作寄存器需要拉高拉低片选,以及使能等
具有帧缓存空间,显存决定LCD分辨率不大,不会消耗MCU
8080协议(只负责数据传输):并行同步半双工。16根数据线,CS片选、WRLCD写、RD LCD读、D/C、
余下接口: RST、BL、T_MISO/T_MOSI/T_PEN/T_CS/T_CLK,触摸屏接口信号
使用过程:拉低片选----D/C高数据低命令----写(读)使能拉低----发送数据/命令----写使能拉高----片选线拉高
什么时候开始刷新、刷新几行、刷新结束
不带显存,由外扩RAM充当显存,显示控制器将SRAM的显存搬运到RGB接口屏
VSYNC(场同步信号线,每经历一个周期刷新一帧图像)、HSYNC(行同步信号线,每经历一个周期刷新一行图像)、VDEN(使能信号线)、VCLK、VD(24根数据线)
每过1个周期发送3个字节数据,频率越大,发送数据越快。
DMA 与CPU共用一条AHB总线,芯片内部有一个协调器,保证CPU至少占用一半以上AHB总线时钟
DMA支持存储器到外设、外设到存储器、存储器到存储器
DMA有软件优先级(4)和硬件优先级,软件优先级相同的时候根据硬件优先级(通道编号)
注意: DMA请求可以是硬件,也可以是软件DMA请求。
通道编号越小,优先级越高
支持8位、16位、32位传输
支持循环工作模式
中断源:传输过半、传输完成、传输错误
一个周期最大工作量是1-65535
DMA每次传输万一次数据,硬件-1
配置完DMA直接使能即可,DMA会自动搬运数据整个过程不需要CPU参与
存储器到外设:EPPROM->USART
配置串口与DMA,别忘了使能串口DMA请求
选择外设地址和内存地址
设置传输方向、缓冲区大小、
设置外设和存储器递增,传输模式、外设和存储器传输字节大小
设置优先级,Init DMA 某个通道
使能中断
传输数据:等待串口空闲(标志位)--使能DMA--设置传输缓冲区大小--开启DMA
DMA传输完成产生标志位--中断清除--向串口发送完成中断--串口中断清除标志位
系统定时器:24位倒计数器
外部时钟源--精确延时(72/8=9M) 内部时钟源--操作系统时机单元 (72M)
延时:
选择时钟源、清空、重载、开启
时基:
选择内部时钟、设置节拍数、开中断(中断++)(时间片/ucos)
时间片:抢占时间,通过TIME++值去判断任务轮训
UCOS:设置时间节拍、初始化ucos、创建起始任务(进入临界区、创建任务、退出临界区、挂起起始任务)、开启UCOS。跟线程处理一样
定时器:
时基单元:计数器(递增,递减,先增后减)、预分频器(时钟分频)、自动重装载寄存器
时钟源:内部时钟源、定时器级联、外部时钟模式1,外部时钟模式2
功能:提供DAC时钟、产生中断、DMA请求
延时:向计数器写值,开始定时模式,等待标志位
输入捕获:设置捕获寄存器,在某个跳变沿捕获,通过捕获中断判断状态值
输出比较:PWM模式、输出模式 延时20ms:预分频器分72000,即1s计数1000000,20ms/x = 1s/1000000 ==>x
PID:单片机使用离散PID,它是一个过程并不是瞬时的
比例控制P:尽快接近目标值,存在稳态误差。(对误差值就行乘积,越接近误差越小)
积分控制I:消除稳态误差。但是存在超调(误差累加)
微分控制:超前调节,减少响应时间(上一次误差与本次误差差值)
进程是系统分配资源的最小单位。系统创建进程会分配4G虚拟空间。---4G-3GPCB控制块,3G(向下增长的栈,库,向上增长的堆区,全局变量区(.data,.bss),文本常量区(readdata,text文本段))。
进程分为交互进程、批处理进程、守护进程。调度方法:高优先级调度、先来先调度、短进程优先、时间片轮训。
进程看似并发,有就绪态、休眠态、执行态
ps-aux:查进程占用的系统资源,比如物理内存、虚拟内存等
ps-axjf:查看进程详细信息
进程API:
pid_t getpid() 获取进程id
创建进程,子进程继承父进程虚拟地址,空间等。
fork ,vfork(共享数据区,先子后父--遇到exit,_exit,return 结束),system(创三代),execl函数族
wait与waitpid区别:waitpid可以不阻塞父进程(参数1:监听子进程范围,参数2:对子进程处理方式,参数3:子进程结束返回的状态)
_exit退出不清理缓冲区,atexit()注册清理退出函数
守护进程:周期执行某种任务或等待时间的发生 创建过程:使用fork创建子进程--退出父进程--使用setsid使子进程脱离--跳转到根目录--重设文件掩码--尽可能关闭文件描述符
僵尸进程:子进程先于父进程凋亡,父进程没有收回子进程资源。红帽存于init,ubuntu存于upstart. 解决办法:使用wait或waitpid
线程本质是进程,内核通过调用_clone函数,涉及多个进程,这些进程共享内存空间,文件属性
线程组成:线程id、PC指针、寄存器集合、堆栈。主线程堆栈不限增长,普通线程是2M
线程与进程区别:
线程是程序执行流最小单位、进程是系统分配资源最小单位
线程通信采用的是同一地址空间,进程通信用户空间--内核--用户空间
线程不如进程稳定,一个崩溃可能会全崩
线程空间属于统一进程下,进程空间是独立的
线程单main,多进程多main
线程API:
线程创建:pthread_create(存储线程id,分离属性,线程函数,线程传参)
线程退出:pthread_exit()
线程等待:pthread_join() 用于回收系统资源,指定线程没有退出的时候主线程会阻塞
获取线程id:pthread_self()
线程分离:pthread_detach() 用于回收系统资源,使用pthread_detach函数可以不阻塞主线程
线程同步机制:保证原子性、可见性、顺序性
互斥锁:
创建互斥锁:pthread_mutex_init()
加锁:pthread_mutex_lock
解锁:pthread_mutex_unlock
删除:pthread_mutex_destory
条件变量:
创建条件变量:pthread_cond_init
激活:pthread_cond_signal
等待:pthread_cond_wait
删除:pthread_cond_destory
注意:条件变量的使用必须与互斥锁连用。且使用pthread_cond_wait之前必须加锁,调用此函数会解锁,阻塞等待条件满足,再将锁设置为加锁,在调用unlock函数解锁
互斥灯:
创建信号灯:sem_init(信号灯,线程共用,值)
消耗信号灯:P操作 sem_wait
增加信号灯:V操作 sem_post
获取信号值:sem_getvalue
删除信号灯:sem_destory
osi七层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
tcp/ip四层:应用层、传输层、网络互联层、网络接口层
应用层:telnet、ftp协议。通过端口号区别不同的进程
传输层:tcp、udp协议
网络互联层:将数据封装成ip数据报,ICMP,IGMP,IPV4,IPV6
网络接口层:将数据转换为二进制流接收发送 ARP、RARP、MPLS
以太网帧:以太网首部+IP首部+TCP首部+应用数据(ARP)+以太网尾部
APR和RARP响应:局域网内通过MAC地址通信,非局域网:主机A以广播的形式发送ARP请求(包含B的ip地址),主机B收到请求后发现是A要寻找的主机,返回RARP响应(包含主机B的MAC地址)
TCP:
三次握手:客户端向服务器发送连接请求包SYN。服务器收到后回复连接请求确认包,同时发送连接建立询问包。客户端收到后向服务器发送连接建立确认包响应。
四次挥手:客户端发送FIN给服务器。服务器收到FIN后返回ACK,关闭自己的Receive通道,同时客户端收到ACK关闭自己的Send通道。服务器发送FIN给服务器,关闭连接。客户端收到FIN后返回ACK,关闭自己的Receive通道进入time_wait,服务器收到ACK后关闭自己的Send通道。
客户端编程:创建套接字--编写服务器信息(协议类型 ip 端口号)--连接服务器--读写--关闭
服务器编程:创建套接字--编写服务器信息(协议类型 ip 端口号)--将服务器信息与套接字进行绑定--监听--阻塞accept连接--关闭
异常断开:在关闭套接字的时候进行四次挥手,出现异常情况网络连接断开。可以使用keepalive或者应用层心跳包(服务器启动线程定时发送数据给客户端,检测客户端ack)
IPV4分类:A类政府、B中等规模公司、C个人、D组播、E实验
点分十进制计算:点分十进制算法:2345678988(HEX)----转成16进制----8BD0388C---每两位加一个.---8B.D0.38.8C-----每两位转换成十进制------139.208.56.140
子网掩码计算:写1,每八位数据转一个整数
UDP:
面向非连接,传输效率高,实时性高,安全性差
编程思路同上
UDP广播:UDP广播实质是客户端查找局域网内的服务器。客户端发送消息,服务器接收(反过来也可)
INADDR_BROADCAST:255.255.255.255
INADDR_ANY:0.0.0.0
内网穿透:
NAT映射:将同一网段的ip转换成一个共有ip,通过端口号区分不同的ip 优点:安全、节省ip 缺点:传输延迟、NAT进程增加CPU负担
TCP与UDP区别:
TCP | UDP | |
形式 | 打电话 | 发短信 |
传输效率 | 一般 | 快 |
传输安全性 | 高,经历三次握手四次挥手(打电话) | 扔数据,可能会丢帧(发短信) |
乱序(路径不同) | 算法纠正 | 无 |
丢包 | 三次重传(指数) | 快速重传与超市重传 |
传输方式 | 字节流 | 数据报(64K) 大于64k需要分片 |
一帧数据 | 最大1460字节 | 最大1472字节 |
无名管道:父子兄弟之间通信、int pipe 运行时才有
有名管道:任意进程通信,mkfifo()、unlink 具体磁盘中 用户进程--内核--内存---内核---用户进程
注意:双端同时存在才有意义,没数据读read阻塞,不读后64k满,读即清除
信号:2 中断 3:退出 9:杀死 14:闹钟
处理流程:内核发送中断--用户进程接收--中断服务函数
API:杀死kill 注册:signal(signalcation) 闹钟:alarm 设置信号传递闹钟:setitimer
注意:void (*signa(int num,void (*handler)(int)(int) 函数指针类型 可以用typedef void (*signal_t)(int)来代替返回值类型
共享内存:用户进程--内存---用户进程 保持key值相同可以多进程通信,管道只能两个进程
API:shmget创建、shmat映射、shmdt解除映射、shmctl删除
消息队列:消息类型+消息内容 管道是先进先出(基于字节流),消息队列同一类型先进先出(基于消息)
API:创建msgget、发送msgsend(结构体,第一个成员是long ,发送大小的时候要注意减掉)、接收msgrcv(数据接受最大8192)、删除msgctl
注:shell默认使用的是字符串。 {}取变量内容,()取命令内容,[]或(())算数运算
变量赋值、追加、拼接、清空
test=aaaa,test+=bbbb,test=${test}.ddd,unset test
单引号:不展开变量内容 双引号:展开变量内容
字符替换:匹配多个字符*.sh,匹配某个字符?.sh,匹配两个字符:??.sh
命令替换:test=${data} == test=`data`
转义字符:用于取出单个字符的意义
位置参数:$0 传参本身shell $1传参第一个参数 $#:传参个数 $?:存放上一次执行的结果 $$:进程号
输入输出:read test ,echo -n xxx:输出不换行 echo -e:解析转义字符
字符:lt 小于 gt 大于,eq等于 -z:字符串长度为0 -n:字符串长度非零
逻辑运算:! o a
循环语句:
if [ ];then
执行内容
elif [];then
执行内容
fi
case &变量 in
case1)
执行语句;;
case2)
执行语句;;
*)
执行语句
esac
for 循环(6种): ,(C语言格式),(python格式),(for A in 1 2 3 4),(for A in $()),(for A in ${a...z}),(for A in $buff)
while [ ]
do
执行内容
done
break,continue,exit
正则表达式:
【-】:匹配任意字符 ^:匹配行首 (放在【】表示匹配除了括号里的任意内容) \:转义
+ * {M,} {,N} {M,N}, \b:匹配单词开头或者结尾 \B:匹配费开头或者非结尾
【【: xxx:】】
fscanf:从一个流中格式化输入 fscanf(fp,"%s%d%lf",a,&b,&c)
sscanf:
sscanf("123456 ", "%4s", str);printf("str=%s\n", str);//str的值为1234
到指定字符为止的字符串。sscanf("123456 abcdedf", "%[^ ]", str);//注意^后面有一空格
取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。sscanf("123456abcdedfBCDEF", "%[1-9a-z]", str);
C语言与正则表达式:
编译正则表达式,regcomp
匹配正则表达式,regexec
释放正则表法式,regfree
make是一个工程管理器,能根据时间检测文件是否编译。
目标:依赖
规则
隐晦规则:$()或者${}
=延时展开,=:立即赋值,+=追加赋值,?=判断是否赋值
$@目标名称,$$ 输出¥,$^匹配所有目标,$<匹配目标第一个 与%连用模式匹配
伪目标:make -f 目标名
过程:加载makefile,展开include,变量初始化,推导隐晦分析所有,为目标创建依赖关系链,执行
$(patsubst %c,%o ,$( $filter-out $(filter) nodir $(wildcard))
静态库:ar-rc 1.a 1.o 使用的时候加载1.a
动态库:gcc -fpic -shared 1.o -o 1.so
软连接:ln -s 源.so 目标.so
硬链接:ln -P 源.so 目标.so
gdb -g 1.c gdb a.out
l:显示10行,l+行:上5下4
打断点:break 行号 -----run:执行到断点----n:执行一行(不进函数内部)----s:执行一行(进函数内部)----finish:结束该函数
查看断点:info b 删除断点:delete 调到指定行:util 跟踪变量值:display undisplay+n:取消对这个变量编号跟踪 undisplay:取消所有变量
修改变量表达式植:set var kill,结束本次 quit:退出gdb
预处理:gcc 1.c -E 1.i 宏定义的替换,头文件展开,条件编译
编译:gcc 1.i -S 1.s 检查语法错误,生成汇编文件
汇编:gcc 1.s -c 1.o 生成二进制流
链接:gcc 1.o -o 1.out s生成可执行文件
SELECT:1024文件描述符、遍历列表寻找活跃的文件描述符,内存拷贝,支持水平触发---------------数组
编写思路:将文件描述符添加到数组中FD_SET,SELECT监听(先拷贝一份),FD_ISSET轮训判断某个文件描述符发生动作
POLL:不限制文件描述符个数、需要内存拷贝,需要遍历列表,支持水平触发----------------------------链表
编写思路:将文件描述符信息添加到结构体数组,注册,使用POLL监听,轮训判断poll【i】.fd发生变化
EPOOL:不限文件描述符个数,epool在应用层和内核层之间建立一个简易的文件系统,映射至应用层和内核层,增加访问速度。支持水平和边缘触发(注意读写)------二叉树
编写思路:创建根节点,将文件描述符信息添加到结构体数组,注册,epoll判断就绪的文件描述符个数,根据fd/时间判断哪个描述符发生变化,
C++面向对象,C语言面向过程,更加灵活(例:string buff = " zifuchuan";)
输入输出:cin>>buffl; cout<
引用:引用只是别名,不占内存;引用不是一个具体的类型;引用在形式上是一个指针常量;不能返回局部变量的引用;引用必须在创建的时候初始化,一个变量可以有多个引用
引用做返回值:不产生副本 (左值) 引用做常量 (const int &a)
二义性:定义不写默认参数,声明写
函数重载:返回值类型、函数名、作用域相同,参数个数类型不同,不能传引用参数
extern C:以C语言风格编译
左值:表达式结束后任然存在的持久对象。++i : i++:会产生副本,增加代码运行时间
传值:内存在栈区拷贝一份相同的变量
传址:内存映射
传引用:传址(只是名不同)
对象是类的实例化,类指针不占大小。.在类中定义的变量不一定存储在全局静态存储区,要看在哪实例化。如果在main中实例化,那就存储在栈区。
面向过程:按部就班解决问题
面向对象:描述解决某个问题的整个行为。
通常只有短小的(1-5行)的代码会当做内联函数。
内联函数内不能有循环语句和开关语句,会当成普通函数使用
内联函数不能递归
结构体与类:默认权限不同,空类型大小不同。是否具备成员函数
类对象空间不是存储成员函数的指针,在实例化的时候将调用语句的成员函数用地址代替。
构造函数分为初始化阶段和构造阶段,在编写的时候不写返回值不写void,与类名一致,可以重载。只调用一次(编译器调用)
初始化阶段:初始化参数列表,解决const修饰的成员属性和引用问题
参数列表:赋值操作
C++默认会有无参构造、析构函数、浅拷贝
当有参构造后,默认调用浅拷贝,当拷贝后,不在执行其他构造
普通构造:括号法 A test(4); 显示法 A test() = A(4);隐式法A test() = 4;
拷贝构造:类名(const 类名 &a)浅拷贝(共享数据区),深拷贝(不同享数据区)
注意:const new必须深拷贝,浅拷贝不能与析构连用
值方式传参、值方式返回局部对象、已创建完毕的对象初始化一个新的对象会默认调用拷贝函数
静态成员:静态成员属性共享数据区(类外初始化),静态成员函数访问静态成员变量才有意义,作用域。
注意:静态成员函数没有this指针,类外初始化,不能声明为const 、virtual、volatile。
This指针:在非静态成员函数中返回对象本身
对象指针:比malloc更灵活:可以传参,自动计算大小,同时还可以自动执行构造函数