1# SPI<a name="ZH-CN_TOPIC_0000001053057951"></a> 2 3- [概述](#section193356154511) 4 - [接口说明](#section232141411476) 5 6- [使用指导](#section71363452477) 7 - [使用流程](#section32846814820) 8 - [获取SPI设备句柄](#section1927265711481) 9 - [获取SPI设备属性](#section541133418493) 10 - [配置SPI设备属性](#section7870106145010) 11 - [进行SPI通信](#section13324155195013) 12 - [销毁SPI设备句柄](#section19661632135117) 13 14- [使用实例](#section06541058155120) 15 16## 概述<a name="section193356154511"></a> 17 18- SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线。 19- SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信,常用于与闪存、实时时钟、传感器以及模数转换器等进行通信。 20- SPI以主从方式工作,通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连,它们分别是: 21 - SCLK – 时钟信号,由主设备产生; 22 - MOSI – 主设备数据输出,从设备数据输入; 23 - MISO – 主设备数据输入,从设备数据输出; 24 - CS – 片选,从设备使能信号,由主设备控制。 25 26 27- 一个主设备和两个从设备的连接示意图如[图1](#fig15227181812587)所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 28 29**图 1** SPI主从设备连接示意图。<a name="fig15227181812587"></a> 30 31 32 33 34- SPI通信通常由主设备发起,通过以下步骤完成一次通信: 35 361. 通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。 372. 通过SCLK给选中的从设备提供时钟信号。 383. 基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。 39 40- 根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式: 41 - CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。 42 - CPOL=0,CPHA=1 时钟信号idle状态为低电平,第二个时钟边沿采样数据。 43 - CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。 44 - CPOL=1,CPHA=1 时钟信号idle状态为高电平,第二个时钟边沿采样数据。 45 46 47- SPI接口定义了操作SPI设备的通用方法集合,包括: 48 - SPI设备句柄获取和释放。 49 - SPI读写: 从SPI设备读取或写入指定长度数据。 50 - SPI自定义传输:通过消息传输结构体执行任意读写组合过程。 51 - SPI设备配置:获取和设置SPI设备属性。 52 53 54> **说明:** 55>当前只支持主机模式,不支持从机模式。 56 57### 接口说明<a name="section232141411476"></a> 58 59**表 1** SPI驱动API接口功能介绍 60 61<a name="table1731550155318"></a> 62<table><thead align="left"><tr id="row4419501537"><th class="cellrowborder" align="left" valign="top" width="20.857914208579142%" id="mcps1.2.4.1.1"><p id="p641050105320"><a name="p641050105320"></a><a name="p641050105320"></a>功能分类</p> 63</th> 64<th class="cellrowborder" align="left" valign="top" width="23.36766323367663%" id="mcps1.2.4.1.2"><p id="p54150165315"><a name="p54150165315"></a><a name="p54150165315"></a>接口名</p> 65</th> 66<th class="cellrowborder" align="left" valign="top" width="55.77442255774422%" id="mcps1.2.4.1.3"><p id="p941150145313"><a name="p941150145313"></a><a name="p941150145313"></a>描述</p> 67</th> 68</tr> 69</thead> 70<tbody><tr id="row1651292212306"><td class="cellrowborder" rowspan="2" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p1387414255305"><a name="p1387414255305"></a><a name="p1387414255305"></a>SPI设备句柄获取释放接口</p> 71</td> 72<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p8874825143014"><a name="p8874825143014"></a><a name="p8874825143014"></a>SpiOpen</p> 73</td> 74<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p1087432513307"><a name="p1087432513307"></a><a name="p1087432513307"></a>获取SPI设备句柄</p> 75</td> 76</tr> 77<tr id="row1429083612305"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1956614106311"><a name="p1956614106311"></a><a name="p1956614106311"></a>SpiClose</p> 78</td> 79<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p829111362306"><a name="p829111362306"></a><a name="p829111362306"></a>释放SPI设备句柄</p> 80</td> 81</tr> 82<tr id="row34145016535"><td class="cellrowborder" rowspan="3" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>SPI读写接口</p> 83</td> 84<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p19389143041518"><a name="p19389143041518"></a><a name="p19389143041518"></a>SpiRead</p> 85</td> 86<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p8738101941716"><a name="p8738101941716"></a><a name="p8738101941716"></a>读取指定长度的数据</p> 87</td> 88</tr> 89<tr id="row5632152611414"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p143890309153"><a name="p143890309153"></a><a name="p143890309153"></a>SpiWrite</p> 90</td> 91<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p573815197171"><a name="p573815197171"></a><a name="p573815197171"></a>写入指定长度的数据</p> 92</td> 93</tr> 94<tr id="row1766145611414"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p183904373018"><a name="p183904373018"></a><a name="p183904373018"></a>SpiTransfer</p> 95</td> 96<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1639011313303"><a name="p1639011313303"></a><a name="p1639011313303"></a>SPI数据传输接口</p> 97</td> 98</tr> 99<tr id="row1020919129159"><td class="cellrowborder" rowspan="2" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p82092126154"><a name="p82092126154"></a><a name="p82092126154"></a>SPI设备配置接口</p> 100<p id="p6794153701111"><a name="p6794153701111"></a><a name="p6794153701111"></a></p> 101</td> 102<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p1739013012154"><a name="p1739013012154"></a><a name="p1739013012154"></a>SpiSetCfg</p> 103</td> 104<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p073910197173"><a name="p073910197173"></a><a name="p073910197173"></a>根据指定参数,配置SPI设备</p> 105</td> 106</tr> 107<tr id="row379443710118"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p4333154919111"><a name="p4333154919111"></a><a name="p4333154919111"></a>SpiGetCfg</p> 108</td> 109<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p11333649171117"><a name="p11333649171117"></a><a name="p11333649171117"></a>获取SPI设备配置参数</p> 110</td> 111</tr> 112</tbody> 113</table> 114 115> **说明:** 116>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 117 118## 使用指导<a name="section71363452477"></a> 119 120### 使用流程<a name="section32846814820"></a> 121 122使用SPI的一般流程如[图2](#fig23885455594)所示。 123 124**图 2** SPI使用流程图<a name="fig23885455594"></a> 125 126 127 128 129### 获取SPI设备句柄<a name="section1927265711481"></a> 130 131在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。 132 133DevHandle SpiOpen\(const struct SpiDevInfo \*info\); 134 135**表 2** SpiOpen参数和返回值描述 136 137<a name="table7603619123820"></a> 138<table><tbody><tr id="row1060351914386"><td class="cellrowborder" valign="top" width="50%"><p id="p14603181917382"><a name="p14603181917382"></a><a name="p14603181917382"></a><strong id="b743851872411"><a name="b743851872411"></a><a name="b743851872411"></a>参数</strong></p> 139</td> 140<td class="cellrowborder" valign="top" width="50%"><p id="p36031519183819"><a name="p36031519183819"></a><a name="p36031519183819"></a><strong id="b545016183242"><a name="b545016183242"></a><a name="b545016183242"></a>参数描述</strong></p> 141</td> 142</tr> 143<tr id="row1960431983813"><td class="cellrowborder" valign="top" width="50%"><p id="p3604719123817"><a name="p3604719123817"></a><a name="p3604719123817"></a>info</p> 144</td> 145<td class="cellrowborder" valign="top" width="50%"><p id="p1560441923818"><a name="p1560441923818"></a><a name="p1560441923818"></a>SPI设备描述符</p> 146</td> 147</tr> 148<tr id="row380484160"><td class="cellrowborder" valign="top" width="50%"><p id="p460381915385"><a name="p460381915385"></a><a name="p460381915385"></a><strong id="b209091422131617"><a name="b209091422131617"></a><a name="b209091422131617"></a>返回值</strong></p> 149</td> 150<td class="cellrowborder" valign="top" width="50%"><p id="p96031619153812"><a name="p96031619153812"></a><a name="p96031619153812"></a><strong id="b126401632121619"><a name="b126401632121619"></a><a name="b126401632121619"></a>返回值描述</strong></p> 151</td> 152</tr> 153<tr id="row5793818161"><td class="cellrowborder" valign="top" width="50%"><p id="p1060418195389"><a name="p1060418195389"></a><a name="p1060418195389"></a>NULL</p> 154</td> 155<td class="cellrowborder" valign="top" width="50%"><p id="p760471912388"><a name="p760471912388"></a><a name="p760471912388"></a>获取SPI设备句柄失败</p> 156</td> 157</tr> 158<tr id="row187914871618"><td class="cellrowborder" valign="top" width="50%"><p id="p5604719133811"><a name="p5604719133811"></a><a name="p5604719133811"></a>设备句柄</p> 159</td> 160<td class="cellrowborder" valign="top" width="50%"><p id="p3604181933818"><a name="p3604181933818"></a><a name="p3604181933818"></a>对应的SPI设备句柄</p> 161</td> 162</tr> 163</tbody> 164</table> 165 166假设系统中的SPI设备总线号为0,片选号为0,获取该SPI设备句柄的示例如下: 167 168``` 169struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ 170DevHandle spiHandle = NULL; /* SPI设备句柄 */ 171spiDevinfo.busNum = 0; /* SPI设备总线号 */ 172spiDevinfo.csNum = 0; /* SPI设备片选号 */ 173 174/* 获取SPI设备句柄 */ 175spiHandle = SpiOpen(&spiDevinfo); 176if (spiHandle == NULL) { 177 HDF_LOGE("SpiOpen: failed\n"); 178 return; 179} 180``` 181 182### 获取SPI设备属性<a name="section541133418493"></a> 183 184在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示: 185 186int32\_t SpiGetCfg\(DevHandle handle, struct SpiCfg \*cfg\); 187 188**表 3** SpiGetCfg参数和返回值描述 189 190<a name="table14209152141313"></a> 191<table><tbody><tr id="row1420918529133"><td class="cellrowborder" valign="top" width="50%"><p id="p42091852141314"><a name="p42091852141314"></a><a name="p42091852141314"></a><strong id="b2209135217139"><a name="b2209135217139"></a><a name="b2209135217139"></a>参数</strong></p> 192</td> 193<td class="cellrowborder" valign="top" width="50%"><p id="p202099523137"><a name="p202099523137"></a><a name="p202099523137"></a><strong id="b16209195201319"><a name="b16209195201319"></a><a name="b16209195201319"></a>参数描述</strong></p> 194</td> 195</tr> 196<tr id="row142091352171310"><td class="cellrowborder" valign="top" width="50%"><p id="p1520915529131"><a name="p1520915529131"></a><a name="p1520915529131"></a>handle</p> 197</td> 198<td class="cellrowborder" valign="top" width="50%"><p id="p720995291310"><a name="p720995291310"></a><a name="p720995291310"></a>SPI设备句柄</p> 199</td> 200</tr> 201<tr id="row6209152161314"><td class="cellrowborder" valign="top" width="50%"><p id="p720916522139"><a name="p720916522139"></a><a name="p720916522139"></a>cfg</p> 202</td> 203<td class="cellrowborder" valign="top" width="50%"><p id="p172091452131319"><a name="p172091452131319"></a><a name="p172091452131319"></a>SPI设备配置参数</p> 204</td> 205</tr> 206<tr id="row12092522139"><td class="cellrowborder" valign="top" width="50%"><p id="p18209125211134"><a name="p18209125211134"></a><a name="p18209125211134"></a><strong id="b2209155219132"><a name="b2209155219132"></a><a name="b2209155219132"></a>返回值</strong></p> 207</td> 208<td class="cellrowborder" valign="top" width="50%"><p id="p420975231318"><a name="p420975231318"></a><a name="p420975231318"></a><strong id="b4209165210132"><a name="b4209165210132"></a><a name="b4209165210132"></a>返回值描述</strong></p> 209</td> 210</tr> 211<tr id="row8209155251310"><td class="cellrowborder" valign="top" width="50%"><p id="p13210145291312"><a name="p13210145291312"></a><a name="p13210145291312"></a>0</p> 212</td> 213<td class="cellrowborder" valign="top" width="50%"><p id="p152101952141315"><a name="p152101952141315"></a><a name="p152101952141315"></a>获取配置成功</p> 214</td> 215</tr> 216<tr id="row102101452121320"><td class="cellrowborder" valign="top" width="50%"><p id="p10210175219134"><a name="p10210175219134"></a><a name="p10210175219134"></a>负数</p> 217</td> 218<td class="cellrowborder" valign="top" width="50%"><p id="p72101252101312"><a name="p72101252101312"></a><a name="p72101252101312"></a>获取配置失败</p> 219</td> 220</tr> 221</tbody> 222</table> 223 224``` 225int32_t ret; 226struct SpiCfg cfg = {0}; /* SPI配置信息*/ 227ret = SpiGetCfg(spiHandle, &cfg); /* 获取SPI设备属性 */ 228if (ret != 0) { 229 HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); 230} 231``` 232 233### 配置SPI设备属性<a name="section7870106145010"></a> 234 235在获取到SPI设备句柄之后,需要配置SPI设备属性,配置SPI设备属性的函数如下所示: 236 237int32\_t SpiSetCfg\(DevHandle handle, struct SpiCfg \*cfg\); 238 239**表 4** SpiSetCfg参数和返回值描述 240 241<a name="table219052945210"></a> 242<table><tbody><tr id="row14191192918522"><td class="cellrowborder" valign="top" width="50%"><p id="p17424155016529"><a name="p17424155016529"></a><a name="p17424155016529"></a><strong id="b13808393249"><a name="b13808393249"></a><a name="b13808393249"></a>参数</strong></p> 243</td> 244<td class="cellrowborder" valign="top" width="50%"><p id="p942512508520"><a name="p942512508520"></a><a name="p942512508520"></a><strong id="b78202962416"><a name="b78202962416"></a><a name="b78202962416"></a>参数描述</strong></p> 245</td> 246</tr> 247<tr id="row219152915524"><td class="cellrowborder" valign="top" width="50%"><p id="p2191122985218"><a name="p2191122985218"></a><a name="p2191122985218"></a>handle</p> 248</td> 249<td class="cellrowborder" valign="top" width="50%"><p id="p1519162913524"><a name="p1519162913524"></a><a name="p1519162913524"></a>SPI设备句柄</p> 250</td> 251</tr> 252<tr id="row1719110297526"><td class="cellrowborder" valign="top" width="50%"><p id="p181911292523"><a name="p181911292523"></a><a name="p181911292523"></a>cfg</p> 253</td> 254<td class="cellrowborder" valign="top" width="50%"><p id="p91911729155216"><a name="p91911729155216"></a><a name="p91911729155216"></a>SPI设备配置参数</p> 255</td> 256</tr> 257<tr id="row036524131716"><td class="cellrowborder" valign="top" width="50%"><p id="p6425165035214"><a name="p6425165035214"></a><a name="p6425165035214"></a><strong id="b61219451173"><a name="b61219451173"></a><a name="b61219451173"></a>返回值</strong></p> 258</td> 259<td class="cellrowborder" valign="top" width="50%"><p id="p18425650165215"><a name="p18425650165215"></a><a name="p18425650165215"></a><strong id="b826124514172"><a name="b826124514172"></a><a name="b826124514172"></a>返回值描述</strong></p> 260</td> 261</tr> 262<tr id="row43653411178"><td class="cellrowborder" valign="top" width="50%"><p id="p1319132918520"><a name="p1319132918520"></a><a name="p1319132918520"></a>0</p> 263</td> 264<td class="cellrowborder" valign="top" width="50%"><p id="p1719117292522"><a name="p1719117292522"></a><a name="p1719117292522"></a>配置成功</p> 265</td> 266</tr> 267<tr id="row536594171715"><td class="cellrowborder" valign="top" width="50%"><p id="p719119296522"><a name="p719119296522"></a><a name="p719119296522"></a>负数</p> 268</td> 269<td class="cellrowborder" valign="top" width="50%"><p id="p20191192925212"><a name="p20191192925212"></a><a name="p20191192925212"></a>配置失败</p> 270</td> 271</tr> 272</tbody> 273</table> 274 275``` 276int32_t ret; 277struct SpiCfg cfg = {0}; /* SPI配置信息*/ 278cfg.mode = SPI_MODE_LOOP; /* 以回环模式进行通信 */ 279cfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* 以轮询的方式进行通信 */ 280cfg.maxSpeedHz = 115200; /* 最大传输频率 */ 281cfg.bitsPerWord = 8; /* 读写位宽为8个比特 */ 282ret = SpiSetCfg(spiHandle, &cfg); /* 配置SPI设备属性 */ 283if (ret != 0) { 284 HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); 285} 286``` 287 288### 进行SPI通信<a name="section13324155195013"></a> 289 290- 向SPI设备写入指定长度的数据 291 292如果只向SPI设备写一次数据,则可以通过以下函数完成: 293 294int32\_t SpiWrite\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); 295 296**表 5** SpiWrite参数和返回值描述 297 298<a name="table1018490043"></a> 299<table><tbody><tr id="row31848013417"><td class="cellrowborder" valign="top" width="50%"><p id="p1415816132411"><a name="p1415816132411"></a><a name="p1415816132411"></a><strong id="b011110449230"><a name="b011110449230"></a><a name="b011110449230"></a>参数</strong></p> 300</td> 301<td class="cellrowborder" valign="top" width="50%"><p id="p11158111316410"><a name="p11158111316410"></a><a name="p11158111316410"></a><strong id="b18123204410230"><a name="b18123204410230"></a><a name="b18123204410230"></a>参数描述</strong></p> 302</td> 303</tr> 304<tr id="row10184701945"><td class="cellrowborder" valign="top" width="50%"><p id="p104891871157"><a name="p104891871157"></a><a name="p104891871157"></a>handle</p> 305</td> 306<td class="cellrowborder" valign="top" width="50%"><p id="p204891671156"><a name="p204891671156"></a><a name="p204891671156"></a>SPI设备句柄</p> 307</td> 308</tr> 309<tr id="row928111518418"><td class="cellrowborder" valign="top" width="50%"><p id="p4282955412"><a name="p4282955412"></a><a name="p4282955412"></a>buf</p> 310</td> 311<td class="cellrowborder" valign="top" width="50%"><p id="p7282752412"><a name="p7282752412"></a><a name="p7282752412"></a>待写入数据的指针</p> 312</td> 313</tr> 314<tr id="row149041113651"><td class="cellrowborder" valign="top" width="50%"><p id="p139051213357"><a name="p139051213357"></a><a name="p139051213357"></a>len</p> 315</td> 316<td class="cellrowborder" valign="top" width="50%"><p id="p16905313854"><a name="p16905313854"></a><a name="p16905313854"></a>待写入的数据长度</p> 317</td> 318</tr> 319<tr id="row1148818622017"><td class="cellrowborder" valign="top" width="50%"><p id="p8158313248"><a name="p8158313248"></a><a name="p8158313248"></a><strong id="b1197324122018"><a name="b1197324122018"></a><a name="b1197324122018"></a>返回值</strong></p> 320</td> 321<td class="cellrowborder" valign="top" width="50%"><p id="p161591413741"><a name="p161591413741"></a><a name="p161591413741"></a><strong id="b15219182419209"><a name="b15219182419209"></a><a name="b15219182419209"></a>返回值描述</strong></p> 322</td> 323</tr> 324<tr id="row14488762202"><td class="cellrowborder" valign="top" width="50%"><p id="p103191916578"><a name="p103191916578"></a><a name="p103191916578"></a>0</p> 325</td> 326<td class="cellrowborder" valign="top" width="50%"><p id="p1231981611712"><a name="p1231981611712"></a><a name="p1231981611712"></a>写入成功</p> 327</td> 328</tr> 329<tr id="row164881464201"><td class="cellrowborder" valign="top" width="50%"><p id="p531916166716"><a name="p531916166716"></a><a name="p531916166716"></a>负数</p> 330</td> 331<td class="cellrowborder" valign="top" width="50%"><p id="p93191161174"><a name="p93191161174"></a><a name="p93191161174"></a>写入失败</p> 332</td> 333</tr> 334</tbody> 335</table> 336 337``` 338int32_t ret; 339uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78}; 340/* 向SPI设备写入指定长度的数据 */ 341ret = SpiWrite(spiHandle, wbuff, 4); 342if (ret != 0) { 343 HDF_LOGE("SpiWrite: failed, ret %d\n", ret); 344} 345``` 346 347- 从SPI设备读取指定长度的数据 348 349如果只读取一次数据,则可以通过以下函数完成: 350 351int32\_t SpiRead\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); 352 353**表 6** SpiRead参数和返回值描述 354 355<a name="table0265191412124"></a> 356<table><tbody><tr id="row42651914141213"><td class="cellrowborder" valign="top" width="50%"><p id="p1483184123"><a name="p1483184123"></a><a name="p1483184123"></a><strong id="b81201431172318"><a name="b81201431172318"></a><a name="b81201431172318"></a>参数</strong></p> 357</td> 358<td class="cellrowborder" valign="top" width="50%"><p id="p9831871216"><a name="p9831871216"></a><a name="p9831871216"></a><strong id="b31321731122316"><a name="b31321731122316"></a><a name="b31321731122316"></a>参数描述</strong></p> 359</td> 360</tr> 361<tr id="row1926651415123"><td class="cellrowborder" valign="top" width="50%"><p id="p389183129"><a name="p389183129"></a><a name="p389183129"></a>handle</p> 362</td> 363<td class="cellrowborder" valign="top" width="50%"><p id="p168151817124"><a name="p168151817124"></a><a name="p168151817124"></a>SPI设备句柄</p> 364</td> 365</tr> 366<tr id="row202661414201220"><td class="cellrowborder" valign="top" width="50%"><p id="p158161821210"><a name="p158161821210"></a><a name="p158161821210"></a>buf</p> 367</td> 368<td class="cellrowborder" valign="top" width="50%"><p id="p98131811126"><a name="p98131811126"></a><a name="p98131811126"></a>待读取数据的指针</p> 369</td> 370</tr> 371<tr id="row1926621451212"><td class="cellrowborder" valign="top" width="50%"><p id="p2918182124"><a name="p2918182124"></a><a name="p2918182124"></a>len</p> 372</td> 373<td class="cellrowborder" valign="top" width="50%"><p id="p169718191220"><a name="p169718191220"></a><a name="p169718191220"></a>待读取的数据长度</p> 374</td> 375</tr> 376<tr id="row05841310206"><td class="cellrowborder" valign="top" width="50%"><p id="p38171818128"><a name="p38171818128"></a><a name="p38171818128"></a><strong id="b33485467201"><a name="b33485467201"></a><a name="b33485467201"></a>返回值</strong></p> 377</td> 378<td class="cellrowborder" valign="top" width="50%"><p id="p881918161220"><a name="p881918161220"></a><a name="p881918161220"></a><strong id="b13361846112013"><a name="b13361846112013"></a><a name="b13361846112013"></a>返回值描述</strong></p> 379</td> 380</tr> 381<tr id="row15584173192016"><td class="cellrowborder" valign="top" width="50%"><p id="p14871820128"><a name="p14871820128"></a><a name="p14871820128"></a>0</p> 382</td> 383<td class="cellrowborder" valign="top" width="50%"><p id="p88118101211"><a name="p88118101211"></a><a name="p88118101211"></a>读取成功</p> 384</td> 385</tr> 386<tr id="row1058418317204"><td class="cellrowborder" valign="top" width="50%"><p id="p10841817125"><a name="p10841817125"></a><a name="p10841817125"></a>负数</p> 387</td> 388<td class="cellrowborder" valign="top" width="50%"><p id="p986183127"><a name="p986183127"></a><a name="p986183127"></a>读取失败</p> 389</td> 390</tr> 391</tbody> 392</table> 393 394``` 395int32_t ret; 396uint8_t rbuff[4] = {0}; 397/* 从SPI设备读取指定长度的数据 */ 398ret = SpiRead(spiHandle, rbuff, 4); 399if (ret != 0) { 400 HDF_LOGE("SpiRead: failed, ret %d\n", ret); 401} 402``` 403 404- 自定义传输 405 406如果需要发起一次自定义传输,则可以通过以下函数完成: 407 408int32\_t SpiTransfer\(DevHandle handle, struct SpiMsg \*msgs, uint32\_t count\); 409 410**表 7** SpiTransfer参数和返回值描述 411 412<a name="table1934414174212"></a> 413<table><tbody><tr id="row1134415176216"><td class="cellrowborder" valign="top" width="50%"><p id="p13295152320217"><a name="p13295152320217"></a><a name="p13295152320217"></a><strong id="b14726194114224"><a name="b14726194114224"></a><a name="b14726194114224"></a>参数</strong></p> 414</td> 415<td class="cellrowborder" valign="top" width="50%"><p id="p1295112352115"><a name="p1295112352115"></a><a name="p1295112352115"></a><strong id="b6744541162218"><a name="b6744541162218"></a><a name="b6744541162218"></a>参数描述</strong></p> 416</td> 417</tr> 418<tr id="row5344101702113"><td class="cellrowborder" valign="top" width="50%"><p id="p19295132382111"><a name="p19295132382111"></a><a name="p19295132382111"></a>handle</p> 419</td> 420<td class="cellrowborder" valign="top" width="50%"><p id="p829510232213"><a name="p829510232213"></a><a name="p829510232213"></a>SPI设备句柄</p> 421</td> 422</tr> 423<tr id="row17344171722117"><td class="cellrowborder" valign="top" width="50%"><p id="p9295122332113"><a name="p9295122332113"></a><a name="p9295122332113"></a>msgs</p> 424</td> 425<td class="cellrowborder" valign="top" width="50%"><p id="p202951238218"><a name="p202951238218"></a><a name="p202951238218"></a>待传输数据的数组</p> 426</td> 427</tr> 428<tr id="row45812466213"><td class="cellrowborder" valign="top" width="50%"><p id="p1659246112117"><a name="p1659246112117"></a><a name="p1659246112117"></a>count</p> 429</td> 430<td class="cellrowborder" valign="top" width="50%"><p id="p259124622119"><a name="p259124622119"></a><a name="p259124622119"></a>msgs数组长度</p> 431</td> 432</tr> 433<tr id="row45187318214"><td class="cellrowborder" valign="top" width="50%"><p id="p17295142322113"><a name="p17295142322113"></a><a name="p17295142322113"></a><strong id="b6754144472117"><a name="b6754144472117"></a><a name="b6754144472117"></a>返回值</strong></p> 434</td> 435<td class="cellrowborder" valign="top" width="50%"><p id="p142959232211"><a name="p142959232211"></a><a name="p142959232211"></a><strong id="b107682446216"><a name="b107682446216"></a><a name="b107682446216"></a>返回值描述</strong></p> 436</td> 437</tr> 438<tr id="row175186313217"><td class="cellrowborder" valign="top" width="50%"><p id="p929532313211"><a name="p929532313211"></a><a name="p929532313211"></a>0</p> 439</td> 440<td class="cellrowborder" valign="top" width="50%"><p id="p829512237217"><a name="p829512237217"></a><a name="p829512237217"></a>执行成功</p> 441</td> 442</tr> 443<tr id="row1451803152114"><td class="cellrowborder" valign="top" width="50%"><p id="p12958234217"><a name="p12958234217"></a><a name="p12958234217"></a>负数</p> 444</td> 445<td class="cellrowborder" valign="top" width="50%"><p id="p1295192312112"><a name="p1295192312112"></a><a name="p1295192312112"></a>执行失败</p> 446</td> 447</tr> 448</tbody> 449</table> 450 451``` 452int32_t ret; 453uint8_t wbuff[1] = {0x12}; 454uint8_t rbuff[1] = {0}; 455struct SpiMsg msg; /* 自定义传输的消息*/ 456msg.wbuf = wbuff; /* 写入的数据 */ 457msg.rbuf = rbuff; /* 读取的数据 */ 458msg.len = 1; /* 读取、写入数据的长度都是1 */ 459msg.csChange = 1; /* 进行下一次传输前关闭片选 */ 460msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ 461msg.speed = 115200; /* 本次传输的速度 */ 462/* 进行一次自定义传输,传输的msg个数为1 */ 463ret = SpiTransfer(spiHandle, &msg, 1); 464if (ret != 0) { 465 HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); 466} 467``` 468 469### 销毁SPI设备句柄<a name="section19661632135117"></a> 470 471SPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示: 472 473void SpiClose\(DevHandle handle\); 474 475该函数会释放掉申请的资源。 476 477**表 8** SpiClose参数描述 478 479<a name="table72517953115"></a> 480<table><tbody><tr id="row1525793312"><td class="cellrowborder" valign="top" width="50%"><p id="p115402031153111"><a name="p115402031153111"></a><a name="p115402031153111"></a><strong id="b691142582513"><a name="b691142582513"></a><a name="b691142582513"></a>参数</strong></p> 481</td> 482<td class="cellrowborder" valign="top" width="50%"><p id="p65406313319"><a name="p65406313319"></a><a name="p65406313319"></a><strong id="b1892414252254"><a name="b1892414252254"></a><a name="b1892414252254"></a>参数描述</strong></p> 483</td> 484</tr> 485<tr id="row1926109193116"><td class="cellrowborder" valign="top" width="50%"><p id="p105419317318"><a name="p105419317318"></a><a name="p105419317318"></a>handle</p> 486</td> 487<td class="cellrowborder" valign="top" width="50%"><p id="p16541153110317"><a name="p16541153110317"></a><a name="p16541153110317"></a>SPI设备句柄</p> 488</td> 489</tr> 490</tbody> 491</table> 492 493``` 494SpiClose(spiHandle); /* 销毁SPI设备句柄 */ 495``` 496 497## 使用实例<a name="section06541058155120"></a> 498 499SPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。 500 501``` 502#include "hdf_log.h" 503#include "spi_if.h" 504 505void SpiTestSample(void) 506{ 507 int32_t ret; 508 struct SpiCfg cfg; /* SPI配置信息 */ 509 struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ 510 DevHandle spiHandle = NULL; /* SPI设备句柄 */ 511 struct SpiMsg msg; /* 自定义传输的消息 */ 512 uint8_t rbuff[4] = { 0 }; 513 uint8_t wbuff[4] = { 0x12, 0x34, 0x56, 0x78 }; 514 uint8_t wbuff2[4] = { 0xa1, 0xb2, 0xc3, 0xd4 }; 515 516 spiDevinfo.busNum = 0; /* SPI设备总线号 */ 517 spiDevinfo.csNum = 0; /* SPI设备片选号 */ 518 spiHandle = SpiOpen(&spiDevinfo); /* 根据spiDevinfo获取SPI设备句柄 */ 519 if (spiHandle == NULL) { 520 HDF_LOGE("SpiOpen: failed\n"); 521 return; 522 } 523 /* 获取SPI设备属性 */ 524 ret = SpiGetCfg(spiHandle, &cfg); 525 if (ret != 0) { 526 HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); 527 goto err; 528 } 529 cfg.maxSpeedHz = 115200; /* 将最大时钟频率改为115200 */ 530 cfg.bitsPerWord = 8; /* 传输位宽改为8比特 */ 531 /* 配置SPI设备属性 */ 532 ret = SpiSetCfg(spiHandle, &cfg); 533 if (ret != 0) { 534 HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); 535 goto err; 536 } 537 /* 向SPI设备写入指定长度的数据 */ 538 ret = SpiWrite(spiHandle, wbuff, 4); 539 if (ret != 0) { 540 HDF_LOGE("SpiWrite: failed, ret %d\n", ret); 541 goto err; 542 } 543 /* 从SPI设备读取指定长度的数据 */ 544 ret = SpiRead(spiHandle, rbuff, 4); 545 if (ret != 0) { 546 HDF_LOGE("SpiRead: failed, ret %d\n", ret); 547 goto err; 548 } 549 msg.wbuf = wbuff2; /* 写入的数据 */ 550 msg.rbuf = rbuff; /* 读取的数据 */ 551 msg.len = 4; /* 读取写入数据的长度为4 */ 552 msg.csChange = 1; /* 进行下一次传输前关闭片选 */ 553 msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ 554 msg.speed = 115200; /* 本次传输的速度 */ 555 /* 进行一次自定义传输,传输的msg个数为1 */ 556 ret = SpiTransfer(spiHandle, &msg, 1); 557 if (ret != 0) { 558 HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); 559 goto err; 560 } 561err: 562 /* 销毁SPI设备句柄 */ 563 SpiClose(spiHandle); 564} 565``` 566 567