PART5——RTC——RCC——IIC、OLED——ADC、TIMER

位带操作(默认开漏输出,浮空输入)

在STM32微控制器中,可以通过位带(Bit-Banding)操作来对端口进行输入输出控制。位带操作允许直接对单个位进行读写,而无需修改整个寄存器的内容,这在嵌入式系统中尤为有用,可以提高代码的效率和可读性。
位带操作模式的基本原理:

1.位带别名区域:STM32微控制器的某些外设寄存器的每个位都可以映射到一个单独的位带别名(Bit-Band Alias)。这意味着,可以使用位带地址来访问单个位,而不是直接操作整个寄存器。
2.寄存器映射:每个位带别名区域的起始地址是固定的,通常是原始寄存器的地址加上一个偏移量。对于STM32,这些位带别名区域的地址可以通过计算得到,或者使用CMSIS提供的宏来简化访问。
3.优势:使用位带操作可以简化对端口的位级控制,特别是在需要频繁地修改单个位而不影响其他位时,具有很大的便利性和效率。

位带操作示例:
假设我们要在STM32中控制GPIOA的第5个引脚(PA5),实现设置为输出并置位和清除位的功能。
#include "stm32f10x.h"  // STM32标准库头文件

int main() {
    // 设置PA5为输出模式
    GPIOA->CRL &= ~(0b1111 << (5 * 4));  // 清除PA5的配置
    GPIOA->CRL |= (0b0010 << (5 * 4));   // 设置PA5为推挽输出 10

    // 使用位带操作设置PA5为高电平
    *((volatile unsigned long*)(0x42000000 + (0x20000 * 32) + (5 * 4))) = 1;

    // 使用位带操作清除PA5为低电平
    *((volatile unsigned long*)(0x42000000 + (0x20000 * 32) + (5 * 4))) = 0;

    while (1) {
        // 循环执行其他任务
    }
    return 0;
}

在上面的示例中:

4.GPIOA->CRL 用于配置GPIOA端口的寄存器,以设置PA5的引脚模式。
5.使用位带操作通过计算地址来直接控制PA5的单个位。具体地址的计算包括基地址 0x42000000,位带别名区域的起始地址偏移 0x20000,和寄存器位偏移 (5 * 4)。

通过这种方式,可以非常高效地对STM32微控制器的GPIO端口进行单个位的读写操作,从而实现精确的控制和管理。

寄存器

9

一、RTC

是一个独立的定时器(32位向上计数),有一 组连续计数的计数器,可提供时钟日历的功能。修LL1在相应软件配置下,改计数器 的值可以重新设置系统当前的时间和日期。
外部无电源时由VBAT(纽扣电池)供电。若都没电则数据清除
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 其配置步骤比较复杂,这时可以参考帮助文档,其中不认识的函数可以查阅固件函数库用户手册。

二、 RCC

在这里插入图片描述

三、ADC

在这里插入图片描述
8在这里插入图片描述

在这里插入图片描述

  • 查询法
#include "stm32f10x.h"  // 包含STM32标准库的头文件

void ADC_Configuration(void) {
   
    ADC_InitTypeDef ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能 ADC 和 GPIO 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置 PA0 为模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // ADC1 配置
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  // 独立模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;       // 禁止扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;  // 开启连续转换模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  // 数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;  // 采样通道数量
    ADC_Init(ADC1, &ADC_InitStructure);

    // 配置 ADC 通道
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);

    // 使能 ADC1
    ADC_Cmd(ADC1, ENABLE);

    // 开启 ADC1 的软件启动转换
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

int main(void) {
   
    ADC_Configuration();

    while (1) {
   
        // 等待 ADC 转换完成
        while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

        // 读取 ADC1 转换结果寄存器
        uint16_t adc_value = ADC_GetConversionValue(ADC1);

        // 处理 ADC 值,比如输出到串口或者其他操作
    }
}

  • 中断法
#include "stm32f10x.h"  // 包含STM32标准库的头文件

uint16_t adc_value;  // 全局变量,用于存储ADC转换结果

void ADC_Configuration(void) {
   
    ADC_InitTypeDef ADC_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 使能 ADC 和 GPIO 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置 PA0 为模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // ADC1 配置
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;  // 独立模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;       // 禁止扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;  // 开启连续转换模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;  // 数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;  // 采样通道数量
    ADC_Init(ADC1, &ADC_InitStructure);

    // 配置 ADC 通道
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0<
### STM32F103 电子计时器时钟教程 #### 高级控制定时器 TIM1 和 TIM8 的时钟源选择 对于STM32F103系列微控制器而言,高级控制定时器TIM1和TIM8支持多种时钟源的选择。这些时钟源可以通过APB2总线获取,并经过可编程预分频器处理后供给定时器使用。具体来说,可以选择内部高速时钟(HSI)、外部高速时钟(HSE)或者其他低功耗模式下的时钟源来驱动这两个定时器的工作[^1]。 ```c // 设置TIM1的时钟源为HSE/2 RCC_ClocksTypeDef RCC_ClockFreq; RCC_GetClocksFreq(&RCC_ClockFreq); uint32_t PrescalerValue = (uint32_t)((SystemCoreClock / 2) / 72000000) - 1; // 假设目标频率为72MHz TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_DeInit(TIM1); TIM_InternalClockConfig(TIM1); TIM_TimeBaseStructure.TIM_Period = 9999; TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); ``` #### 实时时钟 RTC 功能配置 STM32F103还集成了一个实时时钟模块RTC,该模块能够提供精确的时间信息并具备日历功能。为了使能RTC工作,通常需要连接一颗32.768kHz的晶体振荡器,并且当主电源关闭时可通过VBAT供电保持运行状态。通过适当设置寄存器参数可以让RTC每秒钟触发一次中断事件,进而实现秒级别的精准计时服务[^2]。 ```c // 初始化RTC void RTC_Init(void){ PWR_BackupAccessCmd(ENABLE); RCC_LSEConfig(RCC_LSE_ON); while(!RCC_LSEReady()){} RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); } ``` #### 不同应用场景下的时钟源选取建议 针对不同的应用需求,合理挑选合适的时钟源至关重要。如果项目对时间准确性要求不高,则可以直接采用内置RC振荡器作为系统时钟;反之则推荐选用更为稳定的外部晶振以减少因温度变化等因素引起的偏差。特别是在涉及到数据传输协议如UART/IIC/SPI等接口通讯场景下,高稳定性的时钟信号有助于提高通信质量,降低误码率的发生概率[^3]。 #### SysTick 定时器简介及其基本操作方法 除了上述提到的各种硬件定时资源之外,Cortex-M3架构自带了一个名为SysTick的简易型滴答定时装置。此设备拥有24位宽度的倒计数机制,一旦到达零点便会自动重新加载初始值继续循环减小直至再次归零为止。开发者可以根据实际所需调整其周期长度以及对应的回调函数逻辑以便于完成各种延时任务或是构建操作系统底层调度框架等功能[^4]。 ```c // 启动SysTick定时器 void Start_SysTick_Timer(uint32_t ticks){ if(ticks > 0){ SysTick->LOAD = ticks - 1UL; NVIC_SetPriority(SysTick_IRQn,(1<<__NVIC_PRIO_BITS)-1); SysTick->VAL = 0UL; SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_CLKSOURCE_Msk; } } // 关闭SysTick定时器 void Stop_SysTick_Timer(){ SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; SysTick->VAL = 0UL; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值