ARM——操作示例

操作流程:
     

 

 

c60a0a5b5cc346928b2920b1a7b90efa.png

38a07679d8844d8b86ce8f156a78f3fa.png

 

d604ecca8f6d4e05a683d431ca84254b.png

233538bc677a414ebc5d52c8af358692.png

一、实现一个led亮灯

(1)GPIO:可编程的输入输出引脚
每一组io都有一个寄存GP*CON控制引脚作用,每个io都有2个位,控制引脚作用
每一组io都有一个寄存GP*DAT控制引脚数据,每个io都有1个位,控制引脚数据

(2)如图:
在原理图中找到控制led的引脚端口,进而对引脚进行相应的输出配置。
从下图可以看出当引脚为低电平时,LED会被点亮,所以需要寻找对应的nLED_1(对应的GPIO口)
1a021338f7b94841a0ec3ebf036a3175.png

如下图,led对应的寄存器时GPB寄存器,
因此使能GPBCON,使GPBDA的第五位输出低电平/

fe1d188c90be4e25a357eedaac28f25c.png

再从下图中,将GPB的第十位和第十一位设置为01(输出模式)

8b32c9347c514516a6b52b38fc8ad69d.png

代码如下:

7317d7c2c9ed44abafa8494691b6c2f9.png

06e81a0b59f24f578d3179c71f64844d.png

volatile的用法

在C语言中,volatile是一个类型限定符,它的主要作用是告诉编译器,它所修饰的变量的值可能会在程序执行期间被意外地改变(通常是由程序外部的因素导致的),因此编译器不应该对这些变量进行优化,包括不应该将这些变量的值缓存到寄存器中,而应该每次访问时都从内存中重新读取其值。volatile的用法主要包括以下几个方面:

1. 防止编译器优化

编译器在编译代码时,为了提高程序的执行效率,会对代码进行优化,包括将一些常量或变量的值缓存到寄存器中以便快速访问。但在多线程编程、硬件交互等场景中,变量的值可能会被外部因素(如其他线程、硬件设备等)意外地改变。如果编译器对这些变量进行了优化,就可能导致程序无法正确地反映这些外部变化,进而产生错误。通过使用volatile关键字,可以阻止编译器对这些变量进行优化,确保每次访问时都能从内存中读取到最新的值。

2. 保证内存可见性

在多线程编程中,一个线程对共享变量的修改需要能够被其他线程所感知,这就是所谓的内存可见性。如果编译器对共享变量进行了优化(如缓存到寄存器中),就可能导致其他线程无法及时感知到该变量的最新值。通过使用volatile关键字,可以确保每个线程在访问共享变量时都能从内存中读取到最新的值,从而保证内存的可见性。

3. 嵌入式系统编程

在嵌入式系统编程中,经常需要直接与硬件进行交互,包括读取硬件寄存器的值、向硬件寄存器写入数据等。由于硬件寄存器的值可能会被外部设备或中断服务例程等意外地改变,因此需要使用volatile关键字来修饰这些寄存器变量,以确保每次访问时都能从硬件寄存器中读取到最新的值。

4. 调试和性能分析

在某些情况下,为了关闭编译器的某些优化以便更好地进行调试或性能分析,也可以使用volatile关键字。通过将某个变量声明为volatile,可以确保编译器在编译时不会对该变量进行优化,从而保留更多的程序原始信息供调试或性能分析使用。

二、实现流水灯

类似的添加延时函数即可实现蜂鸣器的效果。

extern int asm_add(int x, int y);
#define WTCON   *(volatile unsigned long *)0x53000000UL
#define GPBCON  *(volatile unsigned long *)0x56000010UL	 //11:10  0b 01
#define GPBDAT  *(volatile unsigned long *)0x56000014UL

void c_deal_swi(unsigned int num)
{
	switch (num)
	{
		case 1:break;
		case 2:break;
		case 3:break;
		default:
		break;
	}
}
//延时函数
void delay(int i)
{
	while(i--);
}

void led_init(void)
{
	//配置GDB5引脚功能为输出

	GPBCON &= ~(0xff << 10);
	GPBCON |= (0x55 << 10);

	//将GDB5引脚电平置高
	 GPBDAT |= (0x55 << 5);
	 }
   
void led_on(unsigned int i)
{
	//将GDB5引脚设置为低电平
	  GPBDAT &= ~(1 << 5<<(i-1));
}
void led_off(unsigned int i)
{
	//将GDB5引脚设置为高电平
	 GPBDAT |= (1 << 5<<(i-1));
}

int main(void)
{

//	led_init();
    int i =0;
	WTCON = 0x0;  //看门狗置0
	while(1)
	{
	led_init();
    	for(i=1;i<5;i++)
    	{
		led_on(i);
		delay(30000);	
		led_off(i);
    	}
	}
	return 0;
}

三、实现按健控制等

(1)设置GPIO为输入模式

从下图 可以看出当K1被按下,EINT8被设置为输入模式,通过该引脚可以判断按键是否被按下;

ab82b92fb5d847138c3c967918bb0d98.png

1de85f3d1f8d4f74845fbf7c78aad3b7.png

extern int asm_add(int x, int y);

int myadd(int a, int b)
{
	int c = asm_add(a, b);
	return c;
}

void c_deal_swi(unsigned int num)
{
	switch(num)
	{
		case 1:break;
		case 2:break;
		case 3:break;
		default:break;
	}
}

#define GPBCON *(volatile unsigned long *)0x56000010UL
#define GPBDAT *(volatile unsigned long *)0x56000014UL
#define GPFCON *(volatile unsigned long *)0x56000050UL
#define GPFDAT *(volatile unsigned long *)0x56000054UL
#define GPGCON *(volatile unsigned long *)0x56000060UL
#define GPGDAT *(volatile unsigned long *)0x56000064UL
#define WTCON *(volatile unsigned long *)0x53000000UL
#define WTCNT *(volatile unsigned long *)0x53000008UL

void watchdog_close(void)
{
	WTCON = 0x8021;
	WTCON &= ~0x1;
}

void watchdog_init(void)
{
	
	WTCON = 0x8021;
}

void watchdog_feed(void)
{
	WTCNT = 0x8000;
}

void button_init(void)
{
	GPGCON &= ~(0x3f << 8);
	GPFCON &= ~0x3;

}

void led_init(void)
{
	GPBCON &= (~(0xff << 10));
	GPBCON |= (0x55 << 10);
	
	
	GPBDAT |= 0xf << 5;
}
void delay(unsigned long us)
{
	while(us--)
		;
}
void led_on(unsigned int n)
{
	//GPB5Òý½ÅµçƽÖõÍ
	GPBDAT &= ~(1 << (n + 4));
	delay(30000);
}

void led_off(unsigned int n)
{
	GPBDAT |= (1 << (n + 4));
	delay(30000);
}
void led_off_all(void)
{
	GPBDAT |= (0xf << 5);
}
/*
void delay_ms(unsigned long ms)
{
    unsigned int i;

    while(ms--) 
		{
      for(i = 0; i < 1200; i++)
			{
				
			}
    }
}
*/

void button_led1(void)
{
	unsigned long tmp,tmp1,tmp2,tmp3;
	
	while(1)
	{
		tmp = GPGDAT & 0x1;
		tmp1 = GPFDAT & 0x1 <<4;
		tmp2 = GPFDAT & 0x1 <<5;
		tmp3 = GPFDAT & 0x1 <<6;
		
	if(tmp == 0)
	{
		GPBDAT &= ~(1 << 5);
		delay(500);
	}
	else if(tmp1 == 0)
	{
		GPBDAT &= ~(1 << 6);
		delay(500);
	}
	else if(tmp2 == 0)
	{
		GPBDAT &= ~(1 << 7);
		delay(500);
	}
	else if(tmp3 == 0)
	{
		GPBDAT &= ~(1 << 8);
		delay(500);
	}
	else
	{
		led_off_all();
	}
  }
}
int main(void)
{
	int i = 0;
	watchdog_close();
	led_init();
	button_init();
	/*while(1)
	{
		i = 4;
		while(i)
		{
			led_on(i);
		
		  led_off(i);

		  i--;
			
			watchdog_feed();
		}
  
  }*/
	button_led1();
}

三、时钟

46a1b1afb91d4863a2c99adfaa6519dd.png

 pwm定时器

4c4fe7af718f44a590562dba432333ce.png

 

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值