欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

C# 控制 GPIO

程序员文章站 2022-07-04 08:37:05
控制 IO 有多种方式。 这里说最简单的方式。 Linux 下 一切皆文件。 所以 GPIO 也会是一个文件。通过操作文件,可以控制它。 贴入代码。 1 using NewLife; 2 using NewLife.Log; 3 using System; 4 using System.Collec ......

控制 io 有多种方式。

这里说最简单的方式。

  linux 下 一切皆文件。 所以 gpio 也会是一个文件。通过操作文件,可以控制它。

贴入代码。

  1 using newlife;
  2 using newlife.log;
  3 using system;
  4 using system.collections.generic;
  5 using system.io;
  6 using system.linq;
  7 using system.text;
  8 using system.threading;
  9 using system.threading.tasks;
 10 
 11 namespace linux
 12 {
 13     /// <summary>gpio 组</summary>
 14     public enum pingroup : int
 15     {
 16         pa = 0,
 17         pb = 1,
 18         pc = 2,
 19         pd = 3,
 20         pe = 4,
 21         pg = 5,
 22         ph = 6,
 23         pi = 7,
 24         pj = 6,
 25     }
 26 
 27     /// <summary>引脚输入输出模式</summary>
 28     public enum pindir
 29     {
 30         in = 0,
 31         out = 1,
 32     }
 33 
 34     /// <summary>简单实现 gpio 的读写,不包含中断处理</summary>
 35     public class simplegpio : disposebase
 36     {
 37         /// <summary> 保证 结尾有/ 的路径</summary>
 38         private static string _gpiobasepath = @"/sys/class/gpio/";
 39 
 40         /// <summary>gpio 的目录</summary>
 41         public static string gpiobasepath
 42         {
 43             get { return _gpiobasepath; }
 44             set
 45             {
 46                 if (value == null) return;
 47                 if (value == "") return;
 48 
 49                 _gpiobasepath = value;
 50 
 51                 if (!_gpiobasepath.endswith("/")) _gpiobasepath += "/";
 52             }
 53         }
 54 
 55         /// <summary>方向</summary>
 56         public pindir dir;
 57 
 58         /// <summary>状态</summary>
 59         public boolean opened { get; private set; } = false;
 60 
 61         /// <summary>名称</summary>
 62         public string name { get; set; }
 63 
 64 
 65         /// <summary>引脚编号</summary>
 66         private int _pinidx = -1;
 67 
 68         /// <summary>引脚路径</summary>
 69         private string pinpath;
 70 
 71 
 72         #region 构造
 73 
 74         public simplegpio() { }
 75 
 76         /// <summary></summary>
 77         /// <param name="gp">gpio 组</param>
 78         /// <param name="gpidx">组内编号</param>
 79         public simplegpio(pingroup gp, int gpidx)
 80         {
 81             _pinidx = (int)gp * 32 + gpidx;
 82 
 83             name = "gpio" + _pinidx;
 84         }
 85 
 86         /// <summary></summary>
 87         /// <param name="idx">全局gpio index</param>
 88         public simplegpio(int idx)
 89         {
 90             _pinidx = idx;
 91 
 92             name = "gpio" + _pinidx;
 93         }
 94 
 95         /// <summary>析构</summary>
 96         protected override void ondispose(bool disposing)
 97         {
 98             base.ondispose(disposing);
 99 
100             unexportpin();
101         }
102 
103         #endregion
104 
105         #region 基础操作
106 
107         /// <summary></summary>
108         /// <param name="idx">全局gpio index</param>
109         public void setpin(int idx)
110         {
111             _pinidx = idx;
112 
113             name = "gpio" + _pinidx;
114         }
115 
116         /// <summary> </summary>
117         /// <param name="gp">gpio 组</param>
118         /// <param name="gpidx">组内编号</param>
119         /// <param name="dir">输入/输出</param>
120         public void setpin(pingroup gp, int gpidx, pindir dir = pindir.in)
121         {
122             _pinidx = (int)gp * 32 + gpidx;
123             dir = dir;
124 
125             name = "gpio" + _pinidx;
126         }
127 
128 
129         /// <summary>打开</summary>
130         /// <returns></returns>
131         public boolean open()
132         {
133             pinpath = gpiobasepath + name + "/";
134             xtrace.writeline("打开 " + pinpath);
135 
136             if (!pinpath.asdirectory().exists)
137             {
138                 try
139                 {
140                     if (!exportpin()) return false;
141                 }
142                 catch
143                 {
144                     xtrace.writeline(pinpath + "导出引脚出错,请 检查参数 和 权限");
145                     return false;
146                 }
147             }
148 
149             // 写入配置
150             var dir = new fileinfo(pinpath + "direction");
151             if (!dir.exists) { xtrace.writeline("direction 文件呢?"); return false; }
152 
153             var str = dir == pindir.out ? "out\n" : "in\n";
154             dir.writebytes(str.getbytes());
155 
156             opened = true;
157             return true;
158         }
159 
160         /// <summary>关闭</summary>
161         public void close()
162         {
163             unexportpin();
164 
165             opened = false;
166         }
167 
168         /// <summary>写引脚状态</summary>
169         /// <param name="value"></param>
170         public void write(bool value)
171         {
172             if (!opened) return;
173 
174             if (dir == pindir.in) return;
175 
176             var fi = new fileinfo(pinpath + "value");
177             if (!fi.exists) { xtrace.writeline("value 文件呢?"); return; }
178 
179             if (value)
180                 fi.writebytes("1\n".getbytes());
181             else
182                 fi.writebytes("0\n".getbytes());
183         }
184 
185         /// <summary>读取状态</summary>
186         /// <returns></returns>
187         public bool read()
188         {
189             if (!opened) return false;
190 
191             var fi = new fileinfo(pinpath + "value");
192             if (!fi.exists) { xtrace.writeline("value 文件呢?"); return false; }
193 
194             var v = fi.readbytes(0, 1);
195             if (v == null) return false;
196             if (v.length == 0) return false;
197             if (v[0] == '0') return false;
198 
199             return true;
200         }
201 
202         #endregion
203 
204         #region 辅助
205         /// <summary>导出引脚</summary>
206         /// <returns></returns>
207         public bool exportpin()
208         {
209             if (!gpiobasepath.asdirectory().exists)
210             {
211                 xtrace.writeline("基础目录 {0} 不存在", gpiobasepath);
212                 return false;
213             }
214 
215             var export = new fileinfo(gpiobasepath + "export");
216             if (!export.exists)
217             {
218                 xtrace.writeline("export 文件不存在,请确认gpio目录是否正确");
219                 return false;
220             }
221 
222             var param = _pinidx + "\n";
223             export.writebytes(param.getbytes());
224             thread.sleep(100);
225 
226             if (!pinpath.asdirectory().exists)
227             {
228                 xtrace.writeline("导出失败,请确认 pin 是否正确");
229                 return false;
230             }
231 
232             // xtrace.writeline("导出 {0},成功", name);
233             return true;
234         }
235 
236         /// <summary>取消导出引脚</summary>
237         public void unexportpin()
238         {
239             var unexport = new fileinfo(gpiobasepath + "unexport");
240             if (!unexport.exists)
241             {
242                 xtrace.writeline("unexport 文件不存在,请确认gpio目录是否正确");
243                 return;
244             }
245 
246             var param = _pinidx + "\n";
247             unexport.writebytes(param.getbytes());
248         }
249         #endregion
250     }
251 }

 

问题1: 导出失败,请确认 pin 是否正确

问题有可能是没有权限导出。

  查看 /sys/class/gpio/export 文件所属组

  C# 控制 GPIO

  只允许 root 用户进行导出 io 口。

  需要用 root 用户运行导出函数 exportpin() 。

解决办法:  使用 root 权限运行程序  sudo xxxxx.

  或者   切换到 root 用户再执行。 su 

  注意: 一旦导出,直到关机,引脚文件都会一直存在。 即 多次运行不必每次都导出。

 

问题2: 没有控制gpio 的权限。

解决办法: 将当前用户添加到 io 用户组。或者切换到 io 用户。方法同问题1.