;亮点STM32汇编语言跑马灯,只有1个程序
;LED端口在GPIOC6,7,8,9
;#define led_gpio GPIOC
;#define led1 GPIO_Pin_6 //led1 连接在GIIOC_6
;#define led2 GPIO_Pin_7 //led2 连接在GIIOC_7
;#define led3 GPIO_Pin_8 //led3 连接在GIIOC_8
;#define led4 GPIO_Pin_9 //led4 连接在GIIOC_9
;brightpoint.taobao.com
LED_GPIO EQU 0x40011000 ;GPIOE 地址
GPIOC_CRL EQU 0x40011000 ;低配置寄存器
GPIOC_CRH EQU 0x40011004 ;高配置寄存器
GPIOC_ODR EQU 0x4001100C ;输出,偏移地址0Ch
GPIOC_BSRR EQU 0X40011010 ;低置位,高清除偏移地址10h
GPIOC_BRR EQU 0X40011014 ;清除,偏移地址14h
IOPCEN EQU 0X00000010 ;GPIOC使能位 在APB2的位5
RCC_APB2ENR EQU 0x40021018 ;APB2使能寄存器的地址
STACK_TOP EQU 0X20002000 ;堆栈的栈顶在0X20002000
AREA RESET,CODE,READONLY ;这里开始是中断向量表
DCD STACK_TOP ;MSP主堆栈指针
DCD START ;复位,PC初始值,复位后从START开始运行
ENTRY ;入口,指示开始执行
START
;与在这里观察 RCC_CR=0x00005283 8M内时钟
;(1) 使能GPIOC
LDR R1,=RCC_APB2ENR
LDR R0,[R1] ;读RCC->APB2ENR内容 RO=RCC->APB2ENR;
LDR R2,=IOPCEN ;
ORR R0,R2 ;置位R0位2
STR R0,[R1] ;写RCC->APB2ENR,使能GPIOC时钟
;(2) 设置GPIOC端口寄存器CRL和CRH,使每个引脚都是推挽输出 CNF[1:0]=00 MODE[1:0]=11
LDR R0,=0x33333333
LDR R1,=GPIOC_CRL
STR R0,[R1]
LDR R1,=GPIOC_CRH
STR R0,[R1] ;PC[0..15] 16个引脚均设置成推挽式输出
;(3) 初始的时候
LDR R1,=GPIOC_ODR
LDR R0,=1<<9 ;初始时LED4点亮 ,因为LED4是PC9,对应ODR寄存器BIT9
LOOP
STR R0,[R1]
PUSH {R0}
MOV R0,#300
BL.W DELAY_NMS ;延时300ms
POP {R0}
BL.W ByteRor1 ;状态位右循环移一位
B LOOP
;子程序,将R0右移动,
;0000 0010 0000 0000 led4亮 1<<9
;0000 0001 0000 0000 led3亮 1<<8
;0000 0000 1000 0000 led2亮 1<<7
;0000 0000 0100 0000 led1亮 1<<6
;0000 0000 0010 0000 就越界了,要赋值1<<9
ByteRor1
LSR R0,R0,#1 ;R1=RO>>1
CMP R0,#0X00000020 ;只有4个灯,移动到这里就移出去了
BEQ OutB
BX LR
OutB
LDR R0,=1<<9 ;如果移出去了就回到LED4亮
BX LR
;以下代码拷贝自网络未删改,只做补充说明
;延时R0(us),误差0.5us
;延时超过100us时,误差0.5/R0小于0.5%
DELAY_NUS
SUB R0,#1
NOP
NOP
NOP
CMP R0,#0
BNE DELAY_NUS ;跳时3个周期 8M内时钟,8个周期1US
BX LR ;3个周期
;延时R0(ms),误差((R0-1)*4+12)/8us
;延时较长时,误差小于0.1%
DELAY_NMS
PUSH {R1} ;2个周期
DELAY_NMSLOOP
SUB R0,#1
MOV R1,#1000 ;R1循环1000次,1MS
DELAY_ONEUS
SUB R1,#1
NOP
NOP
NOP
CMP R1,#0
BNE DELAY_ONEUS ;R1循环结束
CMP R0,#0
BNE DELAY_NMSLOOP ;R0循环N次,N毫秒
POP {R1}
BX LR
END