iMX287A多种方法实现流水灯效果
@
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多种方法实现流水灯效果的更多相关文章
- CSS(3)多种方法实现水平垂直居中效果
CSS实现水平垂直居中对齐 在CSS中实现水平居中,会比较简单.常见的,如果想实现inline元素或者inline-block元素水平居中,可以在其父级块级元素上设置text-align: cente ...
- S5PV210_流水灯
1.整体思路:把相应的配置数据写入相应的寄存器,控制GPIO电平(Led.s)——运用工程管理Makefile编译.链接文件(由Led.s编译得到led.bin,该文件用于USB启动方式点亮LED,若 ...
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】【实验一】流水灯模块
实验一:流水灯模块 对于发展商而言,动土仪式无疑是最重要的任务.为此,流水灯实验作为低级建模II的动土仪式再适合不过了.废话少说,我们还是开始实验吧. 图1.1 实验一建模图. 如图1.1 所示,实验 ...
- Tiny4412之C语言实现流水灯,Tiny4412裸机程序[3]
在前边我们使用汇编完成了一个流水灯实验: Tiny4412汇编流水灯代码,Tiny4412裸机LED操作 ---- - -- -- -- - -- -- 修改: # ${MKBL2} ${SOURCE ...
- Tiny4412汇编流水灯代码,Tiny4412裸机LED操作[1]
从今天开始就正式进入到tiny4412的开发学习中了,今天主要看了一下Tiny4412的启动流程及存储器映射及Exynos4412数据手册,用汇编写了一个跑马灯程序(后续会有C语言版本的出来),先说一 ...
- Tiny4412汇编流水灯代码,Tiny4412裸机LED操作【转】
本转载自:http://www.techbulo.com/1313.html Tiny4412汇编流水灯代码,Tiny4412裸机LED操作 2014年10月20日 ⁄ 裸机程序 ⁄ 共 4171字 ...
- cc2530的第三次实验,按键中断控制流水灯
cc2530的第三次实验:按键中断控制流水灯 效果为按一次按键,流水灯亮一次 实验相关电路图: 实验相关寄存器: 初始化函数 //初始化LED灯 //设置P1SEL,通用为0,外设为1 1111110 ...
- [51单片机] EEPROM 24c02 [I2C代码封装-保存实现流水灯]
这里把EEPROM 24c02封装起来,今后可以直接调用,其连线方式为:SDA-P2.1;SCL-P2.0;WP-VCC >_<:i2c.c /*--------------------- ...
- Xilinx Vivado的使用详细介绍(4):Zedboard+vivado之流水灯(加SDK)
Vivado+zedboard之初学流水灯 Author:zhangxianhe 环境:vivado 2016.3(已验证适用于2015.4) 开发板:Zedboard version xc7z020 ...
随机推荐
- \b 是单词边界锚点 word-boundary anchor,一个“\b”匹配一个单词的一端,两个“\b”匹配一个单词的头尾两端
123 $_ = "beforematcha? fter"; 124 if(/\b\w+a\b/){ 125 print "matched: < ...
- GlobalExceptionHandler @ControllerAdvice
package org.linlinjava.litemall.core.config; import org.apache.commons.logging.Log; import org.apach ...
- 牛客-Forsaken的数列(Treap)
题目传送门 sol:第一次看题还真信了是用线段树来做,但是没什么想法,看了题解发现是我不会的Treap,然后花了几天时间学习了一下并补掉题目 无旋Treap #include <bits/std ...
- Windows可以往外ping,外部却ping不通本机
网络背景:192.168.1.17.192.168.1.19.192.168.1.20 三台机器都在一个exsi宿主机下网络非常简单 问题描述:17和19都可以ping通20:20却不能ping通17 ...
- python数据类型:Number数字
Python Number数据类型用于存储数值 数据类型是不允许改变的,如果改变Number数据类型的值,将从新分配内存空间 整型(int):整型或整数,是正或者负整数,不带小数点 长整型(long) ...
- @echo off 批处理
一个批处理文件 @echo off ipconfig /all @pause -------------------------------- @echo off 是什么意思 就是说关闭回显@echo ...
- golang seelog使用
golang中自带的有log包,但是功能并不能满足我们.很多人推荐seelog,我们今天一起学习下. 安装 go get github.com/cihub/seelog 快速开始 引用seelog w ...
- tomcat部署项目方式
三大部署方式1. Context描述文件部署通过独立的Context文件描述清楚项目的访问路径和地址,tomcat在启动的时候会解析这个Context文件,创建一个Context对象. Conte ...
- group compare vs pair compare
成对总体检验是令y1=x11-x12:y2=x21-x22等,令新的随机变量y去做假设检验.此方法适用于排除物理因素影响,对差异更敏感,所以适用于小样本.而使用两个总体均值比较的方法适用于大样本.
- 3DMAX 卸载工具,完美彻底卸载清除干净3dmax各种残留注册表和文件
一些同学安装3dmax出错了,也有时候想重新安装3dmax的时候会出现这种本电脑windows系统已安装3dmax,你要是不留意直接安装,只会安装3dmax的附件,3dmax是不会安装上的.这种原因呢 ...