C# 控制 GPIO

控制 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 }
View Code

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

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

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

  

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

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

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

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

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

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

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

猜你喜欢

转载自www.cnblogs.com/JiuHuan/p/11740610.html