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定时器

相关推荐
憧憬一下2 天前
PCIe_Host驱动分析_地址映射
arm开发·嵌入式硬件·嵌入式·linux驱动开发·pci/pcie
楼兰公子2 天前
相机主要调试参数
arm开发·驱动·camera·v4l2
7yewh2 天前
嵌入式驱动RK3566 HDMI eDP MIPI 背光 屏幕选型与调试提升篇-eDP屏
linux·arm开发·驱动开发·嵌入式硬件·嵌入式linux·rk·edp
千千道4 天前
深入理解 Linux 内核启动流程
linux·arm开发·驱动开发
徐某人..4 天前
ARM嵌入式学习--第八天(PWM)
arm开发·学习·arm
aiamia5 天前
CAN配置---波特率中断引脚等---autochips-AC7811-ARM-M3内核
arm开发·单片机·mcu·车载系统·汽车
驯龙高手_追风5 天前
ARM32位MCU开发板调试经验总结
arm开发·单片机·嵌入式硬件
重生之我是数学王子5 天前
ARM原理
arm开发·系统架构
qq762118225 天前
arm Rk3588 更新固件
arm开发
@嵌入式Linux小白5 天前
了解ARM的千兆以太网——RK3588
linux·arm开发·驱动开发