赞
踩
单片机小白,迄今为止第三次学习单片机(前两次点完灯,因为一些其他的事情就没有继续学习了),是个点灯带师。这学期刚好开了单片机的课程,因此希望通过写笔记的方式督促自己的学习。目前除了听自己老师上课外,还在B站跟着江科大的教程学习,此笔记是基于江科大STM32教程,大部分原理图片均为江科大ppt里复制来的。但是,本笔记案例相较于江科大的有些许改进, 为锻炼自己的代码能力,对多个单独的模块进行统一的控制,对于改进的代码也有相应的实物接线图和说明。
江科大STM32教程链接:【STM32入门教程-2023持续更新中】 https://www.bilibili.com/video/BV1th411z7sn/?share_source=copy_web&vd_source=ee06a25b3dfb2900ab707b01fdff6667
GPIO(General Purpose Input Output) 通用输入输出口
可配置为8种输入输出模式
引脚电平: 0V~3.3V, 部分引脚可容忍5V
输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
通过配置GPIO的端口配置寄存器,端口配置寄存器,端口可以配置成以下8种模式
模式名称 | 性质 | 特征 |
浮空输入 | 数字输入 | 可读取引脚电平,若引脚悬空,则电平不确定 |
上拉输入 | 数字输入 | 可读取引脚电平,内部连接上拉电阻,悬空时默认高电平 |
下拉输入 | 数字输入 | 可读取引脚电平,内部连接下拉电阻,悬空时默认低电平 |
模拟输入 | 模拟输入 | GPIO无效,引脚直接接入内部ADC |
开漏输入 | 数字输入 | 可输出引脚电平,高电平为高阻态,低电平接VSS (高电平没有驱动能力) |
推挽输入 | 数字输入 | 可输出引脚电平,高电平接VDD,低电平接VSS |
复用开漏输入 | 数字输入 | 由片上外设控制,高电平为高阻态,低电平接VSS (高电平没有驱动能力) |
复用推挽输入 | 数字输入 | 由片上外设控制,高电平接VDD,低电平接VSS |
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- /**
- * @brief Enables or disables the High Speed APB (APB2) peripheral clock.
- * @param RCC_APB2Periph: specifies the APB2 peripheral to gates its clock.
- * This parameter can be any combination of the following values:
- * @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
- * RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
- * RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
- * RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
- * RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
- * RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,
- * RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11
- * @param NewState: new state of the specified peripheral clock.
- * This parameter can be: ENABLE or DISABLE.
- * @retval None
- */
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)函数, 用来使能或失能APB2外设时钟。
第一个参数填需要使能或者失能的外设,第二个参数填ENABLE or DISABLE
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
- unsigned int gpio_groups=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5
- |GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;
- GPIO_InitStructure.GPIO_Pin=gpio_groups;
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
通过GPIO_InitTypeDef结构体配置GPIO的初始化参数
结构体内共有三个参数: GPIO_Pin GPIO_Speed GPIO_Mode
- #define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */
- #define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */
- #define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */
- #define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */
- #define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */
- #define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */
- #define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */
- #define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */
- #define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */
- #define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */
- #define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */
- #define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */
- #define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */
- #define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */
- #define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */
- #define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */
- #define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected */
- typedef enum
- {
- GPIO_Speed_10MHz = 1,
- GPIO_Speed_2MHz,
- GPIO_Speed_50MHz
- }GPIOSpeed_TypeDef;
- typedef enum
- { GPIO_Mode_AIN = 0x0, // 模拟输入
- GPIO_Mode_IN_FLOATING = 0x04, // 浮空输入
- GPIO_Mode_IPD = 0x28, // 下拉输入
- GPIO_Mode_IPU = 0x48, // 上拉输入
- GPIO_Mode_Out_OD = 0x14, // 开漏输出
- GPIO_Mode_Out_PP = 0x10, // 推挽输出
- GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出
- GPIO_Mode_AF_PP = 0x18 // 复用推挽输出
- }GPIOMode_TypeDef;
GPIO_Init(GPIOA, &GPIO_InitStructure);
第一个参数: 需要初始化GPIO端口, GPIO初始化结构体
// 引脚高电平 GPIO_SetBits(GPIOA, gpio_groups); while(1) { if(idx==7){ flag=0; } if(idx==0){ flag=1; } //引脚低电平 GPIO_ResetBits(GPIOA, leds[idx]); // 蜂鸣器 GPIO_ResetBits(GPIOA, GPIO_Pin_8); // 延时 Delay_ms(500); // 引脚高电平 GPIO_SetBits(GPIOA, leds[idx]); // 蜂鸣器 GPIO_SetBits(GPIOA, GPIO_Pin_8); // 延时 Delay_ms(500); if(flag==1){ idx++; } if(flag==0){ idx--; } }
#include "stm32f10x.h" #include "delay.h" // LED 闪烁实验 蜂鸣器实验 // 2023年3月8日20:01:30 int main(void) { unsigned leds[8] = {GPIO_Pin_0, GPIO_Pin_1, GPIO_Pin_2, GPIO_Pin_3, GPIO_Pin_4, GPIO_Pin_5, GPIO_Pin_6, GPIO_Pin_7}; unsigned flag = 1; unsigned idx = 0; // RCC 使能APB2外设 GPIOA RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置GPIO初始化参数 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; unsigned int gpio_groups=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5 |GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8; GPIO_InitStructure.GPIO_Pin=gpio_groups; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; // 执行GPIO初始化函数 GPIO_Init(GPIOA, &GPIO_InitStructure); // 引脚高电平 GPIO_SetBits(GPIOA, gpio_groups); while(1) { if(idx==7){ flag=0; } if(idx==0){ flag=1; } //引脚低电平 GPIO_ResetBits(GPIOA, leds[idx]); // 蜂鸣器 GPIO_ResetBits(GPIOA, GPIO_Pin_8); // 延时 Delay_ms(500); // 引脚高电平 GPIO_SetBits(GPIOA, leds[idx]); // 蜂鸣器 GPIO_SetBits(GPIOA, GPIO_Pin_8); // 延时 Delay_ms(500); if(flag==1){ idx++; } if(flag==0){ idx--; } } }
可以看出当光线较暗时,光敏电阻阻值增大,AO输出高电平。
A0-A7接LED,蜂鸣器I/O口接A9; 两个按键分别接到A10、B10,一个高电平触发(A10),一个低电平触发(B10); 光敏传感器模块数字输出口DO接A8; VCC和GND的接线不做说明。
- #include "stm32f10x.h"
- #include "delay.h"
- #include "LED.h"
- #include "key.h"
- #include "lightSensor.h"
- #include "beep.h"
- // 按键控制LED流水灯和光敏传感器控制蜂鸣器
- // 2023年3月10日16:10:49
- int main(void)
- {
- Init_LED(); // 初始化LED 输出IO口
- Init_Key(); // 初始化按键 输入IO口
- Init_LightSensor(); // 初始化光敏传感器 输出IO口
- Init_Beep(); // 初始化蜂鸣器 输入IO口
- uint8_t mode = 0;
- while(1)
- {
- uint8_t sensorSignal = Get_SignalFromSensor(); // 光敏传感器获取信号
- uint8_t keyNum = Get_KeyNum(); // 按键序号
- //按键控制流水灯
- /*
- if(keyNum==1){
- mode = 1;
- }else if(keyNum==2){
- mode = 0;
- }
- */
- mode = keyNum==1 ? 1 : keyNum==2 ? 0 : mode;
- mode = keyNum ? keyNum%2 : mode;
- /*
- if(mode==1){
- FlowLed();
- }else if(mode==0){
- Close_All_Lights();
- }
- */
- mode==1 ? FlowLed(): Close_All_Lights();
- // 光敏传感器控制蜂鸣器
- /*
- if(sensorSignal==1){
- Beep_On();
- }else if(sensorSignal==0){
- Beep_Off();
- }
- */
- sensorSignal==1 ? Beep_On() : Beep_Off();
-
- }
- }
- #include "stm32f10x.h"
- #include "delay.h"
-
- // 2023年3月10日17:00:13
- // B10设置为上拉输入 默认高电平 按键按下后为低电平
- // A10设置为下拉输入 默认低电平 按键按下后为高电平
- void Init_Key(void)
- {
- // GPIO初始化结构体配置参数
- GPIO_InitTypeDef GPIO_InitStructureA;
- GPIO_InitTypeDef GPIO_InitStructureB;
- // RCC时钟使能APB2外设
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
-
- // 配置参数
- GPIO_InitStructureA.GPIO_Mode=GPIO_Mode_IPD; // 下拉输入
- GPIO_InitStructureA.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_InitStructureA.GPIO_Pin=GPIO_Pin_10;
- GPIO_InitStructureB.GPIO_Mode=GPIO_Mode_IPU; // 上拉输入
- GPIO_InitStructureB.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_InitStructureB.GPIO_Pin=GPIO_Pin_10;
- // 调用初始化函数
- GPIO_Init(GPIOA, &GPIO_InitStructureA);
- GPIO_Init(GPIOB, &GPIO_InitStructureB);
- return;
- }
-
- // 判断哪个按键按下
- uint8_t Get_KeyNum(void)
- {
- uint8_t KeyNum=0;
- // A10按下 下拉输入 默认低电平 按键按下后为高电平
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)==1){
- Delay_ms(20);
- while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)==1);
- Delay_ms(20);
- KeyNum=1;
- }
- if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10)==0){
- Delay_ms(20);
- while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)==1);
- Delay_ms(20);
- KeyNum=2;
- }
- return KeyNum;
- }
- #include "stm32f10x.h"
- #include "delay.h"
-
- // 初始化LED所用引脚 A0-A7
- void Init_LED(void)
- {
- // 八个引脚 A0-A7
- uint16_t GPIO_GROUP=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5
- |GPIO_Pin_6|GPIO_Pin_7;
- // RCC 使能APB2外设时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- // GPIO初始化结构体配置参数
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; // 推挽输出模式
- GPIO_InitStructure.GPIO_Pin=GPIO_GROUP;
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- // 调用GPIO初始化函数
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- // 设置高电平
- GPIO_SetBits(GPIOA, GPIO_GROUP);
-
- return;
- }
-
- // 流水灯
- uint8_t FlowLed(void)
- {
- static uint8_t flag=1;
- static uint8_t pin=0;
- uint16_t gpio_group[8] = {GPIO_Pin_0, GPIO_Pin_1, GPIO_Pin_2, GPIO_Pin_3, GPIO_Pin_4,
- GPIO_Pin_5, GPIO_Pin_6, GPIO_Pin_7};
- if((pin)==7){
- flag=0;
- }
-
- if((pin)==0){
- flag=1;
- }
- // 引脚低电平
- GPIO_ResetBits(GPIOA, gpio_group[pin]);
- // 延时
- Delay_ms(500);
- // 引脚高电平
- GPIO_SetBits(GPIOA, gpio_group[pin]);
- // 延时
- Delay_ms(500);
-
- if(flag==1){
- pin = pin+1;
- }
- if(flag==0){
- pin = pin-1;
- }
- return 1;
- }
-
- // 关闭所有LED
- uint8_t Close_All_Lights(void)
- {
- uint16_t GPIO_GROUP=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5
- |GPIO_Pin_6|GPIO_Pin_7;
- GPIO_SetBits(GPIOA, GPIO_GROUP);
- return 1;
- }
- #include "stm32f10x.h"
-
- // 2023年3月10日21:24:36
- // 初始化A8引脚作为光敏传感器信号的输入
- // 当光线变暗时光敏电阻阻值增大,分压上升,输出高电平
- void Init_LightSensor(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- // RCC 使能时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- // 配置GPIO初始化结构体变量
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; // 下拉模式 默认输入为低电平
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- // 调用GPIO初始化函数
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- return;
- }
-
- // 获取并光敏传感器输入到单片机里的信号
- uint8_t Get_SignalFromSensor(void)
- {
- return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8);
- }
- #include "stm32f10x.h"
- #include "delay.h"
- // 2023年3月10日21:26:17
- // 通过A9引脚输出的信号控制蜂鸣器
-
- // 初始化所需要的引脚
- void Init_Beep(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- // RCC时钟使能APB2外设
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- // 配置初始化结构体的参数
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- // 调用GPIO初始化函数
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- // 设置高电平
- GPIO_SetBits(GPIOA, GPIO_Pin_9);
- return;
- }
-
- // 蜂鸣器鸣叫
- uint8_t Beep_On(void)
- {
- GPIO_SetBits(GPIOA, GPIO_Pin_9);
- Delay_ms(200);
- GPIO_ResetBits(GPIOA, GPIO_Pin_9);
- Delay_ms(200);
- return 1;
- }
-
- uint8_t Beep_Off(void)
- {
- // 高电平停止
- GPIO_SetBits(GPIOA, GPIO_Pin_9);
- return 1;
- }
函数名称 | 功能 |
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); | 根据GPIO结构体函数中的参数(GPIO_Mode, GPIO_Pin, GPIO_Speed)初始化外设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); | 向指定的GPIO数据端口写入数据 |
void GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); | 读取指定端口引脚的输入 |
void GPIO_ReadInputData(GPIO_TypeDef* GPIOx); | 读取指定的GPIO端口输入 |
void GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); | 读取指定端口引脚的输出 |
void GPIO_ReadOutputData(GPIO_TypeDef* GPIOx); | 读取指定的GPIO端口输出 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。