stm32之GPIO函数详解和上机实验
目录
- 1.LED和蜂鸣器
- 1.1 LED
- 1.2 蜂鸣器
- 2.实验
- 2.1 库函数:RCC和GPIO
- 2.1.1 RCC函数
- 1. `RCC_AHBPeriphClockCmd`
- 2. `RCC_APB2PeriphClockCmd`
- 3. `RCC_APB1PeriphClockCmd`
- 2.1.2 GPIO函数
- 1. `GPIO_DeInit`
- 2. `GPIO_AFIODeInit`
- 3. `GPIO_Init`
- 4. `GPIO_StructInit`
- 5. `GPIO_ReadInputDataBit`
- 6. `GPIO_ReadInputData`
- 7. `GPIO_ReadOutputDataBit`
- 8. `GPIO_ReadOutputData`
- 9. `GPIO_SetBits`
- 10. `GPIO_ResetBits`
- 11. `GPIO_WriteBit`
- 12. `GPIO_Write`
- 13. `GPIO_PinLockConfig`
- 14. `GPIO_EventOutputConfig`
- 15. `GPIO_EventOutputCmd`
- 16. `GPIO_PinRemapConfig`
- 17. `GPIO_EXTILineConfig`
- 2.2 LED灯闪烁
- 2.3 LED流水灯
- 2.4 蜂鸣器
- 2.5 按键控制LED
- 2.5.1 电路接法
- 2.5.2 编写
- 2.6 光敏传感器控制器蜂鸣器
- 2.6.1 传感器介绍
- 2.6.2 电路接法
- 2.6.3 编程
- 3.OLED
- 3.1 介绍
- 3.2 API
- 3.3 代码
1.LED和蜂鸣器
1.1 LED
或者长脚是正极、短脚是负极,led的电路接法可以两种,主要是看IO的高/低电平驱动能力去选择
上半是低电平驱动的电路,IO口处于推挽模式,当输出数据寄存器输出的是1时,上管P-MOS管导通,输出的是高电平,但由于LED外部(正极)接的是3.3V的电压,也就是此时LED两边电压差为0,因此不亮。那么输出低电平,产生电压差了,LED就亮了,所以是低电平去驱动的。
下半则是高电平驱动的,其实是差不多的,就是负极接的GND,正极接的IO口,IO口输出高电平的时候才会亮。
需要注意的是在连接的时候最好加一个保护电阻。
1.2 蜂鸣器
这个蜂鸣器是低电平触发的。
使用的是三极管驱动电路来实现的,也有两种接法。
对于上半,接的是一个PNP三极管,对于PNP三极管,当基极输出的是低电平的时候,三极管就导通,也就是3.3V的电压会经过蜂鸣器,就会发出声响
对于下半,接的则是NPN三极管,当E接地的时候,B作为控制引脚,当B输出高电平,那么三极管就导通了,3.3V电压能顺利经过蜂鸣器,然后经过三极管到接地,发出声响。
所以一样也是分为低电平驱动和高电平驱动两种方式,具体可根据实际情况去选择。
2.实验
2.1 库函数:RCC和GPIO
主要涉及RCC和GPIO两个外设,所需要的库函数在Lidrary目录下的.h文件:📎stm32f10x_rcc.h、📎stm32f10x_gpio.h。文件的末尾一般都是该设备的相关函数
2.1.1 RCC函数
其中对于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);
下面是函数的定义,官方给的注释是中文,个人按照自己的理解转换了一下:
1. RCC_AHBPeriphClockCmd
/*** @brief 启用或禁用 AHB 总线的外设时钟。* @param RCC_AHBPeriph: 指定要控制其时钟的 AHB 外设。* * 对于 STM32 的 Connectivity 版本设备,此参数可以是以下值的组合:* @arg RCC_AHBPeriph_DMA1 // DMA1 控制器* @arg RCC_AHBPeriph_DMA2 // DMA2 控制器* @arg RCC_AHBPeriph_SRAM // SRAM 存储器* @arg RCC_AHBPeriph_FLITF // 闪存接口* @arg RCC_AHBPeriph_CRC // CRC 计算单元* @arg RCC_AHBPeriph_OTG_FS // USB OTG 全速接口* @arg RCC_AHBPeriph_ETH_MAC // 以太网 MAC 接口* @arg RCC_AHBPeriph_ETH_MAC_Tx // 以太网 MAC 传输* @arg RCC_AHBPeriph_ETH_MAC_Rx // 以太网 MAC 接收* * 对于其他 STM32 设备,此参数可以是以下值的组合:* @arg RCC_AHBPeriph_DMA1* @arg RCC_AHBPeriph_DMA2* @arg RCC_AHBPeriph_SRAM* @arg RCC_AHBPeriph_FLITF* @arg RCC_AHBPeriph_CRC* @arg RCC_AHBPeriph_FSMC // 灵活静态存储控制器* @arg RCC_AHBPeriph_SDIO // SDIO 接口* * @note SRAM 和 FLITF 时钟仅在睡眠模式下可以禁用。* @param NewState: 指定外设时钟的新状态,可以是 ENABLE 或 DISABLE。* @retval 无*/
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState)
{/* 检查传入的参数是否合法 */assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE) // 如果新状态为启用{/* 通过设置相应位启用外设的 AHB 时钟 */RCC->AHBENR |= RCC_AHBPeriph;}else // 如果新状态为禁用{/* 通过清除相应位禁用外设的 AHB 时钟 */RCC->AHBENR &= ~RCC_AHBPeriph;}
}
2. RCC_APB2PeriphClockCmd
/*** @brief 启用或禁用 APB2 高速总线的外设时钟。* @param RCC_APB2Periph: 指定要控制其时钟的 APB2 外设。* 此参数可以是以下值的组合:* @arg RCC_APB2Periph_AFIO // 外设功能 IO* @arg RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB, RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,* @arg RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG // GPIO 端口* @arg RCC_APB2Periph_ADC1, RCC_APB2Periph_ADC2, RCC_APB2Periph_ADC3 // ADC 模数转换器* @arg RCC_APB2Periph_TIM1, RCC_APB2Periph_TIM8, RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,* RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11 // 定时器* @arg RCC_APB2Periph_SPI1 // SPI 接口* @arg RCC_APB2Periph_USART1 // USART 接口* @param NewState: 指定外设时钟的新状态,可以是 ENABLE 或 DISABLE。* @retval 无*/
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{/* 检查传入的参数是否合法 */assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE) // 如果新状态为启用{/* 通过设置相应位启用外设的 APB2 时钟 */RCC->APB2ENR |= RCC_APB2Periph;}else // 如果新状态为禁用{/* 通过清除相应位禁用外设的 APB2 时钟 */RCC->APB2ENR &= ~RCC_APB2Periph;}
}
3. RCC_APB1PeriphClockCmd
/*** @brief 启用或禁用 APB1 低速总线的外设时钟。* @param RCC_APB1Periph: 指定要控制其时钟的 APB1 外设。* 此参数可以是以下值的组合:* @arg RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4, RCC_APB1Periph_TIM5,* RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7 // 定时器* @arg RCC_APB1Periph_WWDG // 窗口看门狗* @arg RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3 // SPI 接口* @arg RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4, RCC_APB1Periph_USART5 // USART 接口* @arg RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2 // I2C 接口* @arg RCC_APB1Periph_USB // USB 接口* @arg RCC_APB1Periph_CAN1 // CAN 接口* @arg RCC_APB1Periph_BKP // 备份寄存器* @arg RCC_APB1Periph_PWR // 电源管理* @arg RCC_APB1Periph_DAC // 数模转换器* @arg RCC_APB1Periph_CEC // 消费电子控制* @arg RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14 // 定时器* @param NewState: 指定外设时钟的新状态,可以是 ENABLE 或 DISABLE。* @retval 无*/
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)
{/* 检查传入的参数是否合法 */assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE) // 如果新状态为启用{/* 通过设置相应位启用外设的 APB1 时钟 */RCC->APB1ENR |= RCC_APB1Periph;}else // 如果新状态为禁用{/* 通过清除相应位禁用外设的 APB1 时钟 */RCC->APB1ENR &= ~RCC_APB1Periph;}
}
这些函数通过设置或清除寄存器中的位来控制不同外设的时钟,使能(启用)或失能(禁用)外设的时钟信号。根据所连接的设备去选择想要使用的时钟使能函数,这里只暂时介绍这三个。
2.1.2 GPIO函数
stm32f10x_gpio.h文件中给出了以下的函数声明:
/*** @brief Deinitializes the GPIOx peripheral registers to their default reset values.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @retval None*/
void GPIO_DeInit(GPIO_TypeDef* GPIOx);/*** @brief Deinitializes the Alternate Functions (remap, event control* and EXTI configuration) registers to their default reset values.* @param None* @retval None*/
void GPIO_AFIODeInit(void);/*** @brief Initializes the GPIOx peripheral according to the specified* parameters in the GPIO_InitStruct.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that* contains the configuration information for the specified GPIO peripheral.* @retval None*/
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);/*** @brief Fills each GPIO_InitStruct member with its default value.* @param GPIO_InitStruct : pointer to a GPIO_InitTypeDef structure which will* be initialized.* @retval None*/
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);/*** @brief Reads the specified input port pin.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bit to read.* This parameter can be GPIO_Pin_x where x can be (0..15).* @retval The input port pin value.*/
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);/*** @brief Reads the specified GPIO input data port.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @retval GPIO input data port value.*/
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);/*** @brief Reads the specified output data port bit.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bit to read.* This parameter can be GPIO_Pin_x where x can be (0..15).* @retval The output port pin value.*/
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);/*** @brief Reads the specified GPIO output data port.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @retval GPIO output data port value.*/
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);/*** @brief Sets the selected data port bits.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bits to be written.* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).* @retval None*/
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);/*** @brief Clears the selected data port bits.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bits to be written.* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).* @retval None*/
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);/*** @brief Sets or clears the selected data port bit.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bit to be written.* This parameter can be one of GPIO_Pin_x where x can be (0..15).* @param BitVal: specifies the value to be written to the selected bit.* This parameter can be one of the BitAction enum values:* @arg Bit_RESET: to clear the port pin* @arg Bit_SET: to set the port pin* @retval None*/
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);/*** @brief Writes data to the specified GPIO data port.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param PortVal: specifies the value to be written to the port output data register.* @retval None*/
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);/*** @brief Locks GPIO Pins configuration registers.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bit to be written.* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).* @retval None*/
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);/*** @brief Selects the GPIO pin used as Event output.* @param GPIO_PortSource: selects the GPIO port to be used as source* for Event output.* This parameter can be GPIO_PortSourceGPIOx where x can be (A..E).* @param GPIO_PinSource: specifies the pin for the Event output.* This parameter can be GPIO_PinSourcex where x can be (0..15).* @retval None*/
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);/*** @brief Enables or disables the Event Output.* @param NewState: new state of the Event output.* This parameter can be: ENABLE or DISABLE.* @retval None*/
void GPIO_EventOutputCmd(FunctionalState NewState);/*** @brief Changes the mapping of the specified pin.* @param GPIO_Remap: selects the pin to remap.* This parameter can be one of the following values:* @arg GPIO_Remap_SPI1 : SPI1 Alternate Function mapping* @arg GPIO_Remap_I2C1 : I2C1 Alternate Function mapping* @arg GPIO_Remap_USART1 : USART1 Alternate Function mapping* @arg GPIO_Remap_USART2 : USART2 Alternate Function mapping* @arg GPIO_PartialRemap_USART3 : USART3 Partial Alternate Function mapping* @arg GPIO_FullRemap_USART3 : USART3 Full Alternate Function mapping* @arg GPIO_PartialRemap_TIM1 : TIM1 Partial Alternate Function mapping* @arg GPIO_FullRemap_TIM1 : TIM1 Full Alternate Function mapping* @arg GPIO_PartialRemap1_TIM2 : TIM2 Partial1 Alternate Function mapping* @arg GPIO_PartialRemap2_TIM2 : TIM2 Partial2 Alternate Function mapping* @arg GPIO_FullRemap_TIM2 : TIM2 Full Alternate Function mapping* @arg GPIO_PartialRemap_TIM3 : TIM3 Partial Alternate Function mapping* @arg GPIO_FullRemap_TIM3 : TIM3 Full Alternate Function mapping* @arg GPIO_Remap_TIM4 : TIM4 Alternate Function mapping* @arg GPIO_Remap1_CAN1 : CAN1 Alternate Function mapping* @arg GPIO_Remap2_CAN1 : CAN1 Alternate Function mapping* @arg GPIO_Remap_PD01 : PD01 Alternate Function mapping* @arg GPIO_Remap_TIM5CH4_LSI : LSI connected to TIM5 Channel4 input capture for calibration* @arg GPIO_Remap_ADC1_ETRGINJ : ADC1 External Trigger Injected Conversion remapping* @arg GPIO_Remap_ADC1_ETRGREG : ADC1 External Trigger Regular Conversion remapping* @arg GPIO_Remap_ADC2_ETRGINJ : ADC2 External Trigger Injected Conversion remapping* @arg GPIO_Remap_ADC2_ETRGREG : ADC2 External Trigger Regular Conversion remapping* @arg GPIO_Remap_ETH : Ethernet remapping (only for Connectivity line devices)* @arg GPIO_Remap_CAN2 : CAN2 remapping (only for Connectivity line devices)* @arg GPIO_Remap_SWJ_NoJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST* @arg GPIO_Remap_SWJ_JTAGDisable : JTAG-DP Disabled and SW-DP Enabled* @arg GPIO_Remap_SWJ_Disable : Full SWJ Disabled (JTAG-DP + SW-DP)* @arg GPIO_Remap_SPI3 : SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices)* When the SPI3/I2S3 is remapped using this function, the SWJ is configured* to Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST. * @arg GPIO_Remap_TIM2ITR1_PTP_SOF : Ethernet PTP output or USB OTG SOF (Start of Frame) connected* to TIM2 Internal Trigger 1 for calibration (only for Connectivity line devices)* If the GPIO_Remap_TIM2ITR1_PTP_SOF is enabled the TIM2 ITR1 is connected to * Ethernet PTP output. When Reset TIM2 ITR1 is connected to USB OTG SOF output. * @arg GPIO_Remap_PTP_PPS : Ethernet MAC PPS_PTS output on PB05 (only for Connectivity line devices)* @arg GPIO_Remap_TIM15 : TIM15 Alternate Function mapping (only for Value line devices)* @arg GPIO_Remap_TIM16 : TIM16 Alternate Function mapping (only for Value line devices)* @arg GPIO_Remap_TIM17 : TIM17 Alternate Function mapping (only for Value line devices)* @arg GPIO_Remap_CEC : CEC Alternate Function mapping (only for Value line devices)* @arg GPIO_Remap_TIM1_DMA : TIM1 DMA requests mapping (only for Value line devices)* @arg GPIO_Remap_TIM9 : TIM9 Alternate Function mapping (only for XL-density devices)* @arg GPIO_Remap_TIM10 : TIM10 Alternate Function mapping (only for XL-density devices)* @arg GPIO_Remap_TIM11 : TIM11 Alternate Function mapping (only for XL-density devices)* @arg GPIO_Remap_TIM13 : TIM13 Alternate Function mapping (only for High density Value line and XL-density devices)* @arg GPIO_Remap_TIM14 : TIM14 Alternate Function mapping (only for High density Value line and XL-density devices)* @arg GPIO_Remap_FSMC_NADV : FSMC_NADV Alternate Function mapping (only for High density Value line and XL-density devices)* @arg GPIO_Remap_TIM67_DAC_DMA : TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices)* @arg GPIO_Remap_TIM12 : TIM12 Alternate Function mapping (only for High density Value line devices)* @arg GPIO_Remap_MISC : Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping, * only for High density Value line devices) * @param NewState: new state of the port pin remapping.* This parameter can be: ENABLE or DISABLE.* @retval None*/
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);/*** @brief Selects the GPIO pin used as EXTI Line.* @param GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines.* This parameter can be GPIO_PortSourceGPIOx where x can be (A..G).* @param GPIO_PinSource: specifies the EXTI line to be configured.* This parameter can be GPIO_PinSourcex where x can be (0..15).* @retval None*/
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);/*** @brief Selects the Ethernet media interface.* @note This function applies only to STM32 Connectivity line devices. * @param GPIO_ETH_MediaInterface: specifies the Media Interface mode.* This parameter can be one of the following values:* @arg GPIO_ETH_MediaInterface_MII: MII mode* @arg GPIO_ETH_MediaInterface_RMII: RMII mode * @retval None*/
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);
以下是这些 GPIO 函数的详细介绍以及如何使用它们的解释:
1. GPIO_DeInit
/*** @brief 将指定的 GPIO 外设寄存器恢复到默认的复位值。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @retval 无*/
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
- 功能:此函数将指定的 GPIO 外设寄存器恢复到它们的默认复位值。用于重置 GPIO 配置,恢复到未配置的状态。
- 用法:如果要将 GPIOA 恢复到初始状态,调用
GPIO_DeInit(GPIOA);
。这样,所有引脚都会复位,原来的配置会被清除。
2. GPIO_AFIODeInit
/*** @brief 将 Alternate Functions(包括重映射、事件控制和 EXTI 配置)寄存器恢复到默认复位值。* @param 无* @retval 无*/
void GPIO_AFIODeInit(void);
- 功能:该函数将用于外设重映射、事件输出、EXTI 线路的 AFIO 配置恢复为默认复位状态。
- 用法:在初始化新的 AFIO 设置之前可以调用,以确保配置干净。例如:
GPIO_AFIODeInit();
。
3. GPIO_Init
/*** @brief 根据指定的配置结构体初始化 GPIO 外设。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @param GPIO_InitStruct: 指向 GPIO_InitTypeDef 结构体的指针,其中包含指定 GPIO 外设的配置信息。* @retval 无*/
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
- 功能:通过配置结构体
GPIO_InitStruct
对 GPIO 端口初始化,比如设置为输入、输出、上拉、下拉等模式。 - 用法:首先创建
GPIO_InitTypeDef
结构体,设置结构体中的各项参数,然后调用此函数。例如:
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
4. GPIO_StructInit
/*** @brief 将 GPIO_InitStruct 结构体的每个成员填充为其默认值。* @param GPIO_InitStruct: 指向将被初始化的 GPIO_InitTypeDef 结构体的指针。* @retval 无*/
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
- 功能:该函数会将
GPIO_InitTypeDef
结构体的成员填充为默认值,以确保结构体初始化时的干净状态。 - 用法:可以调用
GPIO_StructInit(&GPIO_InitStruct);
将结构体的所有成员置为默认值,然后再配置特定的参数。
5. GPIO_ReadInputDataBit
/*** @brief 读取指定输入端口引脚的状态。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @param GPIO_Pin: 指定读取的端口位,可以是 GPIO_Pin_x,其中 x 为 (0..15)。* @retval 输入端口引脚的状态。*/
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 功能:该函数读取指定 GPIO 引脚的输入电平,可以用来检测引脚输入状态(高或低)。
- 用法:调用
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
获取 GPIOA 端口引脚 0 的电平状态。
6. GPIO_ReadInputData
/*** @brief 读取指定 GPIO 输入数据端口的值。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @retval GPIO 输入数据端口的值。*/
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
- 功能:读取整个 GPIO 端口的输入数据。
- 用法:例如
GPIO_ReadInputData(GPIOA);
会返回 GPIOA 端口所有引脚的输入状态。
7. GPIO_ReadOutputDataBit
/*** @brief 读取指定输出端口引脚的状态。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @param GPIO_Pin: 指定读取的端口位,可以是 GPIO_Pin_x,其中 x 为 (0..15)。* @retval 输出端口引脚的状态。*/
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 功能:该函数用于读取 GPIO 输出引脚的当前输出状态。
- 用法:例如
GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_0);
会返回 GPIOA 端口引脚 0 的输出状态。
8. GPIO_ReadOutputData
/*** @brief 读取指定 GPIO 输出数据端口的值。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @retval GPIO 输出数据端口的值。*/
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
- 功能:读取整个 GPIO 端口的输出数据。
- 用法:例如
GPIO_ReadOutputData(GPIOA);
会返回 GPIOA 端口所有引脚的输出状态。
9. GPIO_SetBits
/*** @brief 设置指定的数据端口位。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @param GPIO_Pin: 指定要设置的端口位,可以是 GPIO_Pin_x,其中 x 为 (0..15) 的组合。* @retval 无*/
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 功能:该函数设置指定的 GPIO 引脚为高电平。
- 用法:例如
GPIO_SetBits(GPIOA, GPIO_Pin_0);
将 GPIOA 引脚 0 设为高电平。
10. GPIO_ResetBits
/*** @brief 清除指定的数据端口位。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @param GPIO_Pin: 指定要清除的端口位,可以是 GPIO_Pin_x,其中 x 为 (0..15) 的组合。* @retval 无*/
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 功能:该函数清除指定的 GPIO 引脚为低电平。
- 用法:例如
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
将 GPIOA 引脚 0 设为低电平。
11. GPIO_WriteBit
/*** @brief 设置或清除选定的数据端口位。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @param GPIO_Pin: 指定要写入的端口位,可以是 GPIO_Pin_x,其中 x 为 (0..15)。* @param BitVal: 指定写入的值,可以是 Bit_RESET(低)或 Bit_SET(高)。* @retval 无*/
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
- 功能:根据
BitVal
设置或清除指定的引脚状态。 - 用法:例如
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
将 GPIOA 引脚 0 设置为高。
12. GPIO_Write
/*** @brief 向指定的 GPIO 数据端口写入数据。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @param PortVal: 要写入端口输出数据寄存器的值。* @retval 无*/
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
- 功能:向整个 GPIO 端口写入指定的数据值。
- 用法:例如
GPIO_Write(GPIOA, 0xFFFF);
将 GPIOA 的所有引脚设为高电平。
13. GPIO_PinLockConfig
/*** @brief 锁定 GPIO 引脚配置寄存器。* @param GPIOx: x 可以为 (A..G),用于选择 GPIO 外设。* @param GPIO_Pin: 指定要锁定的端口位,可以是 GPIO_Pin_x,其中 x 为 (0..15) 的组合。* @retval 无*/
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 功能:锁定指定的 GPIO 引脚配置,防止后续更改。
- 用法:调用
GPIO_PinLockConfig(GPIOA, GPIO_Pin_0);
锁定 GPIOA 引脚 0 的配置。
14. GPIO_EventOutputConfig
/*** @brief 配置 GPIO 事件输出。* @param GPIO_PortSource: 选择事件输出端口源,可以是 GPIO_PortSourceGPIOx,其中 x 为 (A..G)。* @param GPIO_PinSource: 选择事件输出引脚源,可以是 GPIO_PinSourcex,其中 x 为 (0..15)。* @retval 无*/
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
- 功能:配置 GPIO 的事件输出源端口和引脚。事件输出允许在特定条件下触发事件,通常与中断结合使用。
- 用法:例如
GPIO_EventOutputConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
设置 GPIOA 的引脚 0 为事件输出。
15. GPIO_EventOutputCmd
/*** @brief 启用或禁用 GPIO 事件输出。* @param NewState: 事件输出的新状态,可以是 ENABLE(启用)或 DISABLE(禁用)。* @retval 无*/
void GPIO_EventOutputCmd(FunctionalState NewState);
- 功能:启用或禁用 GPIO 事件输出功能。
- 用法:例如
GPIO_EventOutputCmd(ENABLE);
启用事件输出,或GPIO_EventOutputCmd(DISABLE);
禁用事件输出。
16. GPIO_PinRemapConfig
/*** @brief 改变指定引脚的映射配置。* @param GPIO_Remap: 选择要重新映射的引脚。* 此参数可以是以下值之一:* @arg GPIO_Remap_SPI1 : SPI1 引脚的备用功能映射* @arg GPIO_Remap_I2C1 : I2C1 引脚的备用功能映射* @arg GPIO_Remap_USART1 : USART1 引脚的备用功能映射* @arg GPIO_Remap_USART2 : USART2 引脚的备用功能映射* @arg GPIO_PartialRemap_USART3 : USART3 部分备用功能映射* @arg GPIO_FullRemap_USART3 : USART3 完全备用功能映射* @arg GPIO_PartialRemap_TIM1 : TIM1 部分备用功能映射* @arg GPIO_FullRemap_TIM1 : TIM1 完全备用功能映射* @arg GPIO_PartialRemap1_TIM2 : TIM2 部分1备用功能映射* @arg GPIO_PartialRemap2_TIM2 : TIM2 部分2备用功能映射* @arg GPIO_FullRemap_TIM2 : TIM2 完全备用功能映射* @arg GPIO_PartialRemap_TIM3 : TIM3 部分备用功能映射* @arg GPIO_FullRemap_TIM3 : TIM3 完全备用功能映射* @arg GPIO_Remap_TIM4 : TIM4 备用功能映射* @arg GPIO_Remap1_CAN1 : CAN1 备用功能映射1* @arg GPIO_Remap2_CAN1 : CAN1 备用功能映射2* @arg GPIO_Remap_PD01 : PD01 备用功能映射* @arg GPIO_Remap_TIM5CH4_LSI : LSI 连接到 TIM5 通道4输入捕获用于校准* @arg GPIO_Remap_ADC1_ETRGINJ : ADC1 外部触发注入转换映射* @arg GPIO_Remap_ADC1_ETRGREG : ADC1 外部触发常规转换映射* @arg GPIO_Remap_ADC2_ETRGINJ : ADC2 外部触发注入转换映射* @arg GPIO_Remap_ADC2_ETRGREG : ADC2 外部触发常规转换映射* @arg GPIO_Remap_ETH : 以太网映射(仅适用于 Connectivity 系列设备)* @arg GPIO_Remap_CAN2 : CAN2 映射(仅适用于 Connectivity 系列设备)* @arg GPIO_Remap_SWJ_NoJTRST : 全 SWJ(启用 JTAG-DP 和 SW-DP,但不包含 JTRST)* @arg GPIO_Remap_SWJ_JTAGDisable : 禁用 JTAG-DP,启用 SW-DP* @arg GPIO_Remap_SWJ_Disable : 禁用全 SWJ(禁用 JTAG-DP 和 SW-DP)* @arg GPIO_Remap_SPI3 : SPI3/I2S3 备用功能映射(仅适用于 Connectivity 系列设备)* 当 SPI3/I2S3 使用此函数重新映射时,SWJ 配置为全 SWJ 启用但不包含 JTRST。* @arg GPIO_Remap_TIM2ITR1_PTP_SOF : 以太网 PTP 输出或 USB OTG SOF(帧起始)连接到 TIM2 内部触发 1 用于校准(仅适用于 Connectivity 系列设备)* 启用 GPIO_Remap_TIM2ITR1_PTP_SOF 时,TIM2 ITR1 连接到以太网 PTP 输出;重置时 TIM2 ITR1 连接到 USB OTG SOF 输出。* @arg GPIO_Remap_PTP_PPS : 以太网 MAC PPS_PTS 输出连接到 PB05(仅适用于 Connectivity 系列设备)* @arg GPIO_Remap_TIM15 : TIM15 备用功能映射(仅适用于 Value 系列设备)* @arg GPIO_Remap_TIM16 : TIM16 备用功能映射(仅适用于 Value 系列设备)* @arg GPIO_Remap_TIM17 : TIM17 备用功能映射(仅适用于 Value 系列设备)* @arg GPIO_Remap_CEC : CEC 备用功能映射(仅适用于 Value 系列设备)* @arg GPIO_Remap_TIM1_DMA : TIM1 DMA 请求映射(仅适用于 Value 系列设备)* @arg GPIO_Remap_TIM9 : TIM9 备用功能映射(仅适用于 XL-density 系列设备)* @arg GPIO_Remap_TIM10 : TIM10 备用功能映射(仅适用于 XL-density 系列设备)* @arg GPIO_Remap_TIM11 : TIM11 备用功能映射(仅适用于 XL-density 系列设备)* @arg GPIO_Remap_TIM13 : TIM13 备用功能映射(仅适用于 High density Value 系列和 XL-density 系列设备)* @arg GPIO_Remap_TIM14 : TIM14 备用功能映射(仅适用于 High density Value 系列和 XL-density 系列设备)* @arg GPIO_Remap_FSMC_NADV : FSMC_NADV 备用功能映射(仅适用于 High density Value 系列和 XL-density 系列设备)* @arg GPIO_Remap_TIM67_DAC_DMA : TIM6/TIM7 和 DAC DMA 请求映射(仅适用于 High density Value 系列设备)* @arg GPIO_Remap_TIM12 : TIM12 备用功能映射(仅适用于 High density Value 系列设备)* @arg GPIO_Remap_MISC : 其他映射(DMA2 通道5位置和 DAC 触发映射,仅适用于 High density Value 系列设备) * @param NewState: 引脚映射的新状态。* 此参数可以是:ENABLE 或 DISABLE。* @retval 无*/
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
- 功能:配置 GPIO 的引脚重映射,将引脚的默认功能重新分配到其他引脚上。这在某些特殊的硬件需求下非常有用。
- 用法:例如
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
将 USART1 的默认引脚重映射到指定引脚上。
17. GPIO_EXTILineConfig
/*** @brief 选择 GPIO 引脚作为外部中断线路的输入。* @param GPIO_PortSource: 选择要配置的端口源,可以是 GPIO_PortSourceGPIOx。* @param GPIO_PinSource: 选择外部中断的引脚源,可以是 GPIO_PinSourcex。* @retval 无*/
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
- 功能:选择 GPIO 引脚来作为外部中断(EXTI)线路的输入源,使得引脚事件可以触发中断。
- 用法:例如
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
将 GPIOA 的引脚 0 配置为外部中断线路的输入源。
2.2 LED灯闪烁
📎3-1 LED闪烁.zip
#include "stm32f10x.h" // Device header
#include "Delay.h"int main(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟//使用各个外设前必须开启时钟,否则对外设的操作无效/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO引脚,赋值为第0号引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度,赋值为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure); /*主循环,循环体内的代码会一直循环执行*/while (1){/*设置PA0引脚的高低电平,实现LED闪烁,下面展示3种方法*/// /*方法1:GPIO_ResetBits设置低电平,GPIO_SetBits设置高电平*/// GPIO_ResetBits(GPIOA, GPIO_Pin_0); //将PA0引脚设置为低电平// Delay_ms(500); //延时500ms// GPIO_SetBits(GPIOA, GPIO_Pin_0); //将PA0引脚设置为高电平// Delay_ms(500); //延时500ms/*方法2:GPIO_WriteBit设置低/高电平,由Bit_RESET/Bit_SET指定*/GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); //将PA0引脚设置为低电平Delay_ms(500); //延时500msGPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); //将PA0引脚设置为高电平Delay_ms(500); //延时500ms// /*方法3:GPIO_WriteBit设置低/高电平,由数据0/1指定,数据需要强转为BitAction类型*/// GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0); //将PA0引脚设置为低电平// Delay_ms(500); //延时500ms// GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1); //将PA0引脚设置为高电平// Delay_ms(500); //延时500ms}
}
大概就是使能APB2总线的RCC时钟,这个GPIOA模块是挂载在APB2总线上的,其有16个端口,要选择哪个gpio引脚、哪种工作模式、速率是根据构造GPIO_InitStructure
结构体来决定
typedef struct
{uint16_t GPIO_Pin; /*!< 指定要配置的GPIO引脚。此参数可以是@ref GPl0 pins define的任意值 */GPIOSpeed_TypeDef GPIO_Speed; /*!< 指定所选引脚的速度此参数可以是@refGPl0Speed_TypeDef的值 */GPIOMode_TypeDef GPIO_Mode; /*!< 指定所选引脚的操作模式。此参数可以是@ref GPI0Mode_TypeDef的值 */
}GPIO_InitTypeDef;
其中对于GPIOMode_TypeDef GPIO_Mode
就有8种工作模式,之前也有提到过:
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;
下面是江科大资料提供的接线图:
需要注意的是低电平来驱动led亮的,因为led是连接着从板子导通出来的电源的:也就是LED引脚的正极(连接着Vdd)和负极(IO口)需要有电压差才能亮。
这个工程还需要添加一个System的文件夹(自己随便取名也行)来存放延迟所需要的相关函数:📎Delay.h📎Delay.c
2.3 LED流水灯
📎3-2 LED流水灯.zip
#include "stm32f10x.h" // Device header
#include "Delay.h"int main(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟//使用各个外设前必须开启时钟,否则对外设的操作无效/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //GPIO引脚,赋值为所有引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度,赋值为50MHzGPIO_Init(GPIOA, &GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数//函数内部会自动根据结构体的参数配置相应寄存器//实现GPIOA的初始化/*主循环,循环体内的代码会一直循环执行*/while (1){/*使用GPIO_Write,同时设置GPIOA所有引脚的高低电平,实现LED流水灯*/GPIO_Write(GPIOA, ~0x0001); //0000 0000 0000 0001,PA0引脚为低电平,其他引脚均为高电平,注意数据有按位取反Delay_ms(100); //延时100msGPIO_Write(GPIOA, ~0x0002); //0000 0000 0000 0010,PA1引脚为低电平,其他引脚均为高电平Delay_ms(100); //延时100msGPIO_Write(GPIOA, ~0x0004); //0000 0000 0000 0100,PA2引脚为低电平,其他引脚均为高电平Delay_ms(100); //延时100msGPIO_Write(GPIOA, ~0x0008); //0000 0000 0000 1000,PA3引脚为低电平,其他引脚均为高电平Delay_ms(100); //延时100msGPIO_Write(GPIOA, ~0x0010); //0000 0000 0001 0000,PA4引脚为低电平,其他引脚均为高电平Delay_ms(100); //延时100msGPIO_Write(GPIOA, ~0x0020); //0000 0000 0010 0000,PA5引脚为低电平,其他引脚均为高电平Delay_ms(100); //延时100msGPIO_Write(GPIOA, ~0x0040); //0000 0000 0100 0000,PA6引脚为低电平,其他引脚均为高电平Delay_ms(100); //延时100msGPIO_Write(GPIOA, ~0x0080); //0000 0000 1000 0000,PA7引脚为低电平,其他引脚均为高电平Delay_ms(100); //延时100ms}
}
2.4 蜂鸣器
📎3-3 蜂鸣器.zip
#include "stm32f10x.h" // Device header
#include "Delay.h"int main(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟//使用各个外设前必须开启时钟,否则对外设的操作无效/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式,赋值为推挽输出模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //GPIO引脚,赋值为第12号引脚GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度,赋值为50MHzGPIO_Init(GPIOB, &GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数//函数内部会自动根据结构体的参数配置相应寄存器//实现GPIOB的初始化/*主循环,循环体内的代码会一直循环执行*/while (1){GPIO_ResetBits(GPIOB, GPIO_Pin_12); //将PB12引脚设置为低电平,蜂鸣器鸣叫Delay_ms(100); //延时100msGPIO_SetBits(GPIOB, GPIO_Pin_12); //将PB12引脚设置为高电平,蜂鸣器停止Delay_ms(100); //延时100msGPIO_ResetBits(GPIOB, GPIO_Pin_12); //将PB12引脚设置为低电平,蜂鸣器鸣叫Delay_ms(100); //延时100msGPIO_SetBits(GPIOB, GPIO_Pin_12); //将PB12引脚设置为高电平,蜂鸣器停止Delay_ms(700); //延时700ms}
}
2.5 按键控制LED
按键:常见的输入设备,按下导通,松手断开
按键抖动:由于按键内部使用的是机械式弹簧片来进行通断的,所以在按下和松手的瞬间会伴随有一连串的抖动(在这个实验中使用延迟手段进行解决)
2.5.1 电路接法
对于左上角的接法,要求输入模式是上拉模式,当按下按钮的时候,接地,也就是PA0输入的是低电平,当松开的时候PA0断开,引脚处于悬浮的状态,无法确定高低电平,这样是不行的,因此得设置为上拉输入模式,保证悬浮的时候默认是高电平。
对于右上角,则是接了一个上拉的电阻,这样在按下按钮的时候,接地,也就是分走了所有的电压,这就使得PA0输入的是低电平;当松开按钮的时候,由于上拉电阻的作用,将PA0拔高,也就是输入的高电平。这两种情况下引脚不会出现悬空的状态。对于这种接法引脚的输入模式可以设置为浮空状态。
2.5.2 编写
Hardware:
- 📎LED.c
- 📎LED.h
- 📎Key.c
- 📎Key.h
User:
- 📎main.c
System:
- 📎Delay.h
- 📎Delay.c
2.6 光敏传感器控制器蜂鸣器
2.6.1 传感器介绍
传感器模块:传感器元件(光敏电阻/热敏电阻/红外接收管等)的电阻会随外界模拟量的变化而变化,通过与定值电阻分压即可得到模拟电压输出,再通过电压比较器进行二值化即可得到数字电压输出
下图从左到右分别是:光敏电阻传感器、热敏电阻传感器、对射式红外传感器、反射式红外传感器
以上图第3个电路为例子,它是模块的内部电路,也就是第5个电路图P1内部有关AO口输出的内部实现。对于该电路的电容在分析的时候可以屏蔽掉,它就个滤波电容,用来保证电路的稳定。
剩下的则是两个电阻了,对于接着Vcc的是定值电阻,对于接着GND的则是传感电阻,这两个其实就形成了上拉电阻和下拉电阻。
只不过对于下拉电阻比较特殊,在整个电路是起着分压的作用,也就是说当传感电阻阻值下降的时候,下拉电阻分到的电压就更多,对于AO口处的电压越小,即会输出低电平,在极端的情况下传感电阻阻值为0,电流完全流入GND(下拉分走了所有的电压),AO输出的电压就为0了。反过来,极端情况下传感电阻阻值为无穷大,也就是下拉处的电路断路了,那么这时候由于上拉电阻的作用,会将AO口的电压拔高(AO口分走了所有的电压),也就是输出高电平了。
简单点就是:当传感电阻阻值下降时,下拉作用增强,AO口输出低电平;阻值上升时,下拉作用减弱,这时候由于上拉起作用,AO口就是高电平。当上拉下拉旗鼓相当的时候,AO就差不多是Vcc/2的电压。
上拉/下拉在电路中是很常见的,其中就有弱上拉/下拉、强上拉/下拉,这里的强和弱就是指阻值的大小。
同时对于传感器还支持二值化的输出,也就是数字信号的输出,主要是P1口的DO引脚,内部是第一个电路图中的U1 LM393芯片的实现:
主要是靠运算放大器,当IN-(倒向输入端)是大于IN+(非倒向输入端)的时候,也就是Ud<0,此时输出端DO就会瞬间升为最小值,反过来就则是升为最大值,从而实现对模拟电压进行二值化处理,使得输入的是模拟电压,输出的(DO)的是数字电压。
而P1处的DO口还接着一个LED,就是用来指示DO口输出的高电平还是低电平,而接着VCC的R5则是为了保证DO默认输出的是高电平。
2.6.2 电路接法
2.6.3 编程
Hardware:
- 📎LightSensor.h
- 📎LightSensor.c
- 📎Buzzer.h
- 📎Buzzer.c
User:
- 📎main.c
System:
- 📎Delay.h
- 📎Delay.c
3.OLED
3.1 介绍
串口调试:通过串口通信,将调试信息发送到电脑端,电脑使用串口助手显示调试信息
显示屏调试:直接将显示屏连接到单片机,将调试信息打印在显示屏上
Keil调试模式:借助Keil软件的调试模式,可使用单步运行、设置断点、查看寄存器及变量等功能
OLED(Organic Light Emitting Diode):有机发光二极管
OLED显示屏:性能优异的新型显示屏,具有功耗低、相应速度快、宽视角、轻薄柔韧等特点
0.96寸OLED模块:小巧玲珑、占用接口少、简单易用,是电子设计中非常常见的显示屏模块
供电:3~5.5V,通信协议:I2C/SPI,分辨率:128*64
3.2 API
函数设计如下,需要用到的时候导入工程就行了:
📎7针脚SPI版本.zip
📎4针脚I2C版本.zip
函数 | 作用 |
---|---|
OLED_Init(); | 初始化 |
OLED_Clear(); | 清屏 |
OLED_ShowChar(1, 1, ‘A’); | 显示一个字符 |
OLED_ShowString(1, 3, “HelloWorld!”); | 显示字符串 |
OLED_ShowNum(2, 1, 12345, 5); | 显示十进制数字 |
OLED_ShowSignedNum(2, 7, -66, 2); | 显示有符号十进制数字 |
OLED_ShowHexNum(3, 1, 0xAA55, 4); | 显示十六进制数字 |
OLED_ShowBinNum(4, 1, 0xAA55, 16); | 显示二进制数字 |
3.3 代码
📎4-1 OLED显示屏.zip
Hardware:
- 📎OLED_Font.h
- 📎Key.c
- 📎Key.h
- 📎LED.c
- 📎LED.h
- 📎OLED.c
- 📎OLED.h
User:
- 📎main.c
相关文章:
stm32之GPIO函数详解和上机实验
目录 1.LED和蜂鸣器1.1 LED1.2 蜂鸣器 2.实验2.1 库函数:RCC和GPIO2.1.1 RCC函数1. RCC_AHBPeriphClockCmd2. RCC_APB2PeriphClockCmd3. RCC_APB1PeriphClockCmd 2.1.2 GPIO函数1. GPIO_DeInit2. GPIO_AFIODeInit3. GPIO_Init4. GPIO_StructInit5. GPIO_ReadInputDa…...
MsQuick编译和使用
MsQuick编译和使用 编译克隆代码使用cmakevs2022编译 使用示例 编译 克隆代码 git clone --recurse-submodules https://github.com/microsoft/msquic.git使用cmakevs2022编译 然后直接configure之后Generate然后打开vs工程编译即可生成动态库 使用示例 #include <s…...
01 ubuntu中wps桌面快捷键无法使用
文章目录 1. 问题描述:2. 解决方法:3. 结果展示4. 参考 1. 问题描述: 2. 解决方法: 添加权限 chmod 755 ./wps-office-prometheus.desktop 右键选择允许运行 3. 结果展示 修改前 修改后 4. 参考 参考1...
云原生后端架构:重塑后端开发的新范式
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:后端开发的新时代正在到来 传统的后端开发常常面临如下挑战:部署流程复杂、环境不一致、系统难以扩展、监控能力薄弱、上线流程缓慢。在企业数字化转型、业务快速迭代的大背景下,这些问题暴露得…...
Linux命令-tcpdump
tcpdump 是一个功能强大的网络数据包捕获和分析工具。以下是 tcpdump 命令的完整参数列表及说明: 参数 -a 将网络地址和广播地址转换为名字 tcpdump -a -i eth0-A 以 ASCII 格式打印所有分组,最小化链路层头部信息 tcpdump -A-b 在数据链路层上选择协议…...
分糖果——牛客
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 幼儿园准备了nnn包糖果,每包糖果里有111、222或333颗美味的糖果。现在需要将这些这些糖果平分给两个表现优异的小朋友以作奖励,为了公平公正,需要…...
L0、L2和L∞范数这三种范数的区别
目录 一、解释 1. L0范数:数一数你有多少件行李 2. L2范数:别把行李塞得太满 3. L∞范数:别带任何超重的东西 一句话总结 二、作用 1. L0范数的作用:做减法,只留最重要的…...
[实战]zynq7000设备树自动导出GPIO
目录 zynq7000设备树自动导出GPIO添加设备树节点验证实验 结论 zynq7000设备树自动导出GPIO 今天无聊,掏出我82年产的microzed玩一玩。玩啥好呢,要不点个灯吧。于是,三下五除二,通过linux sys接口以及echo,很快就点亮…...
java六人打分
import java.util.Scanner;public class HelloWorld {public static void main(String[] args) {//打分平均分System.out.println("请输入六个评分");Scanner sc new Scanner(System.in);double[] score new double[6];for(int i0;i<score.length;i){System.ou…...
量子计算浪潮下的安全应对之法
量子计算凭借其强大的计算能力,被传言能够在极短时间内秒级破解传统计算机需耗时漫长岁月(以万年算)才能解开的密码,成为了近年来人们讨论的热点。这看似高深的科技名词在网络安全中又扮演着何种角色?我们应从当前人们…...
Windows Server 2022 常见问题解答
一、安装与部署 1.1 系统要求 硬件配置:最低需要 1.4 GHz 64 位处理器、512 MB 内存、32 GB 硬盘空间。但在实际生产环境中,为确保系统流畅运行,建议使用 2.0 GHz 以上处理器、8 GB 以上内存和 100 GB 以上硬盘。软件兼容性:与大多数基于 Windows 的企业级应用兼容,但在安…...
项目组合管理PPM
项目组合管理(Project Portfolio Management, PPM)详述 一、定义与核心目标 定义 项目组合管理是通过系统化的方法,对组织的所有项目和项目集进行识别、选择、优先级排序、资源配置和动态监控,以确保其与战略目标一致,并最大化投资回报(ROI)的管理过程。 核心目标 战略…...
自建开源远程协助服务RustDesk —— 筑梦之路
开源项目 # 服务端https://github.com/rustdesk/rustdesk-server.git# 客户端https://github.com/rustdesk/rustdesk.git 搭建服务端 需要使用的端口、协议 hbbs - RustDesk ID 注册服务器 hbbr - RustDesk 中继服务器默认情况下,hbbs 监听 21115(tcp) , 21…...
【android bluetooth 协议分析 11】【AVDTP详解 2】【avdtp 初始化阶段主要回调关系梳理】
在车机中 a2dp 通常情况下作为 sink. 本篇来帮助各位 朋友梳理一下,这部分的初始化流程。 我们着重梳理 native 层的逻辑, framework - java 侧一般比较容易看明白, 暂时不做梳理。 如果需要笨叔梳理的可以在博客评论。 出专门的章节来梳理。…...
C++回顾 day3
宏定义的数据是在预处理发生了替换 const类型的数据是在编译阶段发生的替换 命名空间 namespace 空间名{int a;void func_print(){printf("func_print");}struct Stu{int x;char *y;};//或者其他命名空间 } Space::x 20; cout << Space::x;using Space::x;…...
机器学习算法-分类决策树
分类决策树算法-python实现 数据集 具体方法是:从根结点开始,对结点计算所有可能的特征的信息增益,选择信息增益最大的特征作为结点的特征,由该特征的不同取值建立子节点;再对子结点递归地调用以上方法,构…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(9): 意向形
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(9): 意向形 1、前言(1)情况说明(2)工程师的信仰 2、知识点(1)「~てしまう」=「~ちゃう…...
kotlin与MVVM结合使用总结(一)
一、Kotlin 与 MVVM 结合的核心优势 代码简洁性 数据类(data class)简化 Model 层定义,自动生成equals/hashCode/toString扩展函数简化 View 层逻辑(如点击事件扩展)lateinit/by lazy优化 ViewModel 属性初始化 异步处…...
达妙电机CAN通信及实验
项目进一步往下做的时候,要上实物了,需要用到达妙电机,虽然有说明书和例程,但是STM32控制电机的具体时间还是花了些时间,我的板子和例程的有些区别,中间很多地方都需要进行修改完善,而且还补充了…...
语音合成之四基于LLM的语音合成
基于LLM的语音合成 1.技术架构1.1 LlaSA1.2 CosyVoice (和 CosyVoice2)1.3 SparkTTS 2 特性对比2.1 零样本语音克隆2.2 多语种支持2.3 可控语音生成2.4 计算效率和模型大小 总结 当前,在大型语言模型(Large Language Models,LLMs)…...
Docker Python 官方镜像使用说明(TAG说明)
Docker Python 官方镜像使用说明(TAG说明) 本文将以python的3.12版本,详细讲解官方 Python 镜像 的TAGS含义 官方文档:https://github.com/tuonioooo/docker 🧭 一张图先看懂(最常见 Tag) py…...
Node.js 开发用户登录功能(使用mysql实现)
在 Web 开发中,用户登录功能是一个基础且重要的部分。、 一、环境搭建 在开始开发之前,我们需要搭建好相应的开发环境。以下是所需的工具和库: Node.js:作为 JavaScript 的运行环境,为我们的项目提供支持。mysql2&am…...
程序员学英文之Shipment Claim 运输和索赔
Time is precious , don’t waste your time, you should spend your time on something valuable . 时间很宝贵,不要浪费时间,你应该把时间用在有 价值的事情上。 Dia-1: Shipment by Voyage Charter 租船装运 1. May I know when your bo…...
python实战项目64:selenium采集软科中国大学排名数据
python实战项目64:selenium采集软科中国大学排名数据 一、项目需求二、流程分析三、完整代码一、项目需求 本项目的需求是使用selenium采集软科中国大学排名的数据。网站首页如下: 抓取此网页数据一般有两种方式,一种是直接发requests请求,我们这里采用的是使用selenium控…...
Linux服务器:在ufw防火墙设置这套规则sudo ufw allow from 172.0.0.0/8,为什么容器就可以访问宿主机的服务了?
在 Docker 环境中,容器默认使用 桥接网络(bridge),宿主机和容器之间的通信会受到防火墙(如 ufw)的限制。当你执行 sudo ufw allow from 172.0.0.0/8 后,容器可以访问宿主机上的服务,原因如下: 1. Docker 默认使用 172.x.x.x 网段 Docker 默认会创建一个 docker0 网桥…...
Google搜索技巧
谷歌搜索 1. 使用双引号 (" ") 精确匹配短语 ● 例子:"人工智能的定义" ● 作用:确保搜索结果中包含完全匹配的短语,而不是单独的单词。 2. 使用减号 (-) 排除特定词语 ● 例子:苹果 -水果 ● 作用&…...
Reactor编程模型介绍
Reactor 模型是一种基于事件驱动的编程模型,广泛应用于高并发网络服务器的设计中。它通过事件循环和回调机制,将事件的处理逻辑从主线程中解耦出来,从而实现高效的异步 I/O 操作。Reactor 模型的核心思想是利用一个或多个事件分发器(Reactor)来监听各种事件(如 I/O 事件、…...
C++笔记-stack_queue(含deque,priority_queue,仿函数的讲解)
一.stack和queue的基本使用 stack和queue就是我们之前所学的栈和队列,这两个和之前学的vector,list不太一样: 这是vector和list的,注意第一行中写的containers,代表这两个都是容器,但是: stac…...
意见反馈留言二维码制作
意见反馈对于工作整改具有重要作用,在工作中一味埋头苦干不如抬头多听听反馈声音。而传统的反馈内容投递后,因为繁琐性和时效性的枷锁,往往石沉大海,不知何时才能得到回应,这就导致反馈信息的延迟,一些时效…...
扣子智能体平台深度解读:功能剖析与全流程工作流详解
在上一篇文章中,我们已经带大家了解了“智能体”这一概念的内涵,并通过扣子智能体平台的各大模块做了初步介绍,同时用一个简单的示例演示了如何构建和部署第一个智能体。那篇文章打好了基础,让大家对智能体的基本组成与工作方式有…...
C语言五子棋项目
头文件与宏定义 #include <graphics.h> #include <conio.h> graphics.h:EasyX 图形库,提供图形绘制功能(画线、画圆、显示文字等)。 conio.h:提供控制台输入输出函数(这里只是为了兼容性&…...
建筑安全员 A 证与 C 证:差异决定职业方向
在建筑行业的职业发展道路上,安全员 A 证和 C 证就像两条不同的岔路,它们之间的差异,在很大程度上决定了从业者的职业方向。 从证书性质和用途来看,A 证是从业资格证书,更像是一把开启安全管理高层岗位的 “金钥匙”。…...
长连接、短连接与WebSocket的基本知识
目录 前言正文 前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 爬虫神器,无代码爬取,就来:bright.cn Java基本知识: java框架 零基础从入门到精通的学习路线 附…...
MySQL常见问题解答
一、安装与配置问题 1. 安装失败(权限 / 依赖 / 端口冲突) 权限问题:以管理员身份运行安装程序(Windows)或使用sudo(Linux)。依赖缺失: Windows 需安装 Visual C++ Redistributable(如 2013 版)。Linux 通过包管理器安装依赖(如libaio、perl)。端口冲突: 检查 33…...
Codeforces Round 1019 (Div. 2)(ABCD)
A. Common Multiple 翻译: 给你一个整数数组 a1,a2,...,an。如果存在一个数组 y1,y2,...,ym,且 y 的元素是不同的(换句话说,对于所有 1≤i<j≤m 的数组,yi≠yj),并且对于所有 1≤i≤m 的数组…...
爬虫学习总结
通过前几次课,我们学习了爬虫的相关基础知识。 以下是我对爬虫学习做的一些总结: 一、认识爬虫:开启数据抓取之旅 1.1 什么是网络爬虫 网络爬虫就像是一个不知疲倦的 “数据搬运工”,它能按照预先设定的规则,自动…...
UE5的 Modify Curve 蓝图节点
In Unreal Engine’s Animation Blueprints, the Modify Curve node lets you drive and alter any named Animation Curve on your character at runtime. The Apply Mode setting on that node controls how the “new” value you feed in (via the added curve‐input pin)…...
鸿蒙中的并发线程间通信、线程间通信对象
目录 并发线程间通信1. 线程间通信对象1.1 普通对象1.2 ArrayBuufer对象1.3 SharedArrayBuffer对象1.4 Transferable对象(NativeBinding对象)1.5 Sendable对象简介异步锁ASON解析与生成共享容器共享模块Sendable对象冻结 2 线程间通信场景2.1 使用TaskPo…...
Elasticsearch内核探秘:从Shard分配到网络通信的深度实践指南
#作者:孙德新 文章目录 一、底层模块深入解析之shard allocation1、shard allocation的介绍2、cluster level shard allocation介绍3、disk-based shard allocation介绍4、shard allocation awareness5、shard allocation filtering6、node下线时的shard延迟分配7、…...
Vue3 模板语法
目录 一、插值语法 {{ }} 二、核心指令 三、动态属性绑定 四、事件修饰符 五、条件渲染 vs 列表渲染总结 六、最佳实践 示例 1:插值语法 & 基础绑定 示例 2:条件渲染 示例 3:列表渲染 示例 4:事件处理 示例 5&…...
第1节:Backtrader到底是个啥?能干嘛?
——“框架在手,天下我有;不是吹,Backtrader真香警告!” 🐣 一句话简介 Backtrader 是一个 专门为量化交易打造的 Python 回测框架,说白了,它就是一个量化策略“模拟器控制台评审团”ÿ…...
Java基础第21天-正则表达式
正则表达式是对字符串执行模式匹配的技术 如果想灵活的运用正则表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为: 限定符选择匹配符分组组合和反向引用符特殊字符字符匹配符定位符 转义号\\:在我们使用正则表达式去检索某些特…...
【Pandas】pandas DataFrame mod
Pandas2.2 DataFrame Binary operator functions 方法描述DataFrame.add(other)用于执行 DataFrame 与另一个对象(如 DataFrame、Series 或标量)的逐元素加法操作DataFrame.add(other[, axis, level, fill_value])用于执行 DataFrame 与另一个对象&…...
【哈希表】1399. 统计最大组的数目
1399. 统计最大组的数目 - 力扣(LeetCode) 给你一个整数 n 。请你先求出从 1 到 n 的每个整数 10 进制表示下的数位和(每一位上的数字相加),然后把数位和相等的数字放到同一个组中。 请你统计每个组中的数字数目&…...
57、Spring Boot 最佳实践
Spring Boot 最佳实践 一. 开发规范与代码风格 编写高质量的代码不仅需要功能的实现,还需要遵循一定的规范和代码风格,以提高代码的可读性、可维护性和协作效率。以下是 Spring Boot 开发中的一些关键规范和代码风格建议。 1. 代码命名规范 在编写代码时,命名是非常重要的…...
Java高级:数据库访问优化
系列文章目录 Java高级部分 JDBC编程 文章目录 系列文章目录前言一、编写属性文件:二、编写DBUtil工具类:三、使用DBUtil工具类:总结 前言 通过我之前发的数据库连接,数据库连接https://blog.csdn.net/2301_81776550/article/det…...
升级xcode16之后react-native-zip-archive不兼容,unsupported option ‘-G‘
问题 升级xcode到16之后,xcode build报错:unsupported option -G for target x86_64-apple-ios13.4-simulator (in target RNZipArchive from project Pods) 出现原因 在 React Native 项目中,当你将 Xcode 升级到 16 后,可能会遇到 RNZipArchive 相关的编译错误,特别是…...
基于MTF的1D-2D-CNN-LSTM-Attention时序图像多模态融合的故障识别,适合研究学习(Matlab完整源码和数据),附模型研究报告
基于MTF的1D-2D-CNN-LSTM-Attention时序图像多模态融合的故障识别,适合研究学习(Matlab完整源码和数据),附模型研究报告 目录 基于MTF的1D-2D-CNN-LSTM-Attention时序图像多模态融合的故障识别,适合研究学习࿰…...
逻辑漏洞安全
逻辑漏洞是指由于程序逻辑不严导致一些逻辑分支处理错误造成的漏洞。 在实际开发中,因为开发者水平不一没有安全意识,而且业务发展迅速内部测试没有及时到位,所以常常会出现类似的漏洞。 由于开发者/设计者在开发过程中,由于代码…...
基于PaddleOCR对图片中的excel进行识别并转换成word优化(二)
0、原图 一、优化地方 计算行的时候,采用概率分布去统计差值概率比较大的即为所要的值。 def find_common_difference(array):"""判断数组中每个元素的差值是否相等,并返回该差值:param array: 二维数组,其中每个元素是一个…...