目录
位带操作(默认开漏输出,浮空输入)
在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端口进行单个位的读写操作,从而实现精确的控制和管理。
寄存器
一、RTC
是一个独立的定时器(32位向上计数),有一 组连续计数的计数器,可提供时钟日历的功能。修LL1在相应软件配置下,改计数器 的值可以重新设置系统当前的时间和日期。
外部无电源时由VBAT(纽扣电池)供电。若都没电则数据清除
- 其配置步骤比较复杂,这时可以参考帮助文档,其中不认识的函数可以查阅固件函数库用户手册。
二、 RCC
三、ADC
- 查询法
#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<