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 文件所属组
只允许 root 用户进行导出 io 口。
需要用 root 用户运行导出函数 exportpin() 。
解决办法: 使用 root 权限运行程序 sudo xxxxx.
或者 切换到 root 用户再执行。 su
注意: 一旦导出,直到关机,引脚文件都会一直存在。 即 多次运行不必每次都导出。
问题2: 没有控制gpio 的权限。
解决办法: 将当前用户添加到 io 用户组。或者切换到 io 用户。方法同问题1.
下一篇: 探究分析:快速对大量的数据转换为数组