C# 控制 GPIO,2c


控制 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.

 

相关内容

    暂无相关文章