在ARM架构下,stm32的流水灯可以用三种方法实现:
在这里只提供源代码(不知道如何新建工程或者在Proteus内实现仿真的可以参照我的上一篇博客)
基于ARM,用汇编语言在Keil_V5和Proteus仿真下实现点灯操作
1、汇编语言直接对寄存器操作GPIO口
BIT4 EQU 0X00000010
GPIOC EQU 0X40011000
GPIOC_CRL EQU 0X40011000
GPIOC_CRH EQU 0X40011004
GPIOC_ODR EQU 0X4001100C
GPIOC_BSRR EQU 0X40011010
GPIOC_BRR EQU 0X40011014
IOPCEN EQU BIT4
RCC_APB2ENR EQU 0X40021018
AREA MYCODE, CODE
ENTRY
EXPORT __main
__main
LDR R1, =RCC_APB2ENR
LDR R0, [R1] ;读
LDR R2, =IOPCEN ;进入IOPCEN的地址
ORR R0, R2 ;改
STR R0, [R1] ;写,使能GPIOC时钟
LOOP
MOV R0, #0x00000003
LDR R1, =GPIOC_CRL ;进入配置低寄存器
STR R0, [R1] ;对低四位进行操作,0011,推挽输出,50MHZ
NOP
NOP
LDR R1, =GPIOC_ODR ;进入配置高寄存器
LDR R2, =0x0 ;输出led0
STR R2,[R1] ;输出状态
MOV R0, #4500 ;4500/9=500ms
BL.W DELAY_NMS
EOR R2, #LED0
MOV R0, #0x00000030 ;对高四位进行操作
LDR R1, =GPIOC_CRL
STR R0, [R1]
NOP
NOP
LDR R1, =GPIOC_ODR
LDR R2, =0x1 ;输出led1
STR R2,[R1]
MOV R0, #4500
BL.W DELAY_NMS
EOR R2, #LED0
MOV R0, #0x00000300
LDR R1, =GPIOC_CRL
STR R0, [R1]
NOP
NOP
LDR R1, =GPIOC_ODR
LDR R2, =0x2 ;输出led2
STR R2,[R1]
MOV R0, #4500
BL.W DELAY_NMS
EOR R2, #LED0
MOV R0, #0x00003000
LDR R1, =GPIOC_CRL
STR R0, [R1]
NOP
NOP
LDR R1, =GPIOC_ODR
LDR R2, =0x4 ;输出led3
STR R2,[R1]
MOV R0, #4500
BL.W DELAY_NMS
EOR R2, #LED0
MOV R0, #0x00030000
LDR R1, =GPIOC_CRL
STR R0, [R1]
NOP
NOP
LDR R1, =GPIOC_ODR
LDR R2, =0x8 ;输出led4
STR R2,[R1]
MOV R0, #4500
BL.W DELAY_NMS
EOR R2, #LED0
MOV R0, #0x00300000
LDR R1, =GPIOC_CRL
STR R0, [R1]
NOP
NOP
LDR R1, =GPIOC_ODR
LDR R2, =0x10 ;输出led5
STR R2,[R1]
MOV R0, #4500
BL.W DELAY_NMS
EOR R2, #LED0
MOV R0, #0x03000000
LDR R1, =GPIOC_CRL
STR R0, [R1]
NOP
NOP
LDR R1, =GPIOC_ODR
LDR R2, =0x20 ;输出led6
STR R2,[R1]
MOV R0, #4500
BL.W DELAY_NMS
EOR R2, #LED0
MOV R0, #0x30000000
LDR R1, =GPIOC_CRL
STR R0, [R1]
NOP
NOP
LDR R1, =GPIOC_ODR
LDR R2, =0x40 ;输出led7
STR R2,[R1]
MOV R0, #4500
BL.W DELAY_NMS
EOR R2, #LED0
B LOOP
DELAY_NMS
PUSH {R1} ;2T
DELAY_NMSLOOP
SUB R0, #1
MOV R1,#100
DELAY_ONEUS
SUB R1, #1
NOP
NOP
NOP
CMP R1, #0
BNE DELAY_ONEUS
CMP R0, #0
BNE DELAY_NMSLOOP
POP {R1}
BX LR
NOP
END
2、C语言直接对寄存器操作GPIO口
#include"stm32f10x.h"
void delay_ms(unsigned short Number);
#define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010)
int main(void)
{
while(1)
{
RCC->APB2ENR |=RCC_APB2Periph_GPIOC;
GPIOC->CRL &=0XFFFFFFF0;
GPIOC->CRL |=0X00000003;
GPIOC->ODR &=~(0x1);
delay_ms(50);
GPIOC->ODR |=0x1;
delay_ms(50);
GPIOC->CRL &=0XFFFFFF0F;
GPIOC->CRL |=0X00000030;
GPIOC->ODR &=~(0x2);
delay_ms(50);
GPIOC->ODR |=0x2;
delay_ms(50);
GPIOC->CRL &=0XFFFFF0FF;
GPIOC->CRL |=0X00000300;
GPIOC->ODR &=~(0x4);
delay_ms(50);
GPIOC->ODR |=0x4;
delay_ms(50);
GPIOC->CRL &=0XFFFF0FFF;
GPIOC->CRL |=0X00003000;
GPIOC->ODR &=~(0x8);
delay_ms(50);
GPIOC->ODR |=0x8;
delay_ms(50);
GPIOC->CRL &=0XFFF0FFFF;
GPIOC->CRL |=0X00030000;
GPIOC->ODR &=~(0x10);
delay_ms(50);
GPIOC->ODR |=0x10;
delay_ms(50);
GPIOC->CRL &=0XFF0FFFFF;
GPIOC->CRL |=0X00300000;
GPIOC->ODR &=~(0x20);
delay_ms(50);
GPIOC->ODR |=0x20;
delay_ms(50);
GPIOC->CRL &=0XF0FFFFFF;
GPIOC->CRL |=0X03000000;
GPIOC->ODR &=~(0x40);
delay_ms(50);
GPIOC->ODR |=0x40;
delay_ms(50);
GPIOC->CRL &=0X0FFFFFFF;
GPIOC->CRL |=0X30000000;
GPIOC->ODR &=~(0x80);
delay_ms(50);
GPIOC->ODR |=0x80;
delay_ms(50);
}
}
void delay_ms(unsigned short int Number)
{
unsigned int i;
while(Number--){
i=12000;while(i--);
}
}
3、使用标准固件库操作GPIO端口
如果出现未定义的错误,则在Define输入USE_STDPERIPH_DRIVER
#include "stm32f10x.h"
void delay_ms(unsigned short int Number);
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //输出模式,通用推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //输出速度50MHZ
GPIO_Init(GPIOC, &GPIO_InitStructure);
while(1)
{
GPIO_ResetBits(GPIOC,GPIO_Pin_0); //LED0亮
GPIO_SetBits(GPIOC,GPIO_Pin_1);
GPIO_SetBits(GPIOC,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_3);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
GPIO_SetBits(GPIOC,GPIO_Pin_5);
GPIO_SetBits(GPIOC,GPIO_Pin_6);
GPIO_SetBits(GPIOC,GPIO_Pin_7);
delay_ms(40);
GPIO_SetBits(GPIOC,GPIO_Pin_0); //LED0灭
GPIO_ResetBits(GPIOC,GPIO_Pin_1); //LED1亮
GPIO_SetBits(GPIOC,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_3);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
GPIO_SetBits(GPIOC,GPIO_Pin_5);
GPIO_SetBits(GPIOC,GPIO_Pin_6);
GPIO_SetBits(GPIOC,GPIO_Pin_7);
delay_ms(40);
GPIO_SetBits(GPIOC,GPIO_Pin_0);
GPIO_SetBits(GPIOC,GPIO_Pin_1); //LED1灭
GPIO_ResetBits(GPIOC,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_3);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
GPIO_SetBits(GPIOC,GPIO_Pin_5);
GPIO_SetBits(GPIOC,GPIO_Pin_6);
GPIO_SetBits(GPIOC,GPIO_Pin_7);
delay_ms(40);
GPIO_SetBits(GPIOC,GPIO_Pin_0);
GPIO_SetBits(GPIOC,GPIO_Pin_1);
GPIO_SetBits(GPIOC,GPIO_Pin_2);
GPIO_ResetBits(GPIOC,GPIO_Pin_3);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
GPIO_SetBits(GPIOC,GPIO_Pin_5);
GPIO_SetBits(GPIOC,GPIO_Pin_6);
GPIO_SetBits(GPIOC,GPIO_Pin_7);
delay_ms(40);
GPIO_SetBits(GPIOC,GPIO_Pin_0);
GPIO_SetBits(GPIOC,GPIO_Pin_1);
GPIO_SetBits(GPIOC,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_3);
GPIO_ResetBits(GPIOC,GPIO_Pin_4);
GPIO_SetBits(GPIOC,GPIO_Pin_5);
GPIO_SetBits(GPIOC,GPIO_Pin_6);
GPIO_SetBits(GPIOC,GPIO_Pin_7);
delay_ms(40);
GPIO_SetBits(GPIOC,GPIO_Pin_0);
GPIO_SetBits(GPIOC,GPIO_Pin_1);
GPIO_SetBits(GPIOC,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_3);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
GPIO_ResetBits(GPIOC,GPIO_Pin_5);
GPIO_SetBits(GPIOC,GPIO_Pin_6);
GPIO_SetBits(GPIOC,GPIO_Pin_7);
delay_ms(40);
GPIO_SetBits(GPIOC,GPIO_Pin_0);
GPIO_SetBits(GPIOC,GPIO_Pin_1);
GPIO_SetBits(GPIOC,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_3);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
GPIO_SetBits(GPIOC,GPIO_Pin_5);
GPIO_ResetBits(GPIOC,GPIO_Pin_6);
GPIO_SetBits(GPIOC,GPIO_Pin_7);
delay_ms(40);
GPIO_SetBits(GPIOC,GPIO_Pin_0);
GPIO_SetBits(GPIOC,GPIO_Pin_1);
GPIO_SetBits(GPIOC,GPIO_Pin_2);
GPIO_SetBits(GPIOC,GPIO_Pin_3);
GPIO_SetBits(GPIOC,GPIO_Pin_4);
GPIO_SetBits(GPIOC,GPIO_Pin_5);
GPIO_SetBits(GPIOC,GPIO_Pin_6);
GPIO_ResetBits(GPIOC,GPIO_Pin_7);
delay_ms(40);
}
}
void delay_ms(unsigned short int Number)
{
unsigned int i;
while(Number--){
i=12000;
while(i--);
}
}
以上三种方法都是直接控制八个灯,并未使用位移算法,若有简易的方法,烦请大家指教。