您现在的位置是:首页 >其他 >单片机--实战练习网站首页其他
单片机--实战练习
目录
问: 单片机上电后第一个执行的程序是?
1、初始化堆栈指针SP=_initial_sp
2、初始化PC 指针=Reset_Handler
3、初始化中断向量表
4、配置系统时钟SystemInit
5、调用C 库函数_main 初始化用户堆栈,从而最终调用main 函数去到C 的世界
【1】GPIO
1.定义
在嵌入式系统中,经常需要控制许多结构简单的外部设备或者电路,这些设备有的需要通过CPU控制,有的需要CPU读取其输入信号,因此在嵌入式微处理器上提供了一种“通用可编程I/O端口”,也就是GPIO(General-purpose input/output) 。
2.应用
I - Input - 输入采集
DO - 数字量输出口 0 or 1 有火/没火
O - Output - 输出控制
3.GPIO结构框图
补充:
问:VDD、VSS、VCC分别表示什么意思?
VCC :接入电路的电压
VDD : 元器件内部的工作电压
VSS : 公共接地端电压
问:施密特触发器的作用?
由于外部输入的信号,可能会出现脉冲等噪声的影响,为了让信号更加清晰,所以就设置了TTL施密特触发器来进行整形。
“施密特触发器可作为波形整形电路,能将模拟信号波形整形为数字电路能够处理的方波波形,而且由于施密特触发器具有滞回特性,所以可用于抗干扰,其应用包括在开回路配置中用于抗扰,以及在闭回路正回授/负回授配置中用于实现多谐振荡器。”
4.功能描述
输入功能
浮空输入
通俗讲就是让管脚什么都不接,悬空着。
此时VDD和VSS所在路径的两个开关同时断开。因为没有上拉和下拉,所以当IO口没有接输入的时候,此时的电平状态会是一个不确定的值,完全由外部输入决定。
一般实际运用时,引脚不建议悬空,易受干扰。
优势:这一种输入模式的电平会完全取决于外部电路而与内部电路无关。
缺点:在没有外部电路接入的时候,IO脚浮空会使得电平不确定
应用:该模式是STM32复位之后的默认模式,一般用作对开关按键的读取或用于标准的通讯协议,比如IIC、USART的等。
上拉输入
IO端口 - 上拉电阻 - 施密特触发器 - 输入数据寄存器 - 读
输入的电平不会因上下浮动而导致输入信号不稳定,当外部没有信号输入时,上拉电阻会将输入信号钳在高电平,此时引脚始终读到高电平信号。
下拉输入
IO端口 - 下拉电阻 - 施密特触发器 - 输入数据寄存器 - 读
输入的电平不会因上下浮动而导致输入信号不稳定,当外部没有信号输入时,下拉电阻会将输入信号钳在低电平,此时引脚始终读到低电平信号。
模拟输入
信号进入后不经过上拉电阻或者下拉电阻,关闭施密特触发器,经由另一线路把电压信号传送到片上外设模块。 所以可以理解为模拟输入的信号是未经处理的信号,是原汁原味的信号。
应用:当 GPIO 引脚用于 ADC 采集电压的输入通道时,则需要选择“模拟输入”功能,因为经过施密特触发器后信号只有 0、1 两种状态,所以 ADC 外设要采集到原始的模拟信号,信号源输入必须在施密特触发器之前。
输出功能
开漏输出
输出寄存器上的’0’激活 N-MOS,而输出寄存器上的’1’将端口置于高阻状态 (P-MOS 从不被激活 )。
无法真正输出高电平,即高电平时没有驱动能力,需要借助外部上拉电阻完成对外驱动。
可以利用改变上拉电源的电压来适应所需,进而提高外部电路的驱动能力。
推挽输出
输出寄存器上的’0’激活 N-MOS,而输出寄存器上的’1’将激活 P-MOS,具备输出高低电平的能力。
当上面的MOS管导通时,GPIO输出高电平1,称为“推
当下面MOS管导通时,GPIO输出低电平0,称为“挽”
5.相关寄存器
4 个 32 位 配 置 寄 存 器
GPIOx_MODER 模式寄存器
GPIOx_OTYPER 输出类型寄存器
GPIOx_OSPEEDR 输出速度寄存器
GPIOx_PUPDR 上拉下拉寄存器
2 个 32 位数据寄存器
GPIOx_IDR 输入数据寄存器
GPIOx_ODR 输出数据寄存器
1 个32 位置位 / 复位寄存器
GPIOx_BSRR
1 个 32 位锁定寄存器
GPIOx_LCKR
2 个 32 位替代功能寄存器
GPIOx_AFRH
GPIOx_AFRL
【2】点亮一盏LED灯
1.实验步骤
1.查看开发板,找到LED灯
2.查看原理图
分析得到结论:只需要讲PB1引脚配置成输出功能且输出低电平信号即可点亮蓝灯。
2.编程实现
1)寄存器配置
2)代码编写
RCC->IOPENR |= 1<<1; //使能GPIOB组时钟
GPIOB->MODER &= ~(0X3 << 2); //配置输出模式
GPIOB->MODER |= 1<<2;
GPIOB->OTYPER &= ~(1<<1); //推挽输出模式
GPIOB->ODR &= ~(1<<1); //输出低电平
3.编译下载
4.复位上电
练习:实现LED灯闪烁
先实现初始化函数、开关控制函数、延时函数:
声明函数:
再while(1)死循环中,调用开关函数,并通过延时保持一段时间,即可看到闪烁效果。
练习:实现流水灯效果
实现初始化函数,将PB0/PB1/PB2分别初始化为推挽输出模式。
/* USER CODE BEGIN 4 */
void GPIO_Init()
{
RCC->IOPENR |= 1<<1; //使能GPIOB组时钟 1左移1位==将第二位置1
//PB0
GPIOB->MODER |=1<<0; //配置输出模式 将第0位置1
GPIOB->MODER &=~(1<<1); //将第1位置0
GPIOB->OTYPER &= ~(1<<0); //推挽输出模型
//PB1
GPIOB->MODER |=1<<2; //配置输出模式
GPIOB->MODER &=~(1<<3);
GPIOB->OTYPER &= ~(1<<1); //推挽输出模型
//PB2
GPIOB->MODER |=1<<4; //配置输出模式
GPIOB->MODER &=~(1<<5);
GPIOB->OTYPER &= ~(1<<2); //推挽输出模型
}
实现三盏LED灯的亮灭函数:
//LED2 - PB1
void LED2_ON()
{
GPIOB->ODR &= ~(1<<1); //输出低电平 将第二位置0
}
void LED2_OFF()
{
GPIOB->ODR |= 1<<1; //输出高电平 将第二位置1
}
//LED3 - PB2
void LED3_ON()
{
GPIOB->ODR &= ~(1<<2); //输出低电平 将第三位置0
}
void LED3_OFF()
{
GPIOB->ODR |= 1<<2; //输出高电平 将第三位置1
}
//LED4 - PB0
void LED4_ON()
{
GPIOB->ODR &= ~(1<<0); //输出低电平 将第一位置0
}
void LED4_OFF()
{
GPIOB->ODR |= 1<<0; //输出高电平 将第一位置1
}
实现延时函数:
main函数调用:
/* USER CODE BEGIN 2 */
GPIO_Init(); //初始化GPIO
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
LED2_ON(); //点亮LED2
LED3_OFF(); //熄灭LED3、LED4
LED4_OFF();
Delay(); //延时
LED3_ON(); //点亮LED3
LED2_OFF();//熄灭LED2、LED4
LED4_OFF();
Delay(); //延时
LED4_ON();//点亮LED4
LED2_OFF();//熄灭LED2、LED3
LED3_OFF();
Delay();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
实现效果:
练习:实现流水灯效果 (HAL库版)
打开STM32CubeMX新建工程配置引脚功能
引脚功能详细配置
生成代码
代码编写:
【3】输入采集实验
实验:按键点灯实验
1.查看开发板
找到五向按键 丝印 - S1
2.查看原理图
SN74HC32D: 四路或门电路
//只要有一个方向键被按下,D3&KEY则输出高电平信号。
//只要有方向键被按下,PA8引脚则会输入一个高电平信号。
3.配置STM32CubeMX
4.代码编写
while (1)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8))
{
HAL_Delay(100);//延时消抖
//读取数据
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8))
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2);
while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8));//抬手监测
}
}
}
练习:火焰感应器
1.查看开发板,找到火焰感应器 FLAME1
2.查看原理图
3.配置STM32CubeMX
4.代码编写
while (1)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4))
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_RESET);//监测到火焰黄灯亮起
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);//绿灯熄灭
}
else
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);//监测不到火焰绿灯亮起
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,GPIO_PIN_SET); //黄灯熄灭
}
}
【4】HAL库函数分析
HAL库是ST公司为STM32的MCU最新推出的抽象层嵌入式软件
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_RESET 0 低电平
GPIO_PIN_SET 1 高电平
返回值:无
void HAL_Delay(uint32_t Delay)
功能:实现毫秒级延时
参数:延时时间(ms)
返回值:无
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
void HAL_GPIO_TogglePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin)
功能:翻转指定引脚的电平状态
参数: GPIO_TypeDef * GPIOx 端口号
uint16_t GPIO_Pin 引脚号
返回值:无