基于ARM,使用汇编语言在keil和proteus下实现流水灯操作

在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

基于ARM,使用汇编语言在keil和proteus下实现流水灯操作_第1张图片

#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--);
	}
}

以上三种方法都是直接控制八个灯,并未使用位移算法,若有简易的方法,烦请大家指教。

你可能感兴趣的:(汇编,Keil_v5,Peoteus,arm,stm32)