前几天系统地将32单片机学习了一下,学习的视频是bilibili的江科大自化协c8t6的教学,为了方便以后使用,在这里和b站视频联动写下一篇笔记,以便自己查阅资料和调用函数。
性能:AHB>APB2>APB1(注意关注这三者里面的外设,其实后两者性能差不多)
从APB2总线,引出RCC_APB2PeriphClockCmd(GPIO口的名字,状态),如使GPIOA 使能:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
第一个参数 GPIO_TypeDef* GPIOx 通过x选定GPIO, 如:GPIOA
第二个参数 GPIO_InitTypeDef* GPIO_InitStruct是GPIO的结构体地址 如:&GPIO_InitStructure
struct 关键字,定义结构体变量
用途:数据打包,不同类型的变量打包(可以数组,数组是同一个类型打包)
#define 新名字 旧名字(无脑式定义)
typedef 旧名字 新名字(定义 长变量类型名);
因为结构体变量类型较长,所以通常用typedef更改变量类型名
我们把GPIO_InitTypeDef取个名字叫GPIO_InitStructure放到void GPIO_Init()上面并且在void GPIO_Init()中取地址&GPIO_InitStructure
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure
void GPIO_Init(GPIOA,GPIO_InitTypeDef* GPIO_InitStruct)
由上面struct{…}结构体知道GPIO_InitStructure 有三个参数分别用.引出:
(也可以用->直接指向结构体成员即可,就不必用*取地址和.引出结构体)
GPIO_InitStructure.GPIO_Mode
GPIO_InitStructure.GPIO_Pin
GPIO_InitStructure.GPIO_Speed
GPIO_Mode_AIN(Analog IN)//模拟输入
GPIO_Mode_IN_FLOATING //浮空输入
GPIO_Mode_IPD (In Pull Down) //下拉输入
GPIO_Mode_IPU (In Pull Up) //上拉输入
GPIO_Mode_OUT_OD(Out Open Drain) //开漏输出
GPIO_Mode_PP_OD(Out Push Pull) //推挽输出
GPIO_Mode_AF_OD(Atl Open Drain) //复用开漏
GPIO_Mode_AF_PP(Atl Push Pull) //复用推挽
第二个GPIO_InitStructure.GPIO_Pin 的选择
第三个GPIO_InitStructure.GPIO_Speed的选择
我们一般选50MHz
最后结果如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
这样我们就把GPIOA 上所有引脚都初始化好了。
————————————————————————————————————————————————end
这里总共涉及了RCC和GPIO两个外设
★常用的三个RCC外设
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
★读写GPIO的8个函数
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
例1:
GPIO_SetBits : 拉高引脚输出电平 //1
GPIO_ResetBits :拉低引脚输出电平 //0
GPIO_ResetBits(GPIOA, GPIO_Pin_0); //将PA0口置0
Delay_ms(500);
GPIO_SetBits(GPIOA, GPIO_Pin_0);//将PA0口置1
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);//Bit_RESET设置低电平
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);//强制转换BitAction类型 0 1
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
Delay_ms(500);
例2:读取GPIO上 电平操作
GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);//读取PB13上引脚输入 一般是接一个按键 读它的输入 即是否按下
GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1)//读取PA1上引脚输出 一般接光敏传感器 读它的AO口输出 即是否被遮挡
例3:灯的函数使用
//灯的打开
void LED1_ON(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
//灯的熄灭
void LED1_OFF(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
//灯的翻转
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);
}
}
Delay_us();
Delay_ms();
Delay_s();
Delay.h
#ifndef __DELAY_H
#define __DELAY_H
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);
#endif