画龙点睛:可能是厂商等公司之类的组织, 简化cortex-m 开发, 与特定的硬件绑定。
包引入,
stm32f1xx-hal
GPIO(General Purpose Input/Output)是一种可编程的数字信号引脚,用于微控制器和微处理器与外部设备进行交互。
- 功能:
输入: GPIO 可以配置为输入模式,读取外部信号的状态(例如按钮、开关或传感器)。
输出: GPIO 可以配置为输出模式,向外部设备发送信号(例如点亮 LED、驱动继电器)。
可编程: GPIO 的功能可以通过软件进行配置,可以根据需要设置为输入或输出,并可以选择不同的逻辑电平。
中断: 一些 GPIO 引脚可以配置为中断源,响应外部事件(例如,按下按钮时触发中断)。 - 常见应用:
控制 LED 灯、继电器或其他电器。
读取按钮或开关的状态。
接收传感器信号,例如温度、湿度等。
同样是点亮led:
#![allow(clippy::empty_loop)]
#![deny(unsafe_code)]
#![no_main]
#![no_std]
use cortex_m::delay::Delay;
use cortex_m::peripheral::SYST;
use panic_halt as _;
use cortex_m_rt::entry;
use stm32f1xx_hal::{pac, prelude::*};
#[entry]
fn main() -> ! {
///获取微控制器的外设实例 p,所有硬件外设的访问都是通过这个实例进行。
let p = pac::Peripherals::take().unwrap();
///获取 GPIOC 的控制,将其拆分为更具体的控制结构,用于访问各个引脚
let mut gpioc = p.GPIOC.split();
// 获取 FLASH 和 RCC
let mut flash = p.FLASH.constrain();
let mut rcc = p.RCC.constrain();
///用条件编译(cfg)功能,根据启用的特性设置 GPIO 引脚的状态。
/// 如果启用了 stm32f100 特性,则将 PC9 引脚设置为推挽输出并设置为高电平。
// #[cfg(feature = "stm32f100")]
// gpioc.pc9.into_push_pull_output(&mut gpioc.crh).set_high();
//
// #[cfg(feature = "stm32f101")]
// gpioc.pc9.into_push_pull_output(&mut gpioc.crh).set_high();
//
// #[cfg(any(feature = "stm32f103", feature = "stm32f105", feature = "stm32f107"))]
// gpioc.pc13.into_push_pull_output(&mut gpioc.crh).set_low();
// 根据特性选择用于 LED 的引脚
// 使用 `let` 语句将引脚的信息动态分析放在一个一起
let mut led = if cfg!(feature = "stm32f103") || cfg!(feature = "stm32f105") || cfg!(feature = "stm32f107") {
gpioc.pc13.into_push_pull_output(&mut gpioc.crh).unwrap() // 使用 PC13
} else {
gpioc.pc9.into_push_pull_output(&mut gpioc.crh).unwrap() // 使用 PC9
};
let clocks = rcc.cfgr.freeze(&mut flash.acr);
let mut delay = Delay::new(SYST::take().unwrap(), clocks); // 获取 SYST
loop {
// 切换 LED 状态
led.set_high().unwrap();
delay.delay_ms(500_u32); // 等待 500 毫秒
led.set_low().unwrap();
delay.delay_ms(500_u32); // 等待 500 毫秒
}
}
GPIO(通用输入/输出)引脚在嵌入式系统中用途广泛,除了控制 LED 外,还有许多其他功能和应用。以下是一些常见的使用场景:
- 开关控制
通过 GPIO 控制电源开关,打开或关闭设备(如继电器)。 - 按键输入
读取按钮或开关的状态,例如单击、双击等。这在用户界面中非常常见。 - 信号检测
读取传感器的输出,例如温度传感器、湿度传感器或光传感器,获取环境数据。 - PWM 输出
通过 GPIO 生成脉宽调制信号,控制电机速度或 LED 亮度。 - 中断处理
配置 GPIO 引脚作为中断源,响应外部事件(例如按钮按下时触发中断)。 - 通信接口
一些 GPIO 引脚可以配置为串行通信接口,如 UART、I2C、SPI 等,进行数据传输。 - 状态指示
使用 GPIO 控制状态指示灯,显示系统的工作状态或故障提示。 - 数据采集
通过 GPIO 接收外部设备(如传感器或模块)的数字信号进行数据采集。 - 控制外部设备
驱动蜂鸣器、风扇或其他外部电器设备的开关。 - 模拟输入(ADC)
一些 GPIO 引脚可以配置为模拟输入,用于连接模拟传感器并读取其输出值。 - 通信协议支持
GPIO 可以用于实现各种协议,如 1-Wire、I2C、SPI、UART 等,以连接外部模块或传感器。
ADC(Analog-to-Digital Converter)是一种电子设备,用于将模拟信号转换为数字信号,使微控制器可以处理和分析这些信号。
- 功能:
模拟输入: ADC 能够接收连续的模拟电压信号(如从传感器输出的电压)。
转换: ADC 将模拟信号转换为相应的数字值,以便微控制器进行处理。
分辨率: ADC 的分辨率通常以比特(例如 8-bit、10-bit、12-bit 等)来表示,分辨率越高,能够区分的电压变化越小。 - 常见应用:
读取温度传感器、光传感器或其他模拟传感器的输出电压。
实现音频信号处理,将音频信号转换为数字形式进行处理。
控制系统中的电压监测,例如电池电量检测。
#![no_std]
#![no_main]
use panic_halt as _;
use cortex_m_rt::entry;
use stm32f1xx_hal::{adc, pac, prelude::*};
use cortex_m_semihosting::hprintln;
const LIGHT_THRESHOLD: u16 = 200; // 设置光照阈值
#[entry]
fn main() -> ! {
// 获取外设
let p = pac::Peripherals::take().unwrap();
let mut flash = p.FLASH.constrain();
let rcc = p.RCC.constrain();
// 配置 ADC 时钟
let clocks = rcc.cfgr.adcclk(2.MHz()).freeze(&mut flash.acr);
// 初始化 ADC
let mut adc1 = adc::Adc::adc1(p.ADC1, clocks);
// 初始化 GPIO
let mut gpiob = p.GPIOB.split();
let mut gpioc = p.GPIOC.split();
// 将 PB0 配置为模拟输入
let mut ldr_pin = gpiob.pb0.into_analog(&mut gpiob.crl);
// 将 PC13 配置为推挽输出 (用于控制 LED)
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
loop {
// 读取光传感器的值
let light_value: u16 = adc1.read(&mut ldr_pin).unwrap();
hprintln!("Light Value: {}", light_value).unwrap();
// 根据光照值控制 LED
if light_value < LIGHT_THRESHOLD {
led.set_high().unwrap(); // 光照低,打开 LED
} else {
led.set_low().unwrap(); // 光照足够,关闭 LED
}
// 可选的延迟,避免过于频繁读取
cortex_m::asm::delay(1_000_000);
}
}
#![deny(unsafe_code)]
#![no_main]
#![no_std]
use panic_semihosting as _;
use cortex_m_rt::entry;
use stm32f1xx_hal::{adc, pac, prelude::*};
use cortex_m_semihosting::hprintln;
#[entry]
fn main() -> ! {
// Acquire peripherals
let p = pac::Peripherals::take().unwrap();
///是闪存控制器的约束配置,用于后续时钟设置。
let mut flash = p.FLASH.constrain();
///是时钟控制器的约束配置,用于配置系统时钟和 ADC 时钟。
let rcc = p.RCC.constrain();
// Configure ADC clocks
// Default value is the slowest possible ADC clock: PCLK2 / 8. Meanwhile ADC
// clock is configurable. So its frequency may be tweaked to meet certain
// practical needs. User specified value is be approximated using supported
// prescaler values 2/4/6/8.
let clocks = rcc.cfgr.adcclk(2.MHz()).freeze(&mut flash.acr);
//hprintln! 用于半主机环境下打印 ADC 时钟频率。
hprintln!("adc freq: {}", clocks.adcclk());
// Setup ADC
let mut adc1 = adc::Adc::adc1(p.ADC1, clocks);
#[cfg(any(feature = "stm32f103", feature = "connectivity"))]
let mut adc2 = adc::Adc::adc2(p.ADC2, clocks);
// Setup GPIOB
///GPIOB: 这是微控制器上一个具体的 GPIO 端口,通常有多个端口,如 GPIOA、GPIOB 等。每个端口包含多个引脚(比如 PA0, PA1, PB0, PB1等)。
/// 引脚: 在这个例子中,pb0 表示 GPIOB 上的第0个引脚。类似地,pb1 就是 GPIOB 的第1个引脚。
let mut gpiob = p.GPIOB.split();
// Configure pb0, pb1 as an analog input
///将指定的引脚(在这里是 pb0)配置为模拟输入模式
/// 在 STM32 系列微控制器中,每个 GPIO 端口都有一个控制寄存器,通常分为两个部分:CRL 和 CRH。
/// gpiob.crl 控制的是引脚 0 到引脚 7(低位端)。
/// gpiob.crh 控制的是引脚 8 到引脚 15(高位端)。
let mut ch0 = gpiob.pb0.into_analog(&mut gpiob.crl);
#[cfg(any(feature = "stm32f103", feature = "connectivity"))]
let mut ch1 = gpiob.pb1.into_analog(&mut gpiob.crl);
loop {
let data: u16 = adc1.read(&mut ch0).unwrap();
hprintln!("adc1: {}", data);
#[cfg(any(feature = "stm32f103", feature = "connectivity"))]
{
let data1: u16 = adc2.read(&mut ch1).unwrap();
hprintln!("adc2: {}", data1);
}
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。