GPIOC->ODR |=(0<<2); // 总线操作,即操作整个寄存器.
在51单片机中
P0=0xFE; //总线操作.
sbit LED1=P0^0; //位操作,即操作寄存器中的某一位.
LED1 =0;
在STM32中并没有sbit这样的关键字.但是我们可以用位带操作实现位操作.
位带操作
在 STM32 中,有两个地方实现了位带,一个是 SRAM 区(存放代码)的最低 1MB 空间,令一个是外设区最低 1MB 空间。这两个 1MB 的空间除了可以像正常的 RAM 一样操作外,他们还有自己的位带别名区,位带别名区把这 1MB 的空间的每一个位膨胀成一个 32 位的字(4个字节),当访问位带别名区的这些字时,就可以达到访问位带区某个比特位的目的.
位带操作的公式
外设位带区与外设位带别名区的地址转换: AlisaAddr=0x42000000+(A-0x40000000)*8*4+n*4
SRAM位带区与SRAM位带别名区地址转换: AlisaAddr=0x22000000+(A-0x20000000)*8*4+n*4
其中:A:表示操作的那个位寄存器所在的寄存器地址
n:位号(第几位)
对上面式子的解释:
AlisaAddr=位带别名区基地址+(寄存器地址-寄存器基地址)[偏移多少个字节]*8[一个字节8位]*4[每个位膨胀4个字节] [这是第0位]+n*4[第n个位膨胀的字节说]
理解要点:位带区的一个位在位带别名区膨胀位4个字节
位带操作的总公式
AlisaAddr =((addr&0xF0000000)+0x02000000+((addr&0x00FFFFFF)<<5)+(bitnum<<2))
其中:addr:要操作的寄存器地址.(寄存器映射表中,每个外设地址+偏移地址)
bitnum:位号,即寄存器的第几位
对上面式子的解释: addr&0xF0000000:为了取出4和2,用来区分是外设还是SRAM.然后+0x20000000就等于外设/SRAM位带别名区的起始地址
add&0x00FFFFFF0x00FFFFFF:屏蔽掉高2位,外设位带区的高地址位0x4010 0000,SRAM的位带区高地址为0x2010 0000, (0x4010 0000 –0x40000000) 和(0x2010 0000-0x200000)在求偏移地址相减的时候只要第四位有效,所以就把剩下的高两位屏蔽掉,剩下的6位与F相与即可.
点亮LED的源码
我们在上次的代码中继续添加:
main为:
#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h> #include "bsp_led.h" #include "bsp_key.h" #define SOFT_DELAY Delay(0x0FFFFF); //void Delay(__IO u32 nCount); #define GPIOC_ODR_Addr (GPIOC_BASE+0x0C) #define PCout(bitnum) *(unsigned int *)((GPIOC_ODR_Addr&0xF0000000)+0x02000000+((GPIOC_ODR_Addr &0x00FFFFFF)<<5)+(bitnum<<2)) #define GPIOC_IDR_Addr (GPIOC_BASE+0x08) #define PCIn(bitnum) *(unsigned int *)((GPIOC_IDR_Addr&0xF0000000)+0x02000000+((GPIOC_IDR_Addr &0x00FFFFFF)<<5)+(bitnum<<2)) void Delay( uint32_t count){ for( ;count!=0;count--); } int main(void) { // 来到这里的时候,系统的时钟已经被配置成72M。 LED_GPIO_Config(); LED_OFF; KEY_LED_Config(); while(1){ if(PCIn(13)==KEY_ON){ while(PCIn(13)==KEY_ON) ; LED_TOGGLE; } } }