ARM——操作示例

操作流程:

一、实现一个led亮灯

(1)GPIO:可编程的输入输出引脚

每一组io都有一个寄存GP*CON控制引脚作用,每个io都有2个位,控制引脚作用

每一组io都有一个寄存GP*DAT控制引脚数据,每个io都有1个位,控制引脚数据

(2)如图:

在原理图中找到控制led的引脚端口,进而对引脚进行相应的输出配置。

从下图可以看出当引脚为低电平时,LED会被点亮,所以需要寻找对应的nLED_1(对应的GPIO口)

如下图,led对应的寄存器时GPB寄存器,

因此使能GPBCON ,使GPBDA的第五位输出低电平/

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

代码如下:

volatile的用法

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

  1. 防止编译器优化

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

  1. 保证内存可见性

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

  1. 嵌入式系统编程

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

  1. 调试和性能分析

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

二、实现流水灯

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

cs 复制代码
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被设置为输入模式,通过该引脚可以判断按键是否被按下;

cs 复制代码
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();
}

三、时钟

pwm定时器

相关推荐
海绵宝宝de派小星29 分钟前
MCP与A2A协议深度解析:Agent时代的“TCP/IP“如何诞生
arm开发·网络协议·tcp/ip·ai
Zephyrus_20235 小时前
LSM6DSV16X驱动移植+调试
c语言·arm开发
瑞禧生物tech5 小时前
四臂聚乙二醇-磷脂 4-Arm PEG-DSPE 反应原理解析
arm开发
振南的单片机世界6 小时前
地址总线定“找谁”,数据总线定“搬多少”
arm开发·stm32·单片机
有想法的py工程师1 天前
手工处理 Oracle Cloud ARM 实例在线 DD Rocky Linux 10报错
linux·arm开发·oracle
带土11 天前
2. ARM处理器概论
arm开发
大阳1231 天前
ARM.7(UART,I2C)
arm开发·单片机·嵌入式硬件·i2c·at24c02
secondyoung3 天前
Cortex-R52学习:MPU内存保护机制
arm开发·单片机·学习·arm·mpu
szxinmai主板定制专家3 天前
基于 ARM+FPGA精密多轴实时运动控制卡设计方案,适用于半导体设备等高精度领域(一)
arm开发·人工智能·嵌入式硬件·fpga开发·架构·语音识别
你疯了抱抱我3 天前
【Mac】安装并配置HomeBrew;ARM GCC;make;OpenOCD
arm开发·macos