day12:位带操作
STM32F103RCT6支持位带操作,但是现在的ST的高端产品已经不支持位带操作了,因为ARM公司提供的内核已经不支持,所以ST公司也无能为力。

位带操作指的是操作IO口的位,比如51单片机当中的sbit P0^0 = 0;(或者P0^0 = 0x00;),这样,可以直接控制某个位输出高电平或者低电平
外设与SRAM位带区与位带别名区的地址统一用一个公式 表示
((addr & 0xF0000000)+0x02000000+((addr & 0x000FFFFF)<<5)+(bitnum<<2))
addr:要操作的位所在寄存器的地址,怎么查询到?这是寄存器的端口的真实地址(等于基地址+地址偏移,查看STM32的官方手册)
bitnum:位号,即在寄存器的第几位。比如D4这个LED的端口是PC2,那bitnum=2。

下面,使用位带操作来实现PC2和PC3两个LED灯的流水灯效果
=============================================

bsp_led.h:
/* 和LED功能模块相关的程序 */ #ifndef __BSP_LED_H__ #define __BSP_LED_H__ #include "stm32f10x.h" /*宏定义*/ #define GPIO_CLK_D4 RCC_APB2Periph_GPIOC // 时钟 #define GPIO_PORT_D4 GPIOC // C端口 #define GPIO_PIN_D4 GPIO_Pin_2 // PC2引脚 #define GPIO_CLK_D5 RCC_APB2Periph_GPIOC // 时钟 #define GPIO_PORT_D5 GPIOC // C端口 #define GPIO_PIN_D5 GPIO_Pin_3 // PC2引脚 /*配置GPIO*/ void LED_GPIO_Config(void); #endif /*__BSP_LED_H__*/
bsp_led.c:
/* 和LED功能模块相关的程序头文件 */
#include "./led/bsp_led.h" /*绝对路径,也可在Options for target中设置头文件*/
/*GPIO初始化*/
void LED_GPIO_Config(void)
{
/*外设结构体*/
GPIO_InitTypeDef GPIO_InitStruct_D4, GPIO_InitStruct_D5;
/*第一步:打开外设的时钟,看stm32f10x_rcc.c这个文件的RCC_APB2PeriphClockCmd函数介绍*/
RCC_APB2PeriphClockCmd(GPIO_CLK_D4, ENABLE);
/*第二步:配置外设的初始化结构体*/
GPIO_InitStruct_D4.GPIO_Pin = GPIO_PIN_D4; // PC2的那盏LED灯(D4)的引脚
GPIO_InitStruct_D4.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
GPIO_InitStruct_D4.GPIO_Speed = GPIO_Speed_10MHz; // 引脚速率
GPIO_InitStruct_D5.GPIO_Pin = GPIO_PIN_D5; // PC3的那盏LED灯(D5)的引脚
GPIO_InitStruct_D5.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
GPIO_InitStruct_D5.GPIO_Speed = GPIO_Speed_10MHz; // 引脚速率
/*第三步:调用外设初始化函数,把配置好的结构体成员写到寄存器里面*/
GPIO_Init(GPIO_PORT_D4, &GPIO_InitStruct_D4);
GPIO_Init(GPIO_PORT_D5, &GPIO_InitStruct_D5);
}
main.c:
#include "stm32f10x.h"
#include "./led/bsp_led.h"
/*
* 参数宏定义:
* 后面是公式,直接拷贝进来,输入寄存器端口的真实地址和位的序号就可以了
*/
#define PCout(n) (*(unsigned int*)(((GPIOC_BASE+0X0C) & 0xF0000000)+0x02000000+(((GPIOC_BASE+0X0C) & 0x000FFFFF)<<5)+(n<<2)))
// 延迟函数
void delay(unsigned int i)
{
for(; i!=0; i--);
}
int main(void)
{
/* LED初始化 */
LED_GPIO_Config();
while(1)
{
/* D4亮,D5灭 */
PCout(2) = 0;
PCout(3) = 1;
delay(0XFFFFF);
/* D5亮,D4灭 */
PCout(2) = 1;
PCout(3) = 0;
delay(0XFFFFF);
}
}
实验现象:
D4和D5两个LED灯轮流闪烁,实现了流水灯(跑马灯)的效果

浙公网安备 33010602011771号