推挽输出:VDD/VSS 13.3V/0V
开漏输出:VCC/VSS 5V/0V
复用的就用片上外设对GPIO进行控制
上拉输入:GPIO常高,典型应用是按键输入,按键按下GPIO被拉低
下拉输入:外界没有输入GPIO常低,
浮空输入:外部什么上下拉都断开,外部什么电平GPIO就是什么电平
模拟输入:TTL肖特基触发器关闭,外界输入什么信号,GPIO就是什么信号
提高部分
创建项目过程略过
启动文件为[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
我们可以通过其中的代码观察启动过程
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit //将系统初始化的地址传入r0
BLX R0
LDR R0, =__main
BX R0
ENDP
首先会将systeminit的地址传入R0然后跳转R0执行,接着将__main的地址传入R0并进行跳转,这个函数是由KEIL_MDK进行封装的我们无法跳转,但是这个main最终会调用我们自己写的main函数
-
为了cpu从flash取指令快一些,我们要打开Flash的预缓冲区
-
设置中断组别
-
用处很多,如果使用裸机,HAL的时钟源就是内核滴答定时器;如果是RTOS,那么RTOS用的内核滴答定时器,而HAL用其他时钟源
-
不设置的情况下,MCU工作在系统默认内部时钟
-
因为Flash被访问的速度是有限的,CPU访问速度远大于这个上限,所以要设置Flash等待周期,让CPU去等Flash读完或者写完,这一步就是根据我们的系统时钟来实现的,如果时钟很慢可能就不需要等待,如果时钟很快就需要去设置等待周期
-
这里面的前三步在上面的函数里已经集成了
-
系统时钟设置
-
设置总线时钟和外设时钟
FLatency就是设置Flash等待的参数在这里就可以找到,进入IS_FLASH_LATENCY
支持0、1、2个等待周期
根据手册中的说明,不同的时钟选择不同的状态
环形缓冲区的概念和实现
环形缓冲区的基本操作
环形缓冲区:申请内存空间
//写数据
#define BUFFER_SIZE 8
char ring_buf[BUFFER_SIZE];
int pW = 0;
ring_buf[pW] = data0;
pW = (pW + 1) % BUFFER_SIZE;
//读数据
#define BUFFER_SIZE 8
char ring_buf[BUFFER_SIZE];
int pR = 0;
ring_buf[pR] = data0;
pR = (pR + 1) % BUFFER_SIZE;
将前面的变量定义成结构体
#define BUFFER_SIZE 1024;
typedef struct
{
unsigned char buffer[UART_BUFFER_SIZE];
volatile unsigned int pW;
volatile unsigned int pR;
} ring_buffer;
判断缓冲区有没有数据
- 当写入未写满时候,判断pr和pw是否相等就可以了
- 当数据写满判断(pw+1) % buff_size == pr 如果相等说明写满了,丢弃掉将要写的数据
具体写代码的过程中遇到的问题:
buffer->fifo = (uint8_t*)malloc(size);
buffer->fifo[buffer->pw] = data;
经网上查阅
写代码的过程可以参考视频和写出来的代码文件
半主机模式参考手册
c库和microlib参考手册
半主机模式是ARM架构提出的一个概念和机制
它是一种用于ARM处理器或者模拟器与PC主机之间进行输入输出通信的一种机制。
这里的输入输出一般指的就是键盘输入和PC屏幕显示输出
且这个机制运行的环境必须是PC主机在运行一个ARM模拟器或者是PC主机已经和一个ARM处理器通过某种方式有通信连接,比如串口、网口、USB等。
比如我们可以使用C库里面的printf()函数和scanf()函数使处理器进行获取PC主机的键盘输入和屏幕显示而不是真的在处理器上连接一个键盘和显示器。
而对于C库,其本身是很庞大复杂的,我们没有对里面所有的内容都进行了解,只是针对于半主机模式和microlib进行了粗浅的认识
ARM处理器的模拟器使用的是半主机模式,我们无需添加某些头文件或者指令即可使用半主机模式中的一些接口或者命令,比如HLT、SVC、BKPT等;
但是那是适用于模拟器的,并不适用于一个实际的硬件开发板,因为大多情况下我们的开发板是不会接入一个键盘来获取数据的,
比如我们要实现的调试串口的驱动,我们希望调用printf函数来让UART输出数据,
我们需要重写fputc这个函数才行
microlib只适用于没有操作系统的嵌入式开发中
启动过程中调用main的过程
环形缓冲区在接收过程中的作用
WiFi模块ESP8266的驱动,其接口驱动也是UART驱动
UART发送指令给ESP8266,接收ESP8266返回来的字符串,判断字符串的内容来判断是否发送指令成功
我们在中断中处理接收到的数据,做了两个处理
一个是将接收到的数据保存到储存命令返回数据的环形缓冲区cmdretbuffer
另一个是将接收到的数据保存到储存网络接收数据的环形缓冲区netdatabuffer
之所以这样做,是因为作为一个串口接收方,其本身是无法判断到来的数据到底是命令返回的字符串还是网络接收数据
所以需要我们将这个数据进行两种方式的处理判断
关于解析ESP8266发来的网络数据
我们写了一个状态机
根据网络数据的格式分了三个阶段
第一个阶段是尝试解析和获取头部信息【+ipd】
第二个阶段是,在获取到完整的头部信息后,解析发来的数据个数,即len status
接收到“:”冒号表示数据个数的信息已经接收完了,根据ASCII字符的规则我们计算出了长度len
然后开始接收数据,来到了第三个阶段“接收数据阶段”data status
当接收了len个data后,我们就退出网络数据的接收解析,将数据保存到了缓冲区中。
以上内容来自于百问网7天物联网智能家居】训练营的视频或课件