如何用继电器的发光二极管闪烁电路图

本文主要是关于发光二极管的相关介绍,并着重对使用继电器的发光二极管闪烁电路进行了详尽的描述。
如何用继电器的发光二极管闪烁电路图 原理图如图一
连接电路前先不要接二极管d1,一会再解释二极管的作用。三极管是2n3904 npn型三极管,基极电阻68欧姆,要把图中的5v电源vcc1和gnd1分别接到单片机的电源和地上.,
led灯的电路由外电源供电,r2取1k欧姆,限制电流。
实物图如下,图二和图三分别是led灯亮和灭的照片。虽然我拿个一个开发板,但是只用了其单片机的最小系统。
用示波器测三极管集电极的波形,发现有图五所示的一个尖刺,分析过后,是因为继电器本身就是一个线圈,在电流突然变化的瞬间会起到阻碍其变化的作用,左移在继电器的两端并联一个二极管,稳定输出的作用。加入二极管后的波形如图六中最后一组波形。
控制单片机p2^0口的代码如下:
#include《reg52.h》
#include《intrins.h》
sbit p20=p2^0 ;
void delay1000ms() //@11.0592mhz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
while(1)
{
p20=1;
delay1000ms();
p20=0;
delay1000ms();
}
}
led闪烁电路 该linux驱动用来控制开发板上的4个led灯,即通过向linux驱动发送数据可以控制led灯的开关。led驱动提供两种交互方式:命令和读写设备文件。
测试led驱动之前需用usb线连接开发板,然后打开开发板。成功启动后,执行build.sh脚本文件编译和安装led驱动。build.sh脚本文件会自动将s3c6410_leds.ko文件上传到开发板并安装。led驱动只能在开发板上安装,build.sh执行了build_s3c6410.sh脚本文件进行编译和安装。led驱动会建立一个/dev/s3c6410_leds设备文件,该linux驱动可控制4个led,通过向设备文件发送长度为1到4的字符串可以控制这4个led的开关。1表示开,0表示关。字符串长度不足4个,相当于后面补0。执行命令
“# adb shell “echo ‘1’》 /dev/s3c6410_leds” #打开第一个led,其他的都关闭
# adb shell “echo ‘1010’》 /dev/s3c6410_leds” #第一个和第三个led打开,第二个和第四个关闭
# adb shell “echo ‘1111’》 /dev/s3c6410_leds” #打开所有的led”可控制开发板上的led。可使用命令“# sh ~/drivers/s3c6410_leds/test_leds.sh”执行test_leds.sh脚本文件测试led。执行脚本文件后,开发板上的4个led会根据0到15的二进制形式控制led,第一个为最低位。脚本文件使用的是标准的bash shell,如果在ubuntu下无法成功执行,是因为其将dash作为默认的脚本解析器。可使用命令“# dpkg-reconfigure dash”将默认脚本解析器改成bash,出现设置界面时,选择“否”,再回车即可。
创建led驱动的设备文件,步骤如下;1.描述设备文件需要使用一个cdev结构体,该结构体在《linux内核源代码》/include/linux/cdev.h文件中定义。其中的大多数成员变量只需调用cdev_init()就可被初始化,该函数在《linux内核源代码》/fs/char_dev.c文件中。若要在一个linux驱动中建立多个设备文件,cdev.count变量的值就是要建立的设备文件数。这些设备文件对应的cdev结构体就通过cdev.list.prev和cdev.list.next指针变量连接,从而形成一个双向链表。cdev.owner变量未在cdev.init函数中初始化,使用语句“leds_cdev.owner=this_module;”来初始化2.linux设备文件的设备号分为主设备号和次设备号。用一个int类型表示,其中前12位表示主设备号,后20位表示次设备号。设备号有两种指定方法:直接在代码中指定和动态分配。第一种方法虽比较直观,但如果主设备号和次设备号已存在,建立设备文件就会失败。以防万一,可使用alloc_chrdev_region()自动分配一个未使用的主设备号。习惯上将次设备号设为0。函数原型为int alloc_chrdev_region(dev_t*dev,unsigned baseminor,unsigned count,const char *name),其中dev表示设备号指针,函数会随机分配一个未使用的主设备号,根据baseminor参数值分配次设备号。count表示分配的次设备号范围。name表示设备文件名称。多个linux设备文件可拥有同一个主设备号,但两个设备的主设备号和次设备号不能都一样。在使用函数自动分配设备号时,baseminor和count参数不要设太大,否则次设备号会溢出,且主设备号会进位,从而变成下一个主设备号。若要直接指定设备号,需使用register_chrdev_region()注册字符设备区域,该函数在《linux内核源代码》/fs/char_dev.c文件中实现,原型为:int register_chrdev_region(dev_t from,unsigned count,const char *name),from表示设备号,count表示次设备号范围,name表示设备文件名称。一般采用分别指定主设备号和次设备号的方式指定设备号,需要mkdev宏将主设备号和次设备号组合成设备号-“int dev_number=mkdev(major,minor);”。也可分别使用major和minor宏从设备号中获取主设备号和次设备号,代码为:“int major=major(dev_number); int minor=major(dev_number);”3.cdev_add()用于将字符设备添加到probes数组中。函数在《linux内核源代码》/fs/char_dev.c文件中实现,原型为
“int cdev_add(struct cdev *p,dev_t dev,unsigned count){
p-》dev=dev;
p-》count=count;
return kobj_map(cdev_map,dev,count,null,exact_match,exact_lock,p);
}”,调用该函数需指定设备文件指针p、设备号dev和设备文件数量count。在该函数还调用了一个重要的函数kobj_map,此函数负责将设备文件的相关信息添加到保存已建立的设备文件的probes数组中。kobj_map()和probes数组都在《linux内核源代码》/drivers/base/map.c文件中4.struct class包含一些与设备文件有关的变量及一些回调函数指针变量,使用class_create宏创建struct class,代码为
“struct class *leds_class=null;
leds_class=class_create(this_module,“dev_name”);”,dev_name是设备文件名称。class_create宏实际上使用了_class_create()创建struct class。该函数在《linux内核源代码》/drivers/base/class.c文件中实现5.device_create()用于创建设备文件,该函数在《linux内核源代码》/include/linux/device.h文件中定义,在《linux内核源代码》/drivers/base/core.c文件中实现。可使用代码“device_create(leds_class,null,dev_number,null,device_name);”调用device_create()创建设备文件,其中leds_class表示struct class,dev_number表示设备号,device_name表示设备文件的名称。编写leds_create_device()时应了解:①device_count表示建立设备文件的个数②alloc_chrdev_region()的第二个参数表示分配的起始次设备号。如果第三个参数的值大于1,函数会依次分配次设备号③采用自动分配设备号的方式创建设备文件,建议使用major和minor宏获取主设备号和次设备号,并分别保存在major和minor变量中,以备之后使用到④led驱动的设备号保存在dev_number变量中,要将leds_cdev.dev变量的值赋给dev_number变量。leds_init()是led驱动的初始化函数,在函数中直接调用leds_create_device()即可。若将s3c6410_leds_major设为0,系统会自动分配一个未使用的主设备号,次设备号仍是10.在每次装载led驱动时主设备号可能会不一样,但次设备号总是10。
卸载led驱动的设备文件:卸载操作会稍简单一些,需依次调用device_destroy、class_destroy和unregister_chrdev_region()。leds_destroy_device()用于卸载led驱动的设备文件,leds_exit()是led驱动的卸载函数,它通过调用leds_destroy_device()来完成卸载led驱动设备文件的工作。
设置寄存器与初始化led驱动:arm处理器有多个寄存器,通过设置不同寄存器的值。可以设置led引脚的状态、打开或禁止上拉电路以及控制led的亮和灭。我们必须知道的有:①led有两个引脚:gpb0和gpb1,其中一个引脚连接到了arm处理器的gpi0端口,另一个引脚经过一个限流电阻连接到电源vcc3上。当gpi0端口为低电平时,led两端产生电压差,led有电流通过发光;反之当gpi0端口为高电平时,led中没有电流通过,灯熄灭。高低电平之间切换非常快,led亮灭之间有一定的延迟②控制led需要通过3个寄存器完成,gpmcon端口配置寄存器、gpmdat端口数据寄存器和gpmpud端口上拉电路寄存器③每一个寄存器可以使用4个字节,即一个int类型数据占用的空间④使用gpmcon寄存器的低16位将led的两个端口gpb0、gpb1的属性设为output。每4位设置一个led,共4个led。output的值是0001,若使用十六进制表示,寄存器的低16位的值是0x1111⑤使用gpmdat寄存器的低4位控制4个led的亮、灭。每一位控制一个led,最低位控制离电池最近的led。0表示亮、1表示灭⑥使用gpmpud寄存器的低8位分别打开4个led的上拉电路。每两位控制一个led的上拉电路。10为打开上拉电路。使用十六进制的话,gpmpud寄存器的低8位是0xaa,才能同时打开4个led的上拉电路。以上3个寄存器在内存中都有一个虚拟地址。向这些地址写入数据后,arm处理器会使用一套算法将虚拟地址映射成物理地址,并根据物理地址将数据写入相应的硬件端口。arm处理器中的gpmcom、gpmdat和gpmpud的虚拟地址在linux内核中都使用了宏定义。为了跟踪这些宏,需再加两个include路径:/root/kernel/linux_kernel_2.6.36/arch/arm/mach-s3c64xx/include和/root/kernel/linux_kernel_2.6.36/arch/arm/plat-samsung/include。这三个寄存器的虚拟地址对应的宏分别为s3c64xx_gpmcon、s3c64xx_gpmpud、s3c64xx_gpmdat。这三个宏涉及了4个头文件共9个宏。可推出s3c64xx_gpm_base的值是0xf04500820,gpmcon、gpmdat和gpmpud寄存器的虚拟地址分别为0xf04500820、0xf04500824和0xf04500828,这三个虚拟地址是固定的,可向这三个地址写数据。更好的是使用s3c64xx_gpmcon、s3c64xx_gpmpud、s3c64xx_gpmdat来操作这3个地址。一般需在led驱动装载时初始化上述3个寄存器。只要在leds_init()中调用leds_init_gpm()就可完成寄存器的初始化。
控制led:led驱动可使用两种方式控制led:通过字符串控制led和通过i/o命令控制led。要使用以上两种方式控制led,驱动必须接收相应的数据。若通过字符串控制led,需使用file_operations.write(),可接收向设备文件写入的数据。若通过i/o命令控制,需使用file_operations.ioctl(),可接收向字符设备发送的命令和参数。s3c6410_leds_write()用于接收向led驱动的设备文件写入控制led的数据,在实现其功能编写代码时需了解:①4个led的亮灭用一个长度为4的mem数组。1表示点亮led,0表示熄灭led。与gpmdat寄存器的低4位表示的含义正好相反②若写入的字符串长度小于等于4,直接写入这些字符串。若长度大于4,则只写入前4个字符串。s3c6410_leds_write()要按传入该函数的字符串长度返回,否则系统会调用多次该函数写入字符串③事先mem数组已被清零,若要写入的字符串长度小于4,则相当于后面的字符都是④向gpmdat寄存器写入数据之前最好先读取gpmdat寄存器的当前值,并通过位与、或等操作保留与本次操作无关的值⑤ioread32、iowrite32用于读写虚拟地址中的32位数据。使用命令
“# adb shell ‘echo 1101 》 /dev/s3c6410_leds’
# adb shell ‘echo 1 》 /dev/s3c6410_leds’”可通过字符串控制led的亮、灭。i/o命令无法使用命令行方式进行测试。
led驱动的模块参数:若想在装载led驱动时指定默认状态值,就要使用模块参数。为linux驱动指定一个模块参数需使用module_param(name,type,perm)宏。name表示参数名,type表示参数类型,perm表示读/写权限。module_param支持的参数类型包括byte、short、ushort、int、uint、long、charp、bool和invbool。使用module_param宏指定模块参数时,会在/sys/module目录下生成和驱动设备文件同名的目录。若在装载linux驱动时未指定某个参数,则参数文件的内容是该参数在linux驱动源代码中指定的默认值。通过module_param宏可指定参数文件的访问权限。s_irugo表示所有的用户都可访问该参数文件中的内容,但不能修改。s_irugo|s_iwusr表示允许所有用户读,以及创建文件的用户写。linux内核还提供了更多的定义访问权限的宏。s_irwxugo表示所有用户可对文件读、写和执行。iwugo表示所有用户对文件只有写权限。需要修改led驱动的代码,为led驱动添加一个模块参数,该参数存储了4个led的初始状态,参数类型为int。参数值的范围是0到15.参数值控制led的规则与gpmdat寄存器低4位控制led的规则相同。为led驱动添加模块参数首先要定义一个保存模块参数值的变量,然后使用module_param宏指定模块参数的相关信息。最后修改leds_init()代码,将leds_init_gpm()的参数值改成~leds_state。使用命令“# adb shell insmod /data/local/s3c6410_leds.ko leds_state=3”可测试led驱动的模块参数。执行完命令后,会在/sys/module/s3c6410_leds/parameters目录下生成一个leds_state文件,使用命令
“# adb shell cat /sys/module/s3c6410_leds/parameters/leds_state”可看到文件内容为3。使用命令“# adb shell ‘echo 5 》 /sys/module/s3c6410_leds/parameters/leds_state’”可将文件内容改为5。修改leds_state文件内容后,在led驱动代码中的leds_state变量值会变成5。linux驱动在装载时会将指定的参数值写入参数文件,若未指定参数值,linux驱动会将参数的默认值写入参数文件。在linux驱动工作的过程中,参数值会与参数文件中的内容同步。使用module_param_array(name,type,nump,perm)宏可为linux驱动指定数组形式的模块参数。nump表示存储数组长度的变量的指针,perm表示参数文件的访问权限。通过命令“# adb shell insmod /data/local/s3c6410_leds.ko ‘leds_state=11 param=str1,str2,str3’”可指定params参数值。如果params参数指定的值的个数少于数组长度,后面的数组元素使用默认值。如果大于数组长度,led驱动装载失败,并在日志中输出信息。使用模块参数要注意:①通过module_param_array宏的第3个参数指定数组长度时要使用指针类型的数据②如果linux驱动含有多个模块参数,需将这些参数用单引号或双引号括起来③指定数组类型的参数值时,逗号前不能有空格。
结语 关于使用继电器的发光二极管闪烁电路就介绍就到这了,如有不足之处欢迎指正。
相关阅读推荐:数字电路控制闪烁发光二极管的电路图 相关阅读推荐:单只闪烁发光二极管的应用电路
xilinx ZYNQ7000系列基本开发流程之PS端
先楫半导体 江苏电源学会,南航研修班成功举办
DIALOG半导体电源管理和音频技术受三星青睐
三星Note 8 将卷土重来 硬件加身,刚出血路来!
同步RS触发器原理
如何用继电器的发光二极管闪烁电路图
双向功率转换模块和混合逆变器解决方案
AI经历资本寒冬、疫情黑天鹅之后 行业回归理性迈向深水区
机器视觉检测对比人工检测的优势
如何测试PAM4信号
SD协会近期宣布了一项名为microSD Express的新标准
怎样学习摩尔斯电码
如何使用SIM900A将传感器数据发送到网站
空闲任务钩子函数详解
腾讯最新研发智慧城市加速器正式启动全球招募
华为发布Digital strategy助力运营商数字化转型
分享两个电源电路的原理及PCB布板方式
插接IDE数据线
AutoSAR CAN通信模式转换的条件有哪些
高端装备制造产业现状分析