不仅仅是pin口可以按位或操作,时钟控制也可以用按位或的方式来控制多个外设。
GPIO_SetBits(GPIOA, GPIO_Pin_0);
GPIO_SetBits(GPIOA, GPIO_Pin_0)也可以用按位或的方式设置多个引脚。
为了同时控制16个端口,我们使用函数 GPIO_Write
param2:指定写到输出寄存器的值
LED流水灯点亮成功,而且他也给我弹框了
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//RCC里面的外设时钟控制函数,开启时钟
//---------------GPIO初始化--------------------------
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //点灯使用的是推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //0号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//-----------------GPIO初始化完成---------------------------------
//GPIO_ResetBits(GPIOA, GPIO_Pin_2);
//GPIO_SetBits(GPIOA, GPIO_Pin_2);
while(1)
{
GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001
//因为是低电平点亮,所以前面加上按位取反的符号~
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0008); //0000 0000 0000 1000
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0010); //0000 0000 0001 0000
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0020); //0000 0000 0010 0000
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0040); //0000 0000 0100 0000
Delay_ms(500);
GPIO_Write(GPIOA, ~0x0080); //0000 0000 1000 0000
Delay_ms(500);
}
}
3-3蜂鸣器没亲身实验,因为声音有点大,可以通过延时的时间不同,让其响动的音频也不同。
库函数开发方式的用法:
1、打开.h文件,下拉到最后,看有那些函数名,
2、然后跳转至定义,有biref、param来了解函数
抖动solution:过滤抖动——加延时,耗过抖动时间
传感器模块:
一端接在电路中,一端接地,可以考虑是否是滤波电容的作用——保证电路稳定
上下拉电阻的工作原理——杆子弹簧工作模型
弱上拉、弱下拉、强上拉、强下拉
强弱:电阻阻值的大小(弹簧弹力的大小)
运放做比较器:
按键的硬件电路分为上、下接法,常用下接
图A 的PA0必须配置成上拉输入模式,不然未按下按键时就会出现悬空状态。
图C 的PA0必须配置成下拉输入模式,————————————————
两者区别:
- 宏定义新name在左边,不需要;,可以替换任何名字——改名范围更宽、无脑改名
- typedef在右边,需要;,只能专门给变量类型换名字——会对命名进行检查、给变量类型重命名
要理解库函数的运作逻辑,理解结构体之非常有必要
- 结构体——数据类型:组合数据类型,组合不同类型的数据
- 基本数据类型:int char
- 数组:一大堆基本数据类型的集合,且只能组合相同数据类型——组合数据类型——基本数据类型的组合
- 提问:若想组合不同类型的数据?
- 回答:结构体的出现
主要作用:定义数据、引用数据
变量引用(两种方式):
- 结构体变量名称+.+结构体子项的名称(成员名)
- 结构体指针名->结构体成员名
在函数之间的数据传递中,通常应用的是地址传递,而非值传递。
涉及知识:地址传递、值传递、指针
结构体instinct——数据打包
- 参数写到结构体的三个变量里——>统一打包——>将结构体传递至函数——》函数里拆包结构体——》读取变量
枚举:数据类型 ——定义、引用
- 例如:存储星期的值
- 作用:只能在给定的参数列表里赋值
- LED.c LED.h用来分装LED的驱动程序
- LED.c存放驱动程序的主体代码
- LED.h存放驱动程序可以对外提供的函数或变量的声明
模块化编程
当做自己的product时,外围硬件部件多,——尽量把每个硬件的驱动函数单独提取出来,封装在.c.h文件中,即提取封装的是每个硬件的驱动函数
好处advantage
1、简化主函数的逻辑,主函数main.c有着更为重要的任务,不要让驱动函数来影响我们。
2、硬件驱动的提取,也有利于移植程序
封装要点:
函数注释清楚——方便别人使用你的模块从而快速上手
8个读取和写入的函数之四
局部变量与全局变量:
在函数里优先使用内部的局部变量,若没有,才使用全局变量
哟!错误有有有了!解决问题超棒
以上图片是修改之后的,错误原因:给加了两个
,导致出现了
又出现了新问题:
- 编译正确,也能下载,但我的灯在按键按下时不亮,但是使用老师的程序又完全可以,那我的电路连接是正确的。那是哪里的问题?
呀!又找出答案了
Key_Init; //初始化按键
Key_Init(); //初始化按键
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h" //包含LED模块的头文件
#include "Key.h"
uint8_t KeyNum; //KeyNum在这里是全局变量
int main(void)
{
LED_Init();
Key_Init(); //初始化按键
while(1)
{
KeyNum = Key_GetNum();
if (KeyNum == 1)
{
LED1_ON();
}
if (KeyNum == 2)
{
LED1_OFF();
}
}
}
又有错误了
- 不能实现按按键灯亮又灯灭,只能按一下灯亮,然后没作用了
又是我哪里出错了?当然是我的程序编写有问题了
不是if{}的问题
应该是我LED.c文件编写的问题
存极大的疑问:我和老师的编写完全相同,为何我的不行
我的:
老师的:
void LED1_Turn(void)
{
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1 == 0))
{
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
}
3-5 光敏传感器控制蜂鸣器 也暂时做不了,所以先解决代码问题
主要步骤:驱动程序的分装
测试蜂鸣器——驱动函数
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"
uint8_t KeyNum; //KeyNum在这里是全局变量
int main(void)
{
Buzzer_Init();
LightSensor_Init();
while(1)
{
if (LightSensor_Get() == 1) //光线暗的情况
{
Buzzer_ON();
}
else
{
Buzzer_OFF();
}
}
}
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Buzzer.h"
uint8_t KeyNum; //KeyNum在这里是全局变量
int main(void)
{
Buzzer_Init();
while(1)
{
Buzzer_ON();
Delay_ms(500);
Buzzer_OFF();
Delay_ms(500);
Buzzer_Turn();
Delay_ms(500);
Buzzer_Turn();
Delay_ms(500);
}
}
再次总结GPIO的使用方法:
1.初始化时钟
2.定义结构体
3.赋值结构体
GPIO_Mode——8种输入输出方式
GPIO_Pin——选择引脚,按位或的方式同时选中多个引脚
GPIO_Speed
4.GPIO_Init函数——将指定的GPIO初始化好
tips:8个读取和写入的函数