目录
1. 灯如何才能亮
1.1原理图
1.2 二极管
1.3 换了一个灯和原理图
编辑
1.4 三极管
1.4.1 NPN型三极管
1.4.2 PNP型三极管
2. 基本概念
3. 输入
3.1 浮空输入
3.2 上拉输入
3.3 下拉输入
3.4 模拟输入
4. 输出
4.1 推挽输出
4.2 开漏输出
如何让开漏输出高电平?
5. 相关寄存器
5.1 寄存器定义与作用
5.2 控制某一引脚输出电压来点灯所需要控制的寄存器
5.3 配置时钟使能寄存器
5.4 GPIO配置寄存器
5.4.1 端口模式寄存器
5.4.2 输出类型寄存器
5.4.3 输出速度寄存器
5.4.4 上下拉寄存器
5.4.5 输入数据寄存器
5.4.6 输出数据寄存器
5.5 让PC13引脚输出高电平
5.6 寻找寄存器地址--定位
6. 开始点灯
6.1 C语言点灯
位操作
6.2 新建项目
6.2.1 引脚配置
6.2.1 生成项目
6.2.4 代码分析
6.2.5 库函数分析
6.2.6 闪灯实验
7. 底板与拓展板
7.1 底板
7.2 显示屏与资源拓展板
7.2.1 显示屏
7.2.2 资源拓展板
8. 原理图
8.1 LD1这个灯连到了哪个引脚?
9. 按键
按键消抖
9.1.1 延时消抖
9.1.2 抬手检测
10. 光电开关(任务分析)
10.1 原理
10.2光电开关控制风扇
注意:单片机部分笔记的学习主要围绕STM32U575RIT系列芯片和华清远见学习开发板展开。
开发板软件安装包和原理图等资料连接:
通过网盘分享的文件:单片机
链接: https://pan.baidu.com/s/1gE3Mnl_MF0q667iqQ51IuA?pwd=mv5s 提取码: mv5s
1. 灯如何才能亮
1.1原理图
灯亮需要电流,产生电流需要电势差
单片机的电源3.3V —— + LED - —— 1.0V(单片机上比3.3V低的接口)
1.2 二极管
二极管就是由一个PN结加上相应的电极引线及管壳封装而成的
特点:正向导通,反向截止
记忆:将此符号看作一个箭头,顺着箭头的方向,电压降低才导通(压差最小为0.7v),否则相当于电阻无穷大。
有一种二极管在其导通时可以发光,这种二极管叫做发光二极管(Light Emitting Diode)
我们常说的LED,就是二极管。
1.3 换了一个灯和原理图
1.4 三极管
三极管有两种类型,PNP和NPN型。
1.4.1 NPN型三极管
基极高电平导通
1.4.2 PNP型三极管
基极低电平导通
D1灯亮,需要二极管左端为低电平
三极管导通,GND和D1左端导通,即D1左端拿到低电平,灯亮。
此三极管为NPN型三极管,当PC13为高电平时,三极管导通。
即PC13输出高电平,D1灯亮。
不难看出,此处三极管相当于一个简易的开关。
2. 基本概念
GPIO(General-purpose input/output)通用输入输出接口
--GP 通用
--I input 输入
--O output输出
GPIO,General Purpose Input Output,指的是芯片的通用输入输出引脚。
通过配置对应引脚的输出模式,我们可以进行LED灯的点亮,继电器的开闭控制;
在输入模式下,读取按键开关的状态,模拟输入状态下,我们可以读取温湿度传感器的数据。
除了以上使用情况,也可以作为I2C,SPI,串口的引脚等。
问:VDD、VSS、VCC分别表示什么意思?
VCC:C=circuit,表示电路的意思,即接入电路的电压。
VDD:D=device,表示器件的意思,即器件内部的工作电压。
VSS:S=series,表示公共连接的意思,通常指电路公共接地端电压。
VCC :接入电路的电压 外部参考高电平3.3,
VDD : 元器件内部的工作电压,内部参考高电压,stm32中为3.3v
VSS : 公共接地端电压,内部参考地,stm32中为0v
施密特触发器:整形
3. 输入
3.1 浮空输入
上下拉都关闭
好处:其电平完全由外部决定
不好:当引脚没有外接电路的时候,其电平信号是不确定的,不确定的信号会影响程序的正常判断
3.2 上拉输入
打开上拉,关闭下拉
好处:提供了一个默认电平,当外部电路不确定的时候,提供了一个默认的高电平。
当外部输入低电平时,输入的还是低电平
当外部输入高电平时,输入的是高电平
3.3 下拉输入
打开下拉,关闭上拉
好处:提供了一个默认电平,当外部电路不确定的时候,提供了一个默认的低电平。
当外部输入低电平时,输入的还是低电平
当外部输入高电平时,输入的是高电平
3.4 模拟输入
4. 输出
4.1 推挽输出
P-MOS、N-MOS都能用
输出高电平
在输出数据寄存器对应引脚位置写1--->数据选择器选择上路--->输出控制器给P-MOS和N-MOS都输出高电平--->P-MOS导通,N-MOS截止--->高电平由Vdd提供
输出低电平
在输出数据寄存器对应引脚位置写0--->数据选择器选择上路--->输出控制器给P-MOS和N-MOS都输出低电平--->N-MOS导通,P-MOS截止--->低电平由Vss提供
4.2 开漏输出
P-MOS关闭
输出低电平
在输出数据寄存器对应引脚位置写0--->数据选择器选择上路--->输出控制器给P-MOS和N-MOS都输出低电平--->N-MOS导通,P-MOS截止--->低电平由Vss提供
本身无法输出高电平
在输出数据寄存器对应引脚位置写1--->数据选择器选择上路--->输出控制器给P-MOS和N-MOS都输出高电平--->P-MOS关闭,N-MOS关闭--->电路处于高阻态
由上可得:开漏本身无法输出高电平
如何让开漏输出高电平?
1. 打开内部上拉电阻
2. 外接上拉电阻
好处:提供的电压由用户决定,想提供高电压,把外界上拉电阻的电压源提高即可。
5. 相关寄存器
5.1 寄存器定义与作用
为什么要学习寄存器,寄存器的作用是什么?
答:
- 寄存器是单片机内部的一些存储单元
- 单片机的设置和寄存器直接关联,比如输出模式,比如输入输出的电压,比如上下拉电阻是否打开,所以,想要对单片机进行设置就是对寄存器进行改写的过程。
5.2 控制某一引脚输出电压来点灯所需要控制的寄存器
- 时钟开关,总开关
- 端口模式寄存器--输出模式
- 输出类型寄存器--推挽
- 输出速度寄存器--非常慢
- 上下拉寄存器 --既不上拉也不下拉
- 输出数据寄存器 --1
5.3 配置时钟使能寄存器
思路:
我们的目的是使用PC13,所以要先打开C引脚组时钟。
通过寻找内存架构找到了RCC相关的寄存器组,RCC寄存器组里的寄存器太多了。
找到控制引脚组的RCC寄存器需要找到GPIO属于哪个总线上的(AHB1\APB1\APB2\PHB2等),通过查内存分配架构图可知,GPIO在AHB2总线上,所以,我们定位到了RCC_AHB2ENR1
RCC AHB2 peripheral clock enable register 1 (RCC_AHB2ENR1)
打开C组,就可以使用PC13
RCC_AHB2ENR1第2位写1
5.4 GPIO配置寄存器
5.4.1 端口模式寄存器
GPIO port mode register (GPIOx_MODER) (x = A to J)
PC13为输出模式
GPIOC_MODER第27、26位写0,1
5.4.2 输出类型寄存器
GPIO port output type register (GPIOx_OTYPER) (x = A to J)
PC13推挽模式
GPIOC_OTYPER 第13位写0
5.4.3 输出速度寄存器
GPIO port output speed register (GPIOx_OSPEEDR) (x = A to J)
PC13低速输出
GPIOC_OSPEEDR 第27、26位写 0 0
5.4.4 上下拉寄存器
GPIO port pull-up/pull-down register (GPIOx_PUPDR) (x = A to J)
PC13都不拉
GPIOC_PUPDR 第27、26位写 0 0
5.4.5 输入数据寄存器
GPIO port input data register (GPIOx_IDR) (x = A to J)
5.4.6 输出数据寄存器
GPIO port output data register (GPIOx_ODR) (x = A to J)
PC13输出高电平
让GPIOC_ODR第13位写1
5.5 让PC13引脚输出高电平
- 打开时钟:RCC_AHB2ENR1 给第2位写1
- 配置端口模式寄存器 配置为输出模式 GPIOC_MODER 第27、26位写 0 1
- 配置输出类型寄存器 配置为推挽输出 GPIOC_OTYPER 第13位写0
- 配置输出速度数据寄存器 配置为很低 GPIOC_OSPEEDR 第 27、26位写 0 0
- 配置上下拉寄存器 配置为既不用上拉也不下拉 GPIOC_PUPDR 第27、26位写0 0
- 配置输出数据寄存器 给PC13引脚写1 GPIOC_ODR 第13位写1
5.6 寻找寄存器地址--定位
0x56020C00是RCC寄存器组的基地址
偏移地址,相对于基地址--RCC寄存器组的起始地址
RCC_AHB2ENR1地址为:0x56020C00+0x08C=0X56020C8C
GPIOC寄存器组的基地址为0x5202 0800
GPIOC_MODER : 0x5202 0800+0X00=0x5202 0800
GPIOC_OTYPER : 0x5202 0800+0X04=0x5202 0804
GPIOC_OSPEEDR : 0x5202 0800+0X08=0x5202 0808
GPIOC_PUPDR :0x5202 0800+0X0C=0x5202 080C
GPIOc_ODR :0x5202 0800+0X14=0x5202 0814
6. 开始点灯
6.1 C语言点灯
void SystemInit(void)
{
*(unsigned int*) 0xE000ED88|=((3UL << 20U)|(3UL << 22U));
}
int main(void)
{
}
记得使用微型C库,不勾的话可能会影响效果
如果报了两个未知错误,可尝试调整优化
烧录前一定将烧写器调成STLINK
位操作
精准置1
x|1=1;
x|0=x;
故将不希望改变的位和0相或,将希望置1的位和1相或即可。
使第26位置1,可通过让整个寄存器和1<<26相或再赋值得到,寄存器 |= (1<<26)
精准置1
x|1=1;
x|0=x;
故将不希望改变的位和0相或,将希望置1的位和1相或即可。
使第26位置1,可通过让整个寄存器和1<<26相或再赋值得到,寄存器 |= (1<<
void SystemInit(void)
{
*(unsigned int*) 0xE000ED88|=((3UL << 20U)|(3UL << 22U));
}
int main(void)
{
//RCC_AHB2ENR1地址为:0x56020C00+0x08C=0X56020C8C
//GPIOC_MODER : 0x5202 0800+0X00=0x5202 0800
//GPIOC_OTYPER : 0x5202 0800+0X04=0x5202 0804
//GPIOC_OSPEEDR : 0x5202 0800+0X08=0x5202 0808
//GPIOC_PUPDR :0x5202 0800+0X0C=0x5202 080C
//GPIOc_ODR :0x5202 0800+0X14=0x5202 0814
*(unsigned int *)0X56020C8C |= (1<<2);
*(unsigned int *)0x52020800 |= (1<<26);
*(unsigned int *)0x52020800 &= ~(1<<27);
*(unsigned int *)0x52020804 &= ~(1<<13);
*(unsigned int *)0x52020808 &= ~(3<<26);
*(unsigned int *)0x5202080C &= ~(3<<26);
*(unsigned int *)0x52020814 |= (1<<13);
while(1);
}
void SystemInit(void)
{
*(unsigned int*) 0xE000ED88|=((3UL << 20U)|(3UL << 22U));
}
void delay(int T);
typedef struct{
unsigned int MODER;
unsigned int OTYPER;
unsigned int SPEED;
unsigned int PUPDR;
unsigned int IDR;
unsigned int ODR;
}GPIO;
#define GPIOC (*(GPIO *)0x52020800)
#define RCC_AHB2ENR1 *(unsigned int *)0x56020C8C
int main(void)
{
RCC_AHB2ENR1 |= 1<<2;//配置RCC_AHB2ENR1的第2位置1,打开时钟
GPIOC.MODER |= 1<<26;//GPIOC_MODER 的第26位置1,配置输出
GPIOC.MODER &= ~(1<<27);//GPIOC_MODER 的第27位置0,配置输出
GPIOC.OTYPER &= ~(1<<13);//GPIOC_OTYPER 的第13位置0,配置推挽
GPIOC.SPEED &= ~(3<<26);//GPIOC_OSPPEDR 第27、26位置0
GPIOC.PUPDR &= ~(3<<26);//GPIOC_PUPDR 第27、26位置0
GPIOC.ODR |= 1<<13;//GPIOC_ODR 第13位置1
while(1)
{
GPIOC.ODR |= 1<<13;//GPIOC_ODR 第13位置1
delay(1000);
GPIOC.ODR &= ~(1<<13);//GPIOC_ODR 第13位置0
delay(1000);
}
}
void delay(int T)
{
int a,b;
for(a=0;a<T;a++)
for(b=0;b<100;b++);
}
6.2 库函数点灯
6.2 新建项目
6.2.1 引脚配置
打开烧录口
6.2.1 生成项目
6.2.4 代码分析
双击main.c文件,找到,我们可以查看MX_GPIO_Init();的内容以了解CubeMX帮我们生成了的初始化内容,选中MX_GPIO_Init();后按下F12或鼠标右键,选择Go To Definition of...。
6.2.5 库函数分析
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
功能: 设置或清除指定的端口位
参数:GPIO_TypeDef *GPIOx 端口号
uint16_t GPIO_Pin 引脚号
GPIO_PinState PinState 电平状态
GPIO_PIN_SET 1
GPIO_PIN_RESET 0
返回值:无
void HAL_GPIO_TogglePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin)
功能: 切换指定的引脚电平状态
参数:GPIO_TypeDef * GPIOx 端口号
uint16_t GPIO_Pin 引脚号
返回值:无
GPIO_PinState HAL_GPIO_ReadPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin)
功能: 读取指定的引脚电平状态
参数:GPIO_TypeDef * GPIOx 端口号
uint16_t GPIO_Pin 引脚号
返回值:GPIO_PinState 电平状态
GPIO_PIN_RESET 0
GPIO_PIN_SET 1
HAL_Delay()单位毫秒
点灯
6.2.6 闪灯实验
7. 底板与拓展板
7.1 底板
STM32 开发板底板,支持 5V 电源适配器与 TypeC 供电。
提供 RTC 时钟电源,提供三轴加速度与角速度传感器,用于姿态感知。
板载 ESP-12F 无线模组,用于物联网云平台项目开发。
提供 1 路五向按键,采用中断与 A/D 模式采样。
提供 1 路有源蜂鸣器,1 路 2*17P 扩展接口,用于资源扩展板的接入。
核心板接口通过 2.54mm 间距的插针引出,方便用户外接其它设备
7.2 显示屏与资源拓展板
7.2.1 显示屏
电容触摸显示屏在很多智能设备上得到应用,提升了设备的交互感。
在开发板套件中使用方型显示屏用来模拟圆形的一个手表项目。显示屏尺寸为 2.8寸,分辨率 320*240(RGB)。
驱动 IC采用 ILI9341,自带 172,800 字节的 GRAM 存储。电容触摸屏采用 I2C 接口,驱动 IC 采用 FT6336G。
7.2.2 资源拓展板
资源扩展板提供基于 I2C 总线的温湿度传感器、环境光感知、心率/脉搏测量。基于模数转换接口的电压/电流采集。
基于 EXTI 事件/中断控制类型的人体红外、光电开关、火焰感知传感器。
基于 SPI 总线的数码管驱动电路。
基于 PWM 控制的风扇、蜂鸣器、震动马达。
基于 GPIO 的按键、LED 指示灯。
基于异步串行通信的 485 总线电平转换。基于控制器局域网总线的 CAN 电平转换等外设。
资源扩展板主要用于微控制器入门外设的使用,硬件图纸原理以及项目案例的应用开发学习。
8. 原理图
8.1 LD1这个灯连到了哪个引脚?
1. 先找到想要点的灯是谁,确定丝印为LD1
2. 打开拓展原理图,根据丝印LD1找到等的所在处,LED1线控制着LD1灯的亮灭
LED1为高电平灯亮,反之,灯灭
LED1肯定连到了芯片引脚上,顺线继续找LED1
3. LED1想要连到芯片引脚,必走如图所在处,其丝印为J1(空间有限,板子上并未标注)
4. 打开拓展板原理图J1所在处,能够找到老熟人,LED1,其位于J1的4号口
5. 拓展板通过J1连到了底板的J6口
6. 打开底板原理图找J6的4号口,就找到了LED1的连接处
7. 底板通过地板上的槽J1和J2连到了核心板,所以,LED1想连到芯片上肯定会走这个槽,所以去底板上找这个槽有没有叫LED1的,槽是J1和J2
8. 在J2的15号口又看到了老熟人LED1,为了方便,这里直接标注上了最后连到核心板的PC14上了
在J2的15号口又看到了老熟人LED1,为了方便,这里直接标注上了最后连到核心板的PC14上了
9. 结论:PC4最终连到了LED1,所以,控制PC4的电平高低就可以实现对灯的控制了,至此,此次原理图线路追踪结束,并得出结论
PC4高电平LD1灯亮,反之灯灭
作业:驱动风扇、蜂鸣器、马达隔一段时间切换一次状态
将演示视频发群里
依次方法可知:风扇连到了PC6引脚,高电平驱动
马达连到了PC7引脚,高电平驱动
底板蜂鸣器连到了PA15引脚,高电平驱动
9. 按键
当按键未按下,PC9为高电平
当按键被按下,PC9为低电平
所以,检测PC9是否为低电平就可以直到PC9是否按下了
按键消抖
抖动原因:
任何的机械按键都会有抖动,而且人手按下抬起并不是一瞬间的,人抬手是需要反应时间的,所以会导致按下的低电平时间过长,导致多次误进if判断语句,所以会多次切换状态,导致误判。
9.1.1 延时消抖
此处建议观看录课中的延时消抖讲解
9.1.2 抬手检测
检测到抬手动作后再进行灯的电平翻转
10. 光电开关(任务分析)
10.1 原理
遮挡-->PE15输出高电平--->PB2输入高电平
无遮挡-->PE15输出低电平--->PB2输入低电平
10.2光电开关控制风扇
num测试
]使用调试查看变量内容
最终实现代码