电子工程师技术服务社区
- 社区首页
- 下载
- A80.rar
资料描述
前几天刚刚把那两个烦人的灯给关上,现在还得打开,没办法,谁让它们是测试gpio最好的办法呢。当然,这次再打开,可不是把fex文件再恢复回去,而是直接操作gpio寄存器,可以人为地控制开关、闪烁,也就是所谓的单片机的 “hello world”了。
要在linux下直接操作寄存器,需要先映射内存,获取寄存器的虚拟地址,然后再根据偏移量得到各个功能的寄存器用于操作。这就是uio驱动的写法。当然,目前我还没有找到比较好的可以响应中断的方法,而通过驱动程序将中断信号传给用户态程序的方法又不那么通用,所以暂时没有实现中断,先不考虑了。
现在习惯了用go语言来写程序了,所以这一次也不例外,用最新的golang 1.5.1来编译,代码简洁效率高,虽然这个gpio体现不出来,呵呵。golang 1.5.1 的环境搭建先不写出来,留着给fireprime了:-)。
下面开始:
首先是内存映射,打开/dev/mem文件,这个文件其实就是整个内存,在其中找到需要控制的地址,也就是映射后的寄存器地址了然后用mmap获得内容。需要注意的是,由于pagesize是4k的,所以所有外设入口点要与上0xfffff000,否则不能成功。
为了方便使用全部的寄存器,防止偷懒造成类封装的功能不全,所以我将gpio分为了两部分,一部分是port,一部分是pin,两个合起来就是gpio了。port部分里主要是对各个寄存器的地址的确定,再加上一些必要的初始化。
另一部分就是pin的实现了。其实这个pin的寄存器已经在port中初始化完成,pin类只是继承下来(所谓的继承),并在这个类里只操作对应pin的寄存器,其他无关寄存器不去理会。
这样分开写还有一个好处就是,如果要对一个组内实现8位、16位、32位的输出,可以直接赋值,而不需要每次更改一个pin的高低电平循环来实现,否则效率就太低了。
来看看调用的代码:
封装完调用就简单多了,这里就是控制这两个led,根据原理图确定ph6和ph17两个口。每次执行时ph6关掉,ph17翻转。
效果如下:
顺便sho