知识点1【概念补充】
1、CPU概念:中央处理器
中央处理器(central processing unit)作为计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元。
内核
2、MCU概念:微控制单元
微控制单元(Microcontroller Unit),又称单片机微型计算机或者单片机,是将中央处理器(CPU)的频率与规格做适当缩减,并将内存、计数器、USB、A/D转换、USB、A/D转换、UART、PLC、DMA等周边接口,甚至LCD驱动电路都整合在单一芯片上,形成芯片级的计算机,为不同的应用场合做不同组合控制。
MCU—>单片机—>单核的CPU
目前比较新的单片机 中也有多核的
3、嵌入式
嵌入式系统是以应用为中心,以现代计算机技术为基础,能够根据用户需求(功能,可靠性,成本,体积,功耗,环境等)灵活裁剪软硬件模块的专用计算机系统
嵌入式:软硬件结合 软硬件和裁剪
4、物联网
最简洁明了的定义:物联网(Internet of Things)是一个基于互联网,传统电信网等信息承载体,让所有能够单独寻址的普通物理对象实现互通互联的网络。它具有普通对象设备化、自治终端互联化和普适服务智能化3个重要特征。
物联网包括嵌入式。更准确来说,嵌入式是物联网技术的一种具体实践方式。
万物互联
知识点2【MCU的组成】
ARM公司:主要是设计处理器架构的
ST(意法半导体)公司:获取架构的版权后,设计芯片
台积电:生产芯片
知识点3【软件安装】
之前学习单片机使用的VS code,VIM……
编写单片机的代码,需要使用KEIL5工具
我们这里使用的版本是MDK529
注意:安装的过程中,不要包含中文路径
1、安装keil5的步骤
下面这个界面 随便填写
2、破解keil5的步骤
知识点4【STM32F103ZE】
1、STM32 的命名规则
2、GPIO的输入输出模式
忽略我的标注
1、输出模式
**开漏输出:**本身没有驱动能力,无法输出高电平,如果想要输出高电平,需要外界电路。
开漏的好处,本身不驱动,依赖外部电路,当内部电路电压无法满足外界原件的时候,就需要开漏输出借助外部电路来提高驱动能力
**推挽输出:**有一定的驱动能力,内部既可以输出低电平,也可以输出高电平
**复用推挽:**除了通用IO口输出高低电平的第二功能,都是复用推挽
**复用开漏:**除了通用IO口输出低电平的第二功能,都是复用开漏
2、输入模式
模拟输入:主要使用于AD转换中
上拉输入:管脚默认是高电平,电路内部是弱上拉
下拉输入:管教默认是低电平,电路内部是强下拉
浮空输入:管教既不连接上拉电阻,也不连接下拉电阻,状态不确定。但在32中由于强下拉的原因,呈现低电平
3、寄存器控制IO
1、统一步骤
1、配置时钟
2、配置端口输入输出的模式
3、控制端口
2、操作寄存器的方式
改变其中一位,使用
按位与将特定位置0:与1不变,与0为0
按位或将特定位置1:或0不变,或1位1
4、寄存器配置详解
以配置LED0为例,即配置PB5
1、配置时钟
时钟的概念
时钟在我们的单片机中主要起到计数的作用,代表系统运行的速度快慢
强调:每一个PA,PB,PC(每个端口)…….他们都有各自独立的时钟
1、根据上图选时钟源
2、选完时钟后查手册
这里以配置GPIOB 时钟为例
RCC_APB2ENR |= (0x01 << 4);
将IOPB位置1
2、配置端口输出\输入模式
依旧查表
下面介绍一下 上面是如何配置 输出\输入模式的:
根据 MODE配置管脚是输入还是输出
1、输出
MODE ≠ 0,其余三个模式没有什么特别大的区别,我们这里选择01
选择好MODE后,来选择CNF,我们根据需求,可以知道推挽模式更适合我们,因为LED0无外界电路,且 选择的是GPIOB5 的通用端口。
最终确定我们需要将23 - 20 依次配置为 0010
这里我建议的配置步骤是:先将这四位全部清0,清0后再执行特定位置1操作。
GPIOB->CRL &= ~(0x0f << 20);
GPIOB->CRL |= (0x01 << 20);
2、输入
MODE = 0
选好MODE后,来选择CNF。
这里不多讲配置过程,我想说一下 大家可能在配置按键时的疑惑:
可以看到 下拉和下拉模式都是一个CNF,如何区分呢?
这里我给大家提供方案:
GPIOE->CRL &= ~(0x0f << 16);
GPIOE->CRL |= (0x08 << 16);
GPIOE->ODR |= (1 << 4);//上拉
//下拉则是将这个端口置0
3、配置管脚
在这两个文档里,大家自行查看吧,没什么注意事项,认真就好。
while(1)
{
//LED0 亮
GPIOB->ODR &= ~(0x01 << 5);
//LED1 灭
GPIOE->ODR |= (0x01 << 5);
Delay_1ms(500);
//LED0 灭
GPIOB->ODR |= (0x01 << 5);
//LED1 亮
GPIOE->ODR &= ~(0x01 << 5);
Delay_1ms(500);
}
补充延时函数:
void Delay_1ms(uint32_t ms) {
SysTick->LOAD = 72000 - 1; // 72MHz/1000 = 72000 cycles/ms
SysTick->VAL = 0; // 清空计数器
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
while(ms--) {
while( !(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) ); // 等待计数完成
}
SysTick->CTRL = 0; // 可选:关闭SysTick
}
4、代码演示
#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h>
void Delay_1ms(uint32_t ms);
void LED();
void beep();
int main(void)
{
//配置按键时钟
RCC->APB2ENR |= (0x01 << 6);
//配置按键0 输入模式
GPIOE->CRL &= ~(0x0f << 16);
GPIOE->CRL |= (0x08 << 16);
GPIOE->ODR |= (1 << 4);
//配置按键1 输入模式
GPIOE->CRL &= ~(0x0f << 12);
GPIOE->CRL |= (0x08 << 12);
GPIOE->ODR |= (1 << 3);
//配置按键2 输入模式
GPIOE->CRL &= ~(0x0f << 8);
GPIOE->CRL |= (0x08 << 8);
GPIOE->ODR |= (1 << 2);
//配置按键触发功能
while(1)
{
if((GPIOE->IDR & (0x01 << 4)) == 0)
{
//按键0
Delay_1ms(20);
if((GPIOE->IDR & (0x01 << 4)) == 0)
{
while((GPIOE->IDR & (0x01 << 4)) == 0);
LED();
}
}
//按键1
if((GPIOE->IDR & (0x01 << 3)) == 0)
{
Delay_1ms(20);
if((GPIOE->IDR & (0x01 << 3)) == 0)
{
while((GPIOE->IDR & (0x01 << 3)) == 0);
beep();
}
}
//按键2
if((GPIOE->IDR & (0x01 << 2)) == 0)
{
Delay_1ms(20);
if((GPIOE->IDR & (0x01 << 2)) == 0)
{
while((GPIOE->IDR & (0x01 << 2)) == 0);
}
}
}
}
//走马灯函数
void beep()
{
//打开GPIOB的时钟
RCC->APB2ENR |= (0x01 << 3);
//配置GPIOB8端口输出模式:推挽输出 BEEP
GPIOB->CRH &= ~(0x0f << 0);
GPIOB->CRH |= (0x01 << 0);
//配置端口
GPIOB->ODR |= (0x01 << 8);
Delay_1ms(1000);
GPIOB->ODR &= ~(0x01 << 8);
}
void LED()
{
//配置时钟
RCC->APB2ENR |= (0x0001 << 3);
RCC->APB2ENR |= (0x0001 << 6);
//配置GPIOB5端口模式:推挽输出 LED0
GPIOB->CRL &= ~(0x0f << 20);
GPIOB->CRL |= (0x01 << 20);
//配置GPIOE5端口模式:推挽输出 LED1
GPIOE->CRL &= ~(0x0f << 20);
GPIOE->CRL |= (0x01 << 20);
//配置端口
while(1)
{
//LED0 亮
GPIOB->ODR &= ~(0x01 << 5);
//LED1 灭
GPIOE->ODR |= (0x01 << 5);
Delay_1ms(500);
//LED0 灭
GPIOB->ODR |= (0x01 << 5);
//LED1 亮
GPIOE->ODR &= ~(0x01 << 5);
Delay_1ms(500);
if((GPIOE->IDR & (0x01 << 4)) == 0)
{
//按键0
Delay_1ms(20);
if((GPIOE->IDR & (0x01 << 4)) == 0)
{
while((GPIOE->IDR & (0x01 << 4)) == 0);
//LED0 灭
GPIOB->ODR |= (0x01 << 5);
//LED1 灭
GPIOE->ODR |= (0x01 << 5);
break;
}
}
}
}
void Delay_1ms(uint32_t ms) {
SysTick->LOAD = 72000 - 1; // 72MHz/1000 = 72000 cycles/ms
SysTick->VAL = 0; // 清空计数器
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
while(ms--) {
while( !(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) ); // 等待计数完成
}
SysTick->CTRL = 0; // 可选:关闭SysTick
}
知识点5【代码中遇到的问题】
1、构建和下载程序中出现的问题
2、检查ST Link驱动是否有效
如果遇到驱动没办法正常连接的可以管我要一下驱动文件。
3、时钟理解错误
代码错误:每一个IO块(A,B,C……)都有自己的时钟,知识点遗忘导致忘记配置GPIOE的时钟
学一下使用VS code 写代码
结束
代码重在练习!
代码重在练习!
代码重在练习!
今天的分享就到此结束了,希望对你有所帮助,如果你喜欢我的分享,请点赞收藏加关注,谢谢大家!!!