赞
踩
这段时间又是期末考时期,之前没有学懂的东西又双叒叕忘记了~
我知道如果用库函数来操控底层比较轻松,但是作为51单片机的过渡,还是想使用更符合之前习惯的方法来操控硬件!
在上一篇最小系统的使用中已经建过了,就是建个文件夹放三个文件
main.c
stm32f10x.h
startup_stm32f10x_hd.s
第一个就是这篇博客所需要操作的主函数所处的位置,第二个是放自定义的寄存器的地址。这两个文件都是空文件。第三个是STM32F103单片机的启动文件,不同种类的单片机的启动文件不同。
定时器
中断
串口
DMA
总线
电源管理
…………
这些功能的操控都需要靠相应的寄存器单元的设置。几百个寄存器,几乎每个都是32位的,单单从bit上来考虑似乎不太现实!
在进行寄存器操作的时候,的确是需要按位来操控的,但是许多寄存器不是每一位都是独特的,所以存在许多相似之处使得我们只需要操控几个bit进而操控整个寄存器!
\;
\;
以下是stm32f103相关功能寄存器在内存上的地址
block 0 Code 0x0000 0000 - 0x1FFF FFFF Aliased to Flash or system memory depending on BOOT pins[0x0000 0000 - 0x0007 FFFF] Reserved[0x0008 0000 - 0x07FF FFFF] Flash[0x0800 0000 - 0x0807 FFFF] Reserved[0x0808 0000 - 0x1FFF EFFF] System memory[0x1FFF F000 - 0x1FFF F7FF] Option Bytes[0x1FFF F800 - 0x1FFF F80F] block 1 SRAM 0x2000 0000 - 0x3FFF FFFF SRAM(64 kB aliased by bit-banding)[0x2000 0000 - 0x2000 FFFF] Reserved[0x2001 0000 - 0x3FFF FFFF] block 2 Peripherals 0x4000 0000 - 0x5FFF FFFF APB1总线 TIM2[0x4000 0000 - 0x4000 03FF] TIM3[0x4000 0400 - 0x4000 07FF] TIM4[0x4000 0800 - 0x4000 0BFF] TIM5[0x4000 0C00 - 0x4000 0FFF] TIM6[0x4000 1000 - 0x4000 13FF] TIM7[0x4000 1400 - 0x4000 17FF] Reserved[0x4000 1800 - 0x4000 27FF] RTC[0x4000 2800 - 0x4000 2BFF] WWDG[0x4000 2C00 - 0x4000 2FFF] IWDG[0x4000 3000 - 0x4000 33FF] Reserved[0x4000 3400 - 0x4000 37FF] SPI2/I2S2[0x4000 3800 - 0x4000 3BFF] SPI3/I2S3[0x4000 3C00 - 0x4000 3FFF] Reserved[0x4000 4000 - 0x4000 43FF] USART2[0x4000 4400 - 0x4000 47FF] USART3[0x4000 4800 - 0x4000 4BFF] UART4[0x4000 4C00 - 0x4000 4FFF] UART5[0x4000 5000 - 0x4000 53FF] I2C1[0x4000 5400 - 0x4000 57FF] I2C2[0x4000 5800 - 0x4000 5BFF] USB register[0x4000 5C00 - 0x4000 5FFF] Shared USB/CAN SRAM 512 bytes[0x4000 6000 - 0x4000 63FF] BxCAN[0x4000 6400 - 0x4000 67FF] Reserved[0x4000 6800 - 0x4000 6BFF] BKP[0x4000 6C00 - 0x4000 6FFF] PWR[0x4000 7000 - 0x4000 73FF] DAC[0x4000 7400 - 0x4000 77FF] Reserved[0x4000 7800 - 0x4000 FFFF] APB2总线 AFIO[0x4001 0000 - 0x4001 03FF] EXTI[0x4001 0400 - 0x4001 07FF] PortA[0x4001 0800 - 0x4001 0BFF] PortB[0x4001 0C00 - 0x4001 0FFF] PortC[0x4001 1000 - 0x4001 13FF] PortD[0x4001 1400 - 0x4001 17FF] PortE[0x4001 1800 - 0x4001 1BFF] PortF[0x4001 1C00 - 0x4001 1FFF] PortG[0x4001 2000 - 0x4001 23FF] ADC1[0x4001 2400 - 0x4001 27FF] ADC2[0x4001 2800 - 0x4001 2BFF] TIM1[0x4001 2C00 - 0x4001 2FFF] SPI1[0x4001 3000 - 0x4001 33FF] TIM8[0x4001 3400 - 0x4001 37FF] USART1[0x4001 3800 - 0x4001 3BFF] ADC3[0x4001 3C00 - 0x4001 3FFF] Reserved[0x4001 4000 - 0x4001 7FFF] SDIO[0x4001 8000 - 0x4001 83FF] Reserved[0x4001 8400 - 0x4001 FFFF] AHB总线 DMA1[0x4002 0000 - 0x4002 03FF] DMA2[0x4002 0400 - 0x4002 07FF] Reserved[0x4002 0400 - 0x4002 1FFF] RCC[0x4002 1000 - 0x4002 13FF] Reserved[0x4002 1400 - 0x4002 1FFF] Flash interface[0x4002 2000 - 0x4002 23FF] Reserved[0x4002 2400 - 0x4002 2FFF] CRC[0x4002 3000 - 0x4002 33FF] Reserved[0x4002 4400 - 0x5FFF FFFF] block 3 FSMC bank1&bank2 06000 0000 - 0x7FFF FFFF FSMC bank1 NOR/PSRAM 1[0x6000 0000 - 0x63FF FFFF] FSMC bank1 NOR/PSRAM 2[0x6400 0000 - 0x67FF FFFF] FSMC bank1 NOR/PSRAM 3[0x6800 0000 - 0x6BFF FFFF] FSMC bank1 NOR/PSRAM 4[0x6C00 0000 - 0x6FFF FFFF] FSMC bank2 NAND(NAND1)[0x7000 0000 - 0x7FFF FFFF] block 4 FSMC bank3&bank4 0x8000 0000 - 0x9FFF FFFF FSMC bank3 NAND(NAND2)[0x8000 0000 - 0x8FFF FFFF] FSMC bank4 PCCARD[0x9000 0000 - 0x9FFF FFFF] block 5 FSMC register 0xA000 0000 - 0xBFFF FFFF FSMC register[0xA000 0000 - 0xA000 0FFF] Reserved[0xA000 1000 - 0xBFFF FFFF] block 6 Not used 0xC000 0000 - 0xDFFF FFFF block 7 Cortex-M3's internal Peripherals 0xE000 0000 - 0xFFFF FFFF
block2区域的首地址就是外设的基地址。
根据输入/输入的区别、上下拉电阻的区别、开漏推挽的区别可以将GPIO的工作模式分为8类。
浮空输入
模拟输入(不经过施密特触发器,也没有上下拉电阻)
上拉输入
下拉输入
开漏输出
开漏复用输出
推挽输出
推挽复用输出
(输出模式下,施密特触发器都是开启状态)
每偏移0x04就是偏移一个32位!
x表示可选数0~15!
GPIOx地址
GPIOx_CRL[bias 0x00]设置0~7引脚模式
GPIOx_CRH[bias 0x04]设置8~15引脚模式
GPIOx_IDR[bias 0x08]设置输入数据寄存器,高16位保留
GPIOx_ODR[bias 0x0C]设置输出数据寄存器,高16位保留
GPIOx_BSRR[bias 0x10]设置/清除寄存器
GPIOx_BRR[bias 0x14]清除寄存器,高16位保留
GPIOx_LCKR[bias 0x18]设置锁定寄存器,高15位保留
对于GPIOx_CRL和GPIOx_CRH来说,每四个位控制一个引脚的工作模式。四个位分别是 CNFx[1:0] 和 MODEx[1:0]
MODEx[1:0]
CNFx[1:0]
\;
\;
\;
GPIOx_IDR是端口输入寄存器,在低16位里(高16位保留),其位对应的值就是对应引脚的值——在只读模式下。
GPIOx_ODR是端口输出寄存器,在低16位里(高16位保留),其位对应的值就是对应引脚的值——在可读可写模式下。
GPIOx_BSRR是设置端口值的寄存器,高16位对应引脚的零,低16位对应引脚的一。如果对应的位为一,那么如果是高16位这表示置零,如果是低16位表示置一。
GPIOx_BRR是端口值清零寄存器。低16位(高16位保留)置一表示对应引脚清零。
GPIOx_LCKR是端口配置锁定。 一般用不到这个。
这里写的程序是控制GPIOC亮灯,而GPIOC是APB2总线上的外设,所以需要配置APB2外设时钟的使能寄存器。
对应的位为一,即使对应的外设使能。
//stm32f10x.h #define PERIPH_BASE ((unsigned int)0x40000000) #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) #define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) #define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00) #define GPIOC_CRH *(unsigned int*)(GPIOC_BASE+0x04) #define GPIOC_IDR *(unsigned int*)(GPIOC_BASE+0x08) #define GPIOC_ODR *(unsigned int*)(GPIOC_BASE+0x0C) #define GPIOC_BSRR *(unsigned int*)(GPIOC_BASE+0x10) #define GPIOC_BRR *(unsigned int*)(GPIOC_BASE+0x14) #define GPIOC_LCKR *(unsigned int*)(GPIOC_BASE+0x18) #define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) #define RCC_BASE (AHBPERIPH_BASE + 0x1000) #define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18)
//main.c #include "stm32f10x.h" void delay(unsigned int i){ while(i--){ __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); } } void SystemInit(){} int main(){ int k=0; //use APB2 External RCC //open GPIO clock RCC_APB2ENR|=1<<4; //8 ports //CNF>00 MODE>11 //GPIOC_CRL&=~(0x0f<<(4*0)); //GPIOC_CRL|=(3<<(4*0)); GPIOC_CRL = 0x33333333; //use BSRR //set right ODR be one //GPIOC_BSRR=(1<<(16+0)); while(1){ GPIOC_BSRR=~(1<<k); //light the led delay(0xf000); GPIOC_BSRR=~(1<<(k+16)); //dark the led delay(0xf000); if(k--==0) k=7; } }
显示效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。