- 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 }