Exynos4412裸机开发系列教程--LED流水灯

        对于任何一门编程语言的学习,绝大部分都是从Hello Word开始的,但是对于大部分嵌入式驱动开发者,通常都是从点Led灯开始的,前人有言,给我一个发光二极管,我将点亮整个世界,从这格层面上讲,点灯已是一种方便快捷的调试手段。同样,本教程也不列外,所有的一切都从点亮一颗Led开始。

  任何一款SOC芯片,其外围必定有一堆扩展IO口,通常这些IO是和各种内部外设复用的,比如串口的TXD、RXD信号既可以做功能管脚,也可以做普通IO,对于点亮Led灯,只需要将对应的管脚配置为GPIO输出模式,并设置相应的输出电平状态即可。

       本系列教程,基于九鼎的X4412开发板,此开发板性价比高,性能稳定,扩展性强,功能完善,并提供X4412核心板,方便企业用户做深度定制版二次开发。开发板截图:



      任何系统开机后都有一个启动过程,同样EXYNOS4412也不列外。Exynos4412属于应用处理器,非一般微控制器,开机启动是一个比较复杂的过程,因这里是第一篇教程,故不作过多阐述,后续系列教程会此进行深入描述。这里简单说明一下,EXYNOS4412芯片启动时,固化在芯片内部的IROM会首先执行,其最主要的任务是读取外部存储器的前8k或者16k代码,并做相应的校验,校验通过后,然后执行。在此过程中仅仅使用内部的IROM及IRAM,不涉及任何外部存储器。当然,究竟是从哪个存储器读取前8k或者16k,则是根据硬件的OM启动模式配置管脚来决定的,本教程OM配置模式都是从外部SD卡启动,相应的程序也都烧录在外部SD卡中的第一个扇区。

      前面的这8k或者16k代码后,是系统正常启动的关键。一般都会执行以下动作:关看门狗,设置为系统模式,关MMU,CACHE等,初始化系统主时钟,初始化DDR,拷贝剩余部分代码(当然bootloader都会超过8k的),为C代码准备环境,比如将BSS段清零,初始化已初始化数据段等等,最后是调到C语言的Main函数,至此,启动工作已完成,进入相对较为熟悉的main函数了。

    本教程,重点讲述LED灯相关的操作,首先,我们由原理图可以看出,底板上有四颗LED,参考原理图如下:



为了能方便快捷的操作各个LED,我们定义一个函数,void led_set_status(enum led_name name, enum led_status status),这样在调用时只需传递特定的参数就可以控制各个LED了,这里定义了两个枚举类型:

enum led_name {
	LED_NAME_LED1		= 1,
	LED_NAME_LED2		= 2,
	LED_NAME_LED3		= 3,
	LED_NAME_LED4		= 4,
};

enum led_status {
	LED_STATUS_OFF		= 0,
	LED_STATUS_ON		= 1,
};
在我们执行具体的操作时,我们需要初始化相应的IO口,将其设置为输出上拉模式,初始化代码如下:

/*
 * LED1 -> EXYNOS4412_GPX1(6)
 * LED2 -> EXYNOS4412_GPX1(7)
 * LED3 -> EXYNOS4412_GPX2(6)
 * LED4 -> EXYNOS4412_GPX2(7)
 */
void led_initial(void)
{
	/* LED1 */
	writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_CON, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_CON) & ~(0xf<<24)) | (0x1<<24));
	writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_PUD, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_PUD) & ~(0x3<<12)) | (0x2<<12));
	writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<6)) | (0x1<<6));

	/* LED2 */
	writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_CON, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_CON) & ~(0xf<<28)) | (0x1<<28));
	writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_PUD, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_PUD) & ~(0x3<<14)) | (0x2<<14));
	writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<7)) | (0x1<<7));

	/* LED3 */
	writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_CON, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_CON) & ~(0xf<<24)) | (0x1<<24));
	writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_PUD, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_PUD) & ~(0x3<<12)) | (0x2<<12));
	writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<6)) | (0x1<<6));

	/* LED4 */
	writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_CON, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_CON) & ~(0xf<<28)) | (0x1<<28));
	writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_PUD, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_PUD) & ~(0x3<<14)) | (0x2<<14));
	writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<7)) | (0x1<<7));
}

在初始各个控制IO后,我们可以实现具体的设置LED状态的函数了。根据传递的参数设置相应的控制寄存器。

void led_set_status(enum led_name name, enum led_status status)

{
	switch(name)
	{
	case LED_NAME_LED1:
		if(status == LED_STATUS_ON)
			writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<6)) | (0x0<<6));
		else if(status == LED_STATUS_OFF)
			writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<6)) | (0x1<<6));
		break;

	case LED_NAME_LED2:
		if(status == LED_STATUS_ON)
			writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<7)) | (0x0<<7));
		else if(status == LED_STATUS_OFF)
			writel(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX1_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<7)) | (0x1<<7));
		break;

	case LED_NAME_LED3:
		if(status == LED_STATUS_ON)
			writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<6)) | (0x0<<6));
		else if(status == LED_STATUS_OFF)
			writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<6)) | (0x1<<6));
		break;

	case LED_NAME_LED4:
		if(status == LED_STATUS_ON)
			writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<7)) | (0x0<<7));
		else if(status == LED_STATUS_OFF)
			writel(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT, (readl(EXYNOS4412_GPX2_BASE + EXYNOS4412_GPIO_DAT) & ~(0x1<<7)) | (0x1<<7));
		break;

	default:
		break;
	}
}
有了以上LED控制函数,我们就可以实现具体的流水灯程序了,闪烁规则如下,从左至右依次点亮,然后再从右至左依次点亮,通过index变量标识是那颗led,flag变量标识流水的方向,从左至右还是从右至左。

int tester_led(int argc, char * argv[])
{
	int index = 0;
	int flag = 0;

	while(1)
	{
		led_set_status(LED_NAME_LED1, LED_STATUS_OFF);
		led_set_status(LED_NAME_LED2, LED_STATUS_OFF);
		led_set_status(LED_NAME_LED3, LED_STATUS_OFF);
		led_set_status(LED_NAME_LED4, LED_STATUS_OFF);

		switch(index)
		{
		case 0:
			led_set_status(LED_NAME_LED1, LED_STATUS_ON);
			break;

		case 1:
			led_set_status(LED_NAME_LED2, LED_STATUS_ON);
			break;

		case 2:
			led_set_status(LED_NAME_LED3, LED_STATUS_ON);
			break;

		case 3:
			led_set_status(LED_NAME_LED4, LED_STATUS_ON);
			break;

		default:
			break;
		}

		mdelay(50);

		if(index == 0 || index == 3)
			flag = !flag;

		if(flag)
			index = (index + 1) % 4;
		else
			index = (index + 4 - 1) % 4;
	}

	return 0;
}

运行状态,一张静态图,将就看看吧,实际效果可以自行下载到SD卡中运行:


如果您对本文感兴趣,想必是同道中人,需要源码的朋友,可移步此处,点击下载,有任何疑问欢迎留言,或者直接加QQ: 8192542。第一篇教程就此结束,先有格感性认识吧,尽请期待后续教程,您的支持就是我的动力,还请各路大侠多多捧场。

附上源码:

Exynos4412裸机系列教程源码之流水灯

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: exynos4412-pwm 蜂鸣器开发是指使用Exynos4412芯片的PWM模块来控制蜂鸣器的开发。PWM模块可以产生一定频率和占空比的脉冲信号,通过控制脉冲信号的频率和占空比,可以控制蜂鸣器发出不同的声音。在开发过程中,需要了解Exynos4412芯片的PWM模块的使用方法,以及蜂鸣器的工作原理和控制方式。同时,还需要编写相应的驱动程序和应用程序,实现蜂鸣器的控制。 ### 回答2: exynos4412-pwm蜂鸣器开发是指在使用exynos4412芯片的板子上使用pwm技术来控制蜂鸣器发出声音。该方案的实现需要一些必要的硬件和软件条件。 首先,需要准备一款带有蜂鸣器的arduino或类似的板子,同时还需要exynos4412芯片的板子,以及一些杜邦线和电阻等电子元器件。其次,需要在板子上安装linux操作系统,并配置好相关的驱动程序和开发环境。在这个过程中需要熟悉linux的内核驱动开发和用户空间开发,同时还需要掌握pwm技术和蜂鸣器的原理。 在完成硬件和软件准备后,可以开始进行exynos4412-pwm蜂鸣器开发。首先创建一个设备驱动程序来控制蜂鸣器,并在其中实现pwm技术来生成不同频率的蜂鸣器声音。然后可以在应用程序中调用这个驱动程序来实现具体的功能,比如根据输入的命令生成不同的蜂鸣器声音。 总的来说,exynos4412-pwm蜂鸣器开发需要掌握一定的硬件和软件技能,包括linux开发、驱动程序开发、pwm技术和蜂鸣器原理等。在掌握了这些技能后,可以很方便地在exynos4412芯片的板子上实现蜂鸣器声音的控制和应用。 ### 回答3: exynos4412-pwm是一种嵌入式系统的PWM控制器,它能够对某些外设进行精准控制。而蜂鸣器则是常用的一种简单外设,能够通过PWM信号控制而发出声音。因此,我们可以结合exynos4412-pwm的特性,来进行蜂鸣器的开发。 首先,我们需要确定使用的蜂鸣器的型号和规格,以及它的工作电压和最大工作频率。根据这些参数,我们就可以计算出需要给PWM控制器发送的频率和占空比等参数。在编码实现上,我们可以通过Linux操作系统中的sysfs文件系统对PWM控制器进行设置和控制。具体而言,我们需要修改/sys/devices/platform/pwm-ctrl/目录下的相关文件来设置频率和占空比等属性,以及控制PWM输出信号的开关状态。 此外,在硬件设计上,我们还需要将蜂鸣器接入到exynos4412-pwm控制器的PWM输出信号。需要注意的是,蜂鸣器的极性也需要正确接入,以确保PWM正负半周的输出方向正确。 综上所述,exynos4412-pwm蜂鸣器开发需要我们在硬件和软件两个方面进行开发和实现。在硬件方面,需要正确接入蜂鸣器和PWM控制器,并确保信号方向和极性正确;在软件方面,需要通过Linux操作系统的sysfs文件系统对PWM控制器进行设置和控制。通过这样的方式,我们就可以很方便地实现蜂鸣器的声音输出,以满足一些嵌入式系统的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值