@

1.流水灯在电子电路中的地位

记得第一次接触单片机时,还是用的AT89S52单片机,第1个程序就是点亮一个LED,然后再实现LED流水灯的效果。在这个过程中,可以了解整个程序的结构,GPIO的使用,延时的使用等。可以说单片机学习中的点灯,就相当于C语言中的"Hello World"!好的,我们来看一下在ARM Linux下如何控制GPIO。

2.硬件电路分析

点灯的根本是控制LED对应GPIO输出高低电平,那要控制哪个GPIO呢?这就需要查看原理图,看LED是连接到了哪个GPIO管脚。

iMX287的扩展板AP-283Demo原理图中,LED的驱动电路:



与连接器的连接关系:



这里我们把:4个LED的管脚和J8C的4个管脚使用跳线帽短接起来,即

J8A_1=LED1 -> J8C_1=IO3.26
J8A_2=LED2 -> J8C_2=IO3.22
J8A_3=LED3 -> J8C_3=IO3.20
J8A_4=LED4 -> J8C_4=IO2.7

即:

GPIO3_26 = LED1
GPIO3_22 = LED2
GPIO3_20 = LED3
GPIO2_7 = LED4

所以,我们只需要控制这几个GPIO的高低电平,可以控制LED了。

连接方式:

3.先点个灯吧

iMX28 系列处理器的 IO 端口分为 7 个 BANK,其中 BANK0~4 具有 GPIO 功能,每个BANK 具有 32 个 I/O。iMX283 部分 BANK 的引脚不支持 GPIO 功能,具体需要参考《IMX28CEC_Datasheet.pdf》手册。在导出 GPIO 功能引脚时,需要先计算 GPIO 引脚的排列序号,其序号计算公式:

GPIO序号 = Bank * 32 + N

#LED对应的序号
LED1 -> GPIO3_26 = 3 * 32 + 26 = 122
LED2 -> GPIO3_22 = 3 * 32 + 22 = 118
LED3 -> GPIO3_20 = 3 * 32 + 20 = 116
LED4 -> GPIO2_7 = 2 * 32 + 7 = 71

串口或SSH登录开发板之后,通过如下过程可导出对应GPIO的功能,以LED1对应的122为例:

#进入到gpio驱动所在的文件夹
cd /sys/class/gpio #生成LED1操作的相关文件
echo 122 > export #进入到LED1控制文件夹
cd gpio122 #设置GPIO为输出方向
echo out > direction #查看当前GPIO的输入输出方向
cat direction #设置GPIO输出0点亮LED
echo 0 > value #查看当前GPIO的输出状态
cat value #设置GPIO输出1熄灭LED
echo 1 > value #查看当前GPIO的输出状态

在这里,就体现了Linux系统下一切皆文件的含义。



这样,就实现了某个GPIO输出高低电平的目的,其他LED的控制,只需要修改对应的序号即可。

如果想取消LED1的GPIO功能,可以通过如下命令实现:

echo 122 > unexport



当然,如果是读取输入,如按键等,就设置方向为in输入,通过cat value来读取输入的状态。

4.shell脚本实现流水灯

好了,知道了如何实现GPIO的控制,那么如何方便、快捷的执行以上步骤呢?我们这里先介绍一种通过shell脚本的方式控制LED实现流水灯的效果:

#在home目录新建led_blink.sh脚本文件
touch led_blink.sh #输入控制LED实现流水灯效果的代码
vi led_blink.sh

led_blink.sh的文件内容:

#!/bin/bash

#LED对应的GPIO
led1_pin=122
led2_pin=118
led3_pin=116
led4_pin=71 #echo $led1_pin $led2_pin $led3_pin $led4_pin #GPIO操作文件如果不存在则创建,否则不创建
for pin in $led1_pin $led2_pin $led3_pin $led4_pin
do
#如果文件夹存在
if [ ! -d "/sys/class/gpio/gpio$pin/" ];
then
echo $pin > /sys/class/gpio/export
else
echo "$pin dir exist!"
fi
done #GPIO方向设置为输出
for pin in $led1_pin $led2_pin $led3_pin $led4_pin
do
echo out > /sys/class/gpio/gpio$pin/direction
done #死循环
while true
do
#GPIO输出0/1
for pin in $led1_pin $led2_pin $led3_pin $led4_pin
do
echo "点亮$pin"
echo 0 > /sys/class/gpio/gpio$pin/value
sleep 1 echo "熄灭$pin"
echo 1 > /sys/class/gpio/gpio$pin/value
done
done

保存退出之后,通过如下命令执行这个脚本:

#添加可执行权限
chmod +x led_blink.sh #执行脚本文件
./led_blink.sh

然后就可以看到流水灯效果了:



这种方式,没什么高深的技术,就是把之前通过一行一行的命令,转换成了自动化的脚本文件。为了写这种shell脚本,需要学习一些基本的shell语法。下面我们来介绍两种比较通用的方法,通过C语言文件读写的方式来实现流水灯效果。

5.ANSI C文件操作实现流水灯

只使用标准ANSI C文件操作来实现流水灯效果。标准C语言操作,常用的函数有

fopen/fclose/fwrite/fread/fseek等。无论是Linux还是Windows都是通用的。

/* ANSI C文件操作实现流水灯 By whik */

//包含printf和sleep等
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define LED1_PIN 122
#define LED2_PIN 118
#define LED3_PIN 116
#define LED4_PIN 71 #define GPIO_PATH "/sys/class/gpio/" int main(void)
{
int led_table[4] = {LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN};
char path[100];
char cmd_export[100];
int i; char *str;
FILE *fp; //文件指针
int cnt_w; //写入的字节数 //判断LED对应的操作文件夹是否存在,不存在自动创建
for(i = 0; i < 4; i++)
{
sprintf(path, "%sgpio%d", GPIO_PATH, led_table[i]); //sys/class/gpio/gpio122 if (!access(path, 0))
printf("%s 文件夹存在\n", path);
else
{
printf("%s 文件夹不存在\n", path);
sprintf(cmd_export, "echo %d > %sexport", led_table[i], GPIO_PATH);//echo 122 > /sys/class/gpio/export
system(cmd_export); //执行export命令 if(!access(path, 0)) //访问文件夹,确认创建成功
printf("%s 导出成功\n", path);
else
return -1;
}
} //设置输出方向
for(i = 0; i < 4; i++)
{
sprintf(path, "%sgpio%d/direction", GPIO_PATH, led_table[i]);
fp = fopen(path, "r+");
if(fp != NULL) //打开成功
{
printf("%s 打开成功\n", path);
cnt_w = fwrite("out", 3, 1, fp);
if(cnt_w == EOF)
{
printf("方向写入失败\n");
return -1;
}
else
printf("方向写入成功\n");
fclose(fp); //文件关闭
}
else
{
printf("%s 文件打开失败\n", path);
return -1;
}
} //流水灯效果
while(1)
{
for(i = 0; i < 4; i++)
{
sprintf(path, "%sgpio%d/value", GPIO_PATH, led_table[i]); fp = fopen(path, "w+");
if(fp != NULL)
{
fwrite("0", 1, 1, fp);
fseek(fp, 0, SEEK_SET); //重新定位到文件起始
printf("%s 写入0\n", path);
sleep(1); fwrite("1", 1, 1, fp);
printf("%s 写入1\n", path);
fseek(fp, 0, SEEK_SET); fclose(fp);
}
else
{
printf("%s 文件打开失败\n", path);
}
}
} return 0;
}

实现原理和之前的shell脚本也是一样的思路:

  • 先判断LED对应的GPIO操作文件是否导出,如果没有导出则执行导出命令,否则不执行。
  • 循环的方式,依次设置4个LED的方向为输出
  • 循环的方式,控制4个GPIO的输出高低电平,外面是一个死循环

6.Linux 系统调用实现流水灯

Linux系统调用,常用的文件IO操作函数有open/close/read/write/lseek/ulink等。函数用法也很简单,和标准C语言用法几乎一样,这里不再介绍。

/* Linux 系统函数实现流水灯 */
//涉及到设备操作的,需包含以下头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//包含close/read/write/lseek等函数
#include <unistd.h> //包含printf/sprintf函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define LED1_PIN 122
#define LED2_PIN 118
#define LED3_PIN 116
#define LED4_PIN 71 #define GPIO_PATH "/sys/class/gpio/" int main(void)
{ int led_table[4] = {LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN};
char path[100];
char cmd_export[100];
int i; char *str;
int fd;
int cnt_w; //写入的字节数 //判断LED对应的操作文件夹是否存在,不存在自动创建
for(i = 0; i < 4; i++)
{
sprintf(path, "%sgpio%d", GPIO_PATH, led_table[i]); //sys/class/gpio/gpio122 if (!access(path, 0))
printf("%s 文件夹存在\n", path);
else
{
printf("%s 文件夹不存在\n", path);
sprintf(cmd_export, "echo %d > %sexport", led_table[i], GPIO_PATH);//echo 122 > /sys/class/gpio/export
system(cmd_export); //执行export命令 if(!access(path, 0)) //访问文件夹,确认创建成功
printf("%s 导出成功\n", path);
else
return -1;
}
} //设置输出方向
for(i = 0; i < 4; i++)
{
sprintf(path, "%sgpio%d/direction", GPIO_PATH, led_table[i]);
fd = open(path, O_RDWR); //linux系统函数,失败返回-1
if(fd != -1) //打开成功
{
printf("%s 打开成功\n", path);
cnt_w = write(fd, "out", 3); //linux系统函数
if(cnt_w <= 0)
{
printf("方向写入失败\n");
return -1;
}
else
printf("方向写入成功\n");
close(fd); //linux系统函数,成功返回0
}
else
{
printf("%s 文件打开失败\n", path);
return -1;
}
} //流水灯效果
while(1)
{
for(i = 0; i < 4; i++)
{
sprintf(path, "%sgpio%d/value", GPIO_PATH, led_table[i]); fd = open(path, O_RDWR); //linux系统函数
if(fd != -1)
{
write(fd, "0", 1);
lseek(fd, 0, SEEK_SET); //重新定位到文件起始
printf("%s 写入0\n", path);
sleep(1); write(fd, "1", 1);
printf("%s 写入1\n", path);
lseek(fd, 0, SEEK_SET); close(fd);
}
else
{
printf("%s 文件打开失败\n", path);
}
}
} return 0;
}

实现过程也很简单,就是对文件的读写,Linux下一切皆文件的含义你理解了吗?

我的公众号:mcu149

iMX287A多种方法实现流水灯效果的更多相关文章

  1. CSS(3)多种方法实现水平垂直居中效果

    CSS实现水平垂直居中对齐 在CSS中实现水平居中,会比较简单.常见的,如果想实现inline元素或者inline-block元素水平居中,可以在其父级块级元素上设置text-align: cente ...

  2. S5PV210_流水灯

    1.整体思路:把相应的配置数据写入相应的寄存器,控制GPIO电平(Led.s)——运用工程管理Makefile编译.链接文件(由Led.s编译得到led.bin,该文件用于USB启动方式点亮LED,若 ...

  3. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】【实验一】流水灯模块

    实验一:流水灯模块 对于发展商而言,动土仪式无疑是最重要的任务.为此,流水灯实验作为低级建模II的动土仪式再适合不过了.废话少说,我们还是开始实验吧. 图1.1 实验一建模图. 如图1.1 所示,实验 ...

  4. Tiny4412之C语言实现流水灯,Tiny4412裸机程序[3]

    在前边我们使用汇编完成了一个流水灯实验: Tiny4412汇编流水灯代码,Tiny4412裸机LED操作 ---- - -- -- -- - -- -- 修改: # ${MKBL2} ${SOURCE ...

  5. Tiny4412汇编流水灯代码,Tiny4412裸机LED操作[1]

    从今天开始就正式进入到tiny4412的开发学习中了,今天主要看了一下Tiny4412的启动流程及存储器映射及Exynos4412数据手册,用汇编写了一个跑马灯程序(后续会有C语言版本的出来),先说一 ...

  6. Tiny4412汇编流水灯代码,Tiny4412裸机LED操作【转】

    本转载自:http://www.techbulo.com/1313.html Tiny4412汇编流水灯代码,Tiny4412裸机LED操作 2014年10月20日 ⁄ 裸机程序 ⁄ 共 4171字 ...

  7. cc2530的第三次实验,按键中断控制流水灯

    cc2530的第三次实验:按键中断控制流水灯 效果为按一次按键,流水灯亮一次 实验相关电路图: 实验相关寄存器: 初始化函数 //初始化LED灯 //设置P1SEL,通用为0,外设为1 1111110 ...

  8. [51单片机] EEPROM 24c02 [I2C代码封装-保存实现流水灯]

    这里把EEPROM 24c02封装起来,今后可以直接调用,其连线方式为:SDA-P2.1;SCL-P2.0;WP-VCC >_<:i2c.c /*--------------------- ...

  9. Xilinx Vivado的使用详细介绍(4):Zedboard+vivado之流水灯(加SDK)

    Vivado+zedboard之初学流水灯 Author:zhangxianhe 环境:vivado 2016.3(已验证适用于2015.4) 开发板:Zedboard version xc7z020 ...

随机推荐

  1. 监控 Linux 服务器活动的几个命令(watch top ac)

    watch.top 和 ac 命令为我们监视 Linux 服务器上的活动提供了一些十分高效的途径. 为了在获取系统活动时更加轻松,Linux 系统提供了一系列相关的命令.在这篇文章中,我们就一起来看看 ...

  2. 吴裕雄--天生自然python学习笔记:python 用pyInstaller模块打包文件

    要想在没有安装 Python 集成环境的电脑上运行开发的 Python 程序,必须把 Python 文件打包成 .exe 格式的可执行 文件. Python 的打包工作 PyInstaller 提供了 ...

  3. LeetCode No.136,137,138

    No.136 SingleNumber 只出现一次的数字 题目 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明:你的算法应该具有线性时间复 ...

  4. day35-子进程的开启

    #1.异步非阻塞: import os from multiprocessing import Process def func(): print('子进程:',os.getpid()) if __n ...

  5. TPO4-1 Deer Populations of the Puget Sound

    The causes of this population rebound are consequences of other human actions. First, the major pred ...

  6. ios Alamofire网络插件的使用

    pod 'Alamofire' import Alamofire let headers:HTTPHeaders = [ "aa":"bb" ] let par ...

  7. form中采用图片作为提交按钮

    <span style="font-size:14px;"><FORM name="formName" action="xxxx&q ...

  8. javascript 实现最简单的阶乘!

    <script type='text/javascript'>      window.onload =  get(5);   function  get(n){   document.w ...

  9. HTML5 Fundamental Syntax

    HTML5 Fundamental Syntax */--> HTML5 Fundamental Syntax 1 Adding Document Structure with HTML5's ...

  10. MySQL之数据存储引擎

    1.什么是存储引擎: 现实生活中我们用来存储数据的文件有不同的类型,每种文件类型对应各自不同的处理机制:比如处 理文本用txt类型,处理表格用excel,处理图片用png等,数据库中的表也应该有不同的 ...